Compare commits

..

9 Commits

Author SHA1 Message Date
michal 69fe5ef070 Add day 10 solution 2022-12-10 20:51:47 +01:00
michal 407ff5c036 Add day 9 solution 2022-12-10 20:12:54 +01:00
michal fc35818fd4 Add day 8 solution 2022-12-10 19:21:07 +01:00
michal 786be99a7a Add day 7 solution 2022-12-10 18:09:57 +01:00
michal 389e5faed2 'optimize' day 6 2022-12-06 09:59:07 +01:00
michal 314b38e25c Add day 6 solution 2022-12-06 09:53:42 +01:00
michal f485dad5e9 Add day 5 solution 2022-12-05 10:15:22 +01:00
michal 2aa9a6fcdc Add day 4 solution 2022-12-04 12:46:36 +01:00
michal 03233a6710 Add day 3 solution 2022-12-04 10:50:07 +01:00
21 changed files with 699 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
+46
View File
@@ -0,0 +1,46 @@
import fileinput
from typing import Iterable
def letter_to_priority(i: str) -> int:
i = ord(i)
return (i & 0b11111) + (~((i & 0b00100000) >> 5) & 1) * 26
def compartment(items: str) -> int:
field = 0
for item in items:
field |= 1 << (letter_to_priority(item) - 1)
return field
def bitmap_to_priority(field: int) -> int:
for idx in range(52):
if field & 0b1:
return idx + 1
else:
field >>= 1
def solve(lines: Iterable[str]) -> int:
score = 0
for line in map(lambda x: x.strip(), lines):
items = len(line)
lh = compartment(line[:items//2])
rh = compartment(line[items//2:])
score += bitmap_to_priority(lh & rh)
return score
def solveb(lines: Iterable[str]) -> int:
score = 0
iterator = map(lambda x: x.strip(), lines.__iter__())
for first in iterator:
second = next(iterator)
third = next(iterator)
score += bitmap_to_priority(compartment(first) & compartment(second) & compartment(third))
return score
if __name__ == "__main__":
print(solve(fileinput.input()))
print(solveb(fileinput.input()))
+39
View File
@@ -0,0 +1,39 @@
import fileinput
from typing import Iterable
class Range:
rmin: int
rmax: int
length: int
def __init__(self, rang: str):
self.rmin,self.rmax = map(lambda x: int(x), rang.strip().split('-'))
self.length = self.rmax - self.rmin + 1
def solve(lines: Iterable[str]) -> int:
score = 0
for line in lines:
elf1, elf2 = map(lambda x: Range(x), line.strip().split(','))
if elf2.length > elf1.length:
elf2,elf1 = (elf1, elf2)
if elf1.rmin <= elf2.rmin and elf1.rmax >= elf2.rmax:
score += 1
return score
def solveb(lines: Iterable[str]) -> int:
score = 0
for line in lines:
elf1, elf2 = map(lambda x: Range(x), line.strip().split(','))
if elf2.length > elf1.length:
elf2,elf1 = (elf1, elf2)
if elf1.rmin <= elf2.rmax and elf1.rmax >= elf2.rmin:
score += 1
return score
if __name__ == "__main__":
print(solve(fileinput.input()))
print(solveb(fileinput.input()))
+6
View File
@@ -0,0 +1,6 @@
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
+74
View File
@@ -0,0 +1,74 @@
import fileinput
from typing import Iterable,List
class Puzzle:
stacks: List[List[str]]
instructions: List[str]
def __init__(self):
self.stacks = []
self.instructions = []
def parse(lines: Iterable[str]) -> Puzzle:
count = None
stage = 0
puzzle = Puzzle()
for line in map(lambda x: x.replace('\n',''), lines):
if count is None: # Figure out how many stacks
count = len(line)//4 + 1
for _ in range(count):
puzzle.stacks.append([])
#puzzle.stacks = [[]]*count
if stage == 0:
if '[' not in line:
stage = 1
continue
chars = [line[i*4+1:i*4+2] for i in range(count)]
for idx in range(count):
if chars[idx] != ' ':
puzzle.stacks[idx].append(chars[idx])
elif stage == 1:
stage = 2
elif stage == 2:
puzzle.instructions.append(line)
for idx in range(count):
puzzle.stacks[idx] = puzzle.stacks[idx][::-1]
return puzzle
def solve(p: Puzzle) -> str:
for ins in p.instructions:
_, cnt, _, fr, _, to = ins.split(' ')
cnt = int(cnt)
fr = int(fr)
to = int(to)
for _ in range(cnt):
p.stacks[to-1].append(p.stacks[fr-1].pop())
out = ''
for st in p.stacks:
out += st[-1]
return out
def solveb(p: Puzzle) -> str:
for ins in p.instructions:
_, cnt, _, fr, _, to = ins.split(' ')
cnt = int(cnt)
fr = int(fr)
to = int(to)
load = []
for _ in range(cnt):
load.append(p.stacks[fr-1].pop())
load = load[::-1]
p.stacks[to-1] += load
out = ''
for st in p.stacks:
out += st[-1]
return out
if __name__ == "__main__":
puzzle = parse(fileinput.input())
print(solve(puzzle))
puzzle = parse(fileinput.input())
print(solveb(puzzle))
+9
View File
@@ -0,0 +1,9 @@
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
+1
View File
@@ -0,0 +1 @@
mjqjpqmgbljsphdztnvjfqwrcgsmlb
+1
View File
@@ -0,0 +1 @@
bvwbjplbgvbhsrlpgdmjqwftvncz
+1
View File
@@ -0,0 +1 @@
nppdvjthqldpwncqszvftbrmjlhg
+1
View File
@@ -0,0 +1 @@
nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg
+1
View File
@@ -0,0 +1 @@
zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw
+14
View File
@@ -0,0 +1,14 @@
import fileinput
from typing import Iterable
def solve(data: str, length: int = 4) -> int:
for idx in range(len(data)):
if len(set(list(data[idx:idx+length]))) == length:
return idx + length
if __name__ == "__main__":
with fileinput.input() as f:
data = f.readline()
print(solve(data, 4))
print(solve(data, 14))
+23
View File
@@ -0,0 +1,23 @@
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
+77
View File
@@ -0,0 +1,77 @@
import fileinput
from typing import Iterable, Optional
class Directory():
def __init__(self, parent = None):
self.dirs = {}
self.files = {}
self.parent = parent
def get_size(self) -> int:
return sum(self.files.values()) + sum([d.get_size() for d in self.dirs.values()])
def print_tree(self, depth = 0):
if depth == 0:
print("/")
for d, v in self.dirs.items():
print(" "*(depth+1) + d)
v.print_tree(depth+1)
for f, size in self.files.items():
print(" "*(depth+1) + f + " " + str(size))
def walk(self):
output = [self]
for d in self.dirs.values():
output += d.walk()
return output
def parse(lines: Iterable[str]) -> Directory:
root = None
cwd = None
for line in map(lambda x: x.strip(), lines):
if line.startswith("$ "): # command
if line == "$ cd /":
root = Directory()
cwd = root
elif line == "$ cd ..":
cwd = cwd.parent
elif line.startswith("$ cd"):
cwd = cwd.dirs[line.split(" ")[2]]
elif line.startswith("$ ls"):
pass
elif line.startswith("dir "): # dir
name = line.split(' ')[1]
cwd.dirs[name] = Directory(cwd)
else: # file
size, name = line.split(' ')
cwd.files[name] = int(size)
return root
def solve(lines: Iterable[str]) -> int:
root = parse(lines)
output = 0
for d in root.walk():
size = d.get_size()
if size <= 100000:
output += size
return output
def solveb(lines: Iterable[str]) -> int:
TOTAL = 70000000
GOAL = 30000000
root = parse(lines)
current = root.get_size()
free = TOTAL - current
to_free = GOAL - free
print(f"Current: {current}")
print(f"To free: {to_free}")
candidates = [d for d in root.walk() if d.get_size() >= to_free]
return min(map(lambda x: x.get_size(), candidates))
if __name__ == "__main__":
parse(fileinput.input()).print_tree()
print(solve(fileinput.input()))
print(solveb(fileinput.input()))
+6
View File
@@ -0,0 +1,6 @@
30373
25512
65332
33549
35390
+113
View File
@@ -0,0 +1,113 @@
import fileinput
def get_row(m, idx):
return m[idx]
def get_col(m, idx):
return list(map(lambda x: x[idx], m))
class Forest:
def __init__(self, width, height):
self.visible = []
self.heightmap = []
self.score = []
self.width = width
for _ in range(height):
self.visible.append([False] * width)
self.heightmap.append([0] * width)
self.score.append([0] * width)
def print(self):
print("Heightmap:")
for r in self.heightmap:
print(''.join(map(lambda x: str(x), r)))
print("Visibility:")
for r in self.visible:
print(''.join(map(lambda x: "X" if x else "O", r)))
def solve_visibility(self):
# TOP-DOWN
limit = [-1] * self.width
for rowidx in range(self.width):
for colidx in range(self.width):
if limit[colidx] < self.heightmap[rowidx][colidx]:
self.visible[rowidx][colidx] = True
limit[colidx] = self.heightmap[rowidx][colidx]
# BOT-UP
limit = [-1] * self.width
for rowidx in range(self.width):
for colidx in range(self.width):
if limit[colidx] < self.heightmap[-rowidx-1][colidx]:
self.visible[-rowidx-1][colidx] = True
limit[colidx] = self.heightmap[-rowidx-1][colidx]
# LEFT-RIGHT
limit = [-1] * self.width
for colidx in range(self.width):
for rowidx in range(self.width):
if limit[rowidx] < self.heightmap[rowidx][colidx]:
self.visible[rowidx][colidx] = True
limit[rowidx] = self.heightmap[rowidx][colidx]
# RIGHT-LEFT
limit = [-1] * self.width
for colidx in range(self.width):
for rowidx in range(self.width):
if limit[rowidx] < self.heightmap[rowidx][-colidx-1]:
self.visible[rowidx][-colidx-1] = True
limit[rowidx] = self.heightmap[rowidx][-colidx-1]
def solve_score(self):
for rowidx in range(self.width):
for colidx in range(self.width):
current = self.heightmap[rowidx][colidx]
lscore = 0
rscore = 0
uscore = 0
dscore = 0
for idx in range(colidx): # left
lscore += 1
if self.heightmap[rowidx][colidx-idx-1] >= current:
break
for idx in range(self.width - colidx - 1): # right
rscore += 1
if self.heightmap[rowidx][colidx+idx+1] >= current:
break
for idx in range(rowidx): # up
uscore += 1
if self.heightmap[rowidx-idx-1][colidx] >= current:
break
for idx in range(self.width - rowidx - 1): # down
dscore += 1
if self.heightmap[rowidx+idx+1][colidx] >= current:
break
self.score[rowidx][colidx] = lscore*rscore*uscore*dscore
@classmethod
def parse(cls, lines):
output = None
idx = 0
for line in map(lambda x: x.strip(), lines):
if line != "":
if output is None:
output = cls(len(line), len(line))
output.heightmap[idx] = list(map(lambda x: int(x), list(line)))
idx += 1
return output
def visible_count(self):
output = 0
for r in self.visible:
output += sum(r)
return output
if __name__ == "__main__":
forest = Forest.parse(fileinput.input())
forest.solve_visibility()
forest.solve_score()
forest.print()
print(f"Visible: {forest.visible_count()}")
print(f"Score: {max([max(row) for row in forest.score])}")
+8
View File
@@ -0,0 +1,8 @@
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2
+8
View File
@@ -0,0 +1,8 @@
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20
+77
View File
@@ -0,0 +1,77 @@
import fileinput
class Rope:
def __init__(self):
self.head = [0,0]
self.tail = [0,0]
self.visited = set([tuple(self.tail)])
def chatchup(self):
if max(abs(self.head[0] - self.tail[0]), abs(self.head[1] - self.tail[1])) <= 1: # Same pos or next to each other
pass
else:
if self.head[1] > self.tail[1]:
self.tail[1] += 1
elif self.head[1] < self.tail[1]:
self.tail[1] -= 1
if self.head[0] > self.tail[0]:
self.tail[0] += 1
elif self.head[0] < self.tail[0]:
self.tail[0] -= 1
self.visited.add(tuple(self.tail))
def step(self, d, count):
if d == "U":
self.head[1] += 1
elif d == "D":
self.head[1] -= 1
elif d == "L":
self.head[0] += 1
elif d == "R":
self.head[0] -= 1
self.chatchup()
if count > 1:
self.step(d, count-1)
class LongRope:
def __init__(self):
self.ropes = []
for _ in range(9):
self.ropes.append(Rope())
def step(self, d, count):
if d == "U":
self.ropes[0].head[1] += 1
elif d == "D":
self.ropes[0].head[1] -= 1
elif d == "L":
self.ropes[0].head[0] += 1
elif d == "R":
self.ropes[0].head[0] -= 1
self.ropes[0].chatchup()
for idx in range(1, len(self.ropes)):
self.ropes[idx].head = self.ropes[idx-1].tail
self.ropes[idx].chatchup()
if count > 1:
self.step(d,count-1)
def solve(lines):
rope = Rope()
for d, count in map(lambda x: x.split(' '), filter(lambda x: x != "", map(lambda x: x.strip(), lines))):
count = int(count)
rope.step(d, count)
return len(rope.visited)
def solveb(lines):
rope = LongRope()
for d, count in map(lambda x: x.split(' '), filter(lambda x: x != "", map(lambda x: x.strip(), lines))):
count = int(count)
rope.step(d, count)
return len(rope.ropes[-1].visited)
if __name__ == "__main__":
print(f"Visited {solve(fileinput.input())}")
print(f"Visited long {solveb(fileinput.input())}")
+42
View File
@@ -0,0 +1,42 @@
import fileinput
class CPU:
def __init__(self):
self.reg_x = 1
self.cycle = 0
def draw(self):
pos = self.cycle - 1
if pos % 40 == 0 and pos != 0:
print('')
print("#" if abs((pos % 40) - self.reg_x) <= 1 else ".", end='')
if self.cycle == 240:
print("")
def exec(self, instructions, breaks=[]):
for instruction in instructions:
# print(f"Start cycle {self.cycle:3d}: begin executing {instruction}")
if instruction == "noop":
self.cycle += 1
if self.cycle in breaks:
yield self.cycle*self.reg_x
self.draw()
elif instruction.startswith("addx"):
self.cycle += 1
if self.cycle in breaks:
yield self.cycle*self.reg_x
self.draw()
self.cycle += 1
if self.cycle in breaks:
yield self.cycle*self.reg_x
self.draw()
self.reg_x += int(instruction.split(' ')[1])
else:
print("Unknown instruction")
if __name__ == "__main__":
cpu = CPU()
print(f"Solution A: {sum(cpu.exec(filter(lambda x: x != '', map(lambda x: x.strip(), fileinput.input())), [20, 60, 100, 140, 180, 220]))}")
+146
View File
@@ -0,0 +1,146 @@
addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop