Compare commits
No commits in common. "19acd22c9b853c613124c355a0ffa87067ef2b1f" and "895ad08565f0c6ab4183e18862a38a7a571aaf95" have entirely different histories.
19acd22c9b
...
895ad08565
@ -1,8 +0,0 @@
|
||||
{
|
||||
"16": {
|
||||
"1": {
|
||||
"wrong": [],
|
||||
"correct": 59522422
|
||||
}
|
||||
}
|
||||
}
|
||||
38
day01.py
38
day01.py
@ -1,19 +1,6 @@
|
||||
from tools.aoc import AOCDay
|
||||
|
||||
|
||||
def get_fuel(count: int, part2: bool = False):
|
||||
if not part2:
|
||||
return count // 3 - 2
|
||||
else:
|
||||
fuel_sum = 0
|
||||
count = count // 3 - 2
|
||||
while count > 0:
|
||||
fuel_sum += count
|
||||
count = count // 3 - 2
|
||||
|
||||
return fuel_sum
|
||||
|
||||
|
||||
class Day(AOCDay):
|
||||
inputs = [
|
||||
[
|
||||
@ -31,21 +18,22 @@ class Day(AOCDay):
|
||||
]
|
||||
]
|
||||
|
||||
def get_fuel(self, part2: bool = False):
|
||||
if len(self.input) == 1:
|
||||
return get_fuel(self.getInput(int), part2)
|
||||
else:
|
||||
fuel_sum = 0
|
||||
for x in self.getInput(int):
|
||||
fuel_sum += get_fuel(x, part2)
|
||||
|
||||
return fuel_sum
|
||||
|
||||
def part1(self):
|
||||
return self.get_fuel()
|
||||
fuel_sum = 0
|
||||
for x in self.getInputListAsType(int):
|
||||
fuel_sum += x // 3 - 2
|
||||
|
||||
return fuel_sum
|
||||
|
||||
def part2(self):
|
||||
return self.get_fuel(True)
|
||||
fuel_sum = 0
|
||||
for x in self.getInputListAsType(int):
|
||||
fuel_add = x // 3 - 2
|
||||
while fuel_add > 0:
|
||||
fuel_sum += fuel_add
|
||||
fuel_add = fuel_add // 3 - 2
|
||||
|
||||
return fuel_sum
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
6
day07.py
6
day07.py
@ -7,7 +7,7 @@ from typing import Any, List
|
||||
def get_comps(memory: List[int]) -> List[IntCode]:
|
||||
comps = []
|
||||
for _ in range(5):
|
||||
comps.append(IntCode(memory))
|
||||
comps.append(IntCode(memory.copy()))
|
||||
|
||||
return comps
|
||||
|
||||
@ -41,7 +41,7 @@ class Day(AOCDay):
|
||||
|
||||
comps[i].addInput(input1)
|
||||
comps[i].addInput(input2)
|
||||
comps[i].start()
|
||||
comps[i].run()
|
||||
|
||||
signal = comps[4].getOutput()
|
||||
if signal > max_signal:
|
||||
@ -54,7 +54,7 @@ class Day(AOCDay):
|
||||
max_signal = 0
|
||||
phase_settings = [5, 6, 7, 8, 9]
|
||||
for s in itertools.permutations(phase_settings):
|
||||
comps = get_comps(init_memory)
|
||||
comps = get_comps(init_memory.copy())
|
||||
|
||||
for i, input1 in enumerate(s):
|
||||
if i == 0 and not comps[i].isRunning():
|
||||
|
||||
10
day08.py
10
day08.py
@ -1,5 +1,4 @@
|
||||
from tools.aoc import AOCDay
|
||||
from tools.aoc_ocr import convert_6
|
||||
from typing import Any
|
||||
|
||||
|
||||
@ -9,7 +8,7 @@ class Day(AOCDay):
|
||||
(2806, "input08")
|
||||
],
|
||||
[
|
||||
("ZBJAB", "input08")
|
||||
("see image above", "input08")
|
||||
]
|
||||
]
|
||||
|
||||
@ -58,11 +57,14 @@ class Day(AOCDay):
|
||||
while layers[z][y][x] == "2":
|
||||
z += 1
|
||||
|
||||
line += "." if layers[z][y][x] == "0" else "#"
|
||||
line += " " if layers[z][y][x] == "0" else "#"
|
||||
|
||||
rows.append(line)
|
||||
|
||||
return convert_6("\n".join(rows))
|
||||
for x in rows:
|
||||
print(x)
|
||||
|
||||
return "see image above"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
20
day11.py
20
day11.py
@ -1,7 +1,7 @@
|
||||
from intcode import IntCode
|
||||
from tools.aoc import AOCDay
|
||||
from tools.coordinate import Coordinate
|
||||
from tools.grid import Grid
|
||||
from tools.grid import Grid, GridTransformation
|
||||
from typing import Any
|
||||
|
||||
MOVEMENTS = [Coordinate(0, -1), Coordinate(1, 0), Coordinate(0, 1), Coordinate(-1, 0)]
|
||||
@ -13,7 +13,7 @@ class Day(AOCDay):
|
||||
(2373, "input11")
|
||||
],
|
||||
[
|
||||
("PCKRLPUK", "input11")
|
||||
("see image above", "input11")
|
||||
]
|
||||
]
|
||||
|
||||
@ -24,12 +24,12 @@ class Day(AOCDay):
|
||||
hull = Grid()
|
||||
face = 0
|
||||
pos = Coordinate(0, 0)
|
||||
painted = set()
|
||||
painted = {}
|
||||
|
||||
while not comp.isHalted():
|
||||
comp.addInput(int(hull.isSet(pos)))
|
||||
comp.addInput(hull.isSet(pos))
|
||||
hull.set(pos, comp.getOutput())
|
||||
painted.add(pos)
|
||||
painted[pos] = True
|
||||
face += 1 if comp.getOutput() else -1
|
||||
pos = pos + MOVEMENTS[face % 4]
|
||||
|
||||
@ -50,7 +50,15 @@ class Day(AOCDay):
|
||||
face += 1 if comp.getOutput() else -1
|
||||
pos = pos + MOVEMENTS[face % 4]
|
||||
|
||||
return hull.get_aoc_ocr_string(x_shift=1)
|
||||
hull.transform(GridTransformation.ROTATE_RIGHT)
|
||||
hull.transform(GridTransformation.FLIP_HORIZONTALLY)
|
||||
for x in range(hull.minX, hull.maxX + 1):
|
||||
for y in range(hull.minY, hull.maxY + 1):
|
||||
print("#" if hull.isSet(Coordinate(x, y)) else " ", end="")
|
||||
|
||||
print()
|
||||
|
||||
return "see image above"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
37
day12.py
37
day12.py
@ -20,20 +20,10 @@ class Moon:
|
||||
self.y = y
|
||||
self.z = z
|
||||
|
||||
def getKineticEnergy(self):
|
||||
return abs(self.vel_x) + abs(self.vel_y) + abs(self.vel_z)
|
||||
|
||||
def getPotentialEnergy(self):
|
||||
return abs(self.x) + abs(self.y) + abs(self.z)
|
||||
|
||||
def getEnergy(self):
|
||||
return self.getPotentialEnergy() * self.getKineticEnergy()
|
||||
|
||||
def __str__(self):
|
||||
return "x=%3d y=%3d z=%3d" % (self.x, self.y, self.z)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
potential = abs(self.x) + abs(self.y) + abs(self.z)
|
||||
kinetic = abs(self.vel_x) + abs(self.vel_y) + abs(self.vel_z)
|
||||
return potential * kinetic
|
||||
|
||||
|
||||
def moveMoons(moons: List[Moon]):
|
||||
@ -60,7 +50,7 @@ class Day(AOCDay):
|
||||
(12644, "input12")
|
||||
],
|
||||
[
|
||||
(2772, "test_input12"),
|
||||
# ??? (2772, "test_input12"),
|
||||
(4686774924, "test_input12_2"),
|
||||
(None, "input12")
|
||||
]
|
||||
@ -76,20 +66,21 @@ class Day(AOCDay):
|
||||
|
||||
def part2(self) -> Any:
|
||||
moons = [Moon(*map(int, findall(scanline_regex, line)[0])) for line in self.getInput()]
|
||||
init_moons = [Moon(*map(int, findall(scanline_regex, line)[0])) for line in self.getInput()]
|
||||
vel_0_pos = [0] * len(moons)
|
||||
|
||||
init_moons = moons.copy()
|
||||
vel_0_pos = [0, 0, 0, 0]
|
||||
moveCounter = 0
|
||||
while 0 in vel_0_pos:
|
||||
#while 0 in vel_0_pos:
|
||||
for bla in range(3000):
|
||||
moveCounter += 1
|
||||
moveMoons(moons)
|
||||
for i, m in enumerate(moons):
|
||||
if m.x == init_moons[i].x and m.y == init_moons[i].y and m.z == init_moons[i].z:
|
||||
# if i == 1:
|
||||
# print("init pos:", i, "after", moveCounter, "moves =>", m.getPotentialEnergy(), m.getKineticEnergy())
|
||||
if m.getKineticEnergy() == 0:
|
||||
print("init state:", i, "after", moveCounter, "moves =>", m.getPotentialEnergy())
|
||||
vel_0_pos[i] = moveCounter
|
||||
if m.x == init_moons[i].x and m.y == init_moons[i].y and m.z == init_moons[i].z and m.vel_x == 0 and m.vel_y == 0 and m.vel_z == 0:
|
||||
print(i, moveCounter)
|
||||
if (vel_0_pos[i] == 0 or vel_0_pos[i] > moveCounter - vel_0_pos[i]) and m.vel_x == 0 and m.vel_y == 0 and m.vel_z == 0:
|
||||
vel_0_pos[i] = moveCounter - vel_0_pos[i]
|
||||
|
||||
print(vel_0_pos)
|
||||
return lcm(*vel_0_pos)
|
||||
|
||||
|
||||
|
||||
91
day15.py
91
day15.py
@ -1,4 +1,3 @@
|
||||
from collections import deque
|
||||
from intcode import IntCode
|
||||
from tools.aoc import AOCDay
|
||||
from tools.coordinate import Coordinate
|
||||
@ -7,78 +6,58 @@ from typing import Any
|
||||
|
||||
|
||||
MOVEMENTS = [Coordinate(0, -1), Coordinate(0, 1), Coordinate(-1, 0), Coordinate(1, 0)]
|
||||
OXYGEN_POS = None
|
||||
|
||||
|
||||
def discover(comp: IntCode, grid: Grid, pos: Coordinate, visited: set = None) -> Grid:
|
||||
global OXYGEN_POS
|
||||
|
||||
if visited is None:
|
||||
visited = set()
|
||||
|
||||
visited.add(pos)
|
||||
|
||||
for m in range(4):
|
||||
next_pos = pos + MOVEMENTS[m]
|
||||
if next_pos in visited:
|
||||
continue
|
||||
|
||||
comp.addInput(m + 1)
|
||||
outcome = comp.getOutput()
|
||||
if outcome == 0:
|
||||
grid.set(next_pos)
|
||||
else:
|
||||
if outcome == 2:
|
||||
OXYGEN_POS = next_pos
|
||||
grid = discover(comp, grid, next_pos, visited)
|
||||
comp.addInput(MOVEMENTS.index(MOVEMENTS[m].reverse()) + 1)
|
||||
comp.getOutput() # just ignore one to keep the queue clear
|
||||
|
||||
return grid
|
||||
|
||||
|
||||
class Day(AOCDay):
|
||||
inputs = [
|
||||
[
|
||||
(354, "input15")
|
||||
(None, "input15")
|
||||
],
|
||||
[
|
||||
(370, "input15")
|
||||
(None, "input15")
|
||||
]
|
||||
]
|
||||
|
||||
def get_grid(self) -> Grid:
|
||||
def part1(self) -> Any:
|
||||
comp = IntCode(self.getInputAsArraySplit(",", int))
|
||||
comp.start()
|
||||
pos = Coordinate(0, 0)
|
||||
grid = discover(comp, Grid(), pos)
|
||||
comp.stop()
|
||||
return grid
|
||||
ox_pos = None
|
||||
area = Grid()
|
||||
while ox_pos is None:
|
||||
madeMove = Coordinate(0, 0)
|
||||
for i, move in enumerate(MOVEMENTS):
|
||||
if not area.isSet(pos + move):
|
||||
print("Trying to move to", pos + move)
|
||||
comp.addInput(i + 1)
|
||||
madeMove = move
|
||||
break
|
||||
|
||||
reply = comp.getOutput()
|
||||
print("comp replied with", reply)
|
||||
if reply == 0:
|
||||
area.set(pos + madeMove)
|
||||
elif reply == 1:
|
||||
pos += madeMove
|
||||
else:
|
||||
ox_pos = pos + madeMove
|
||||
|
||||
for y in range(area.minY, area.maxY + 1):
|
||||
for x in range(area.minX, area.maxX + 1):
|
||||
if area.isSet(Coordinate(x, y)):
|
||||
print("#", end="")
|
||||
else:
|
||||
print(" ", end="")
|
||||
|
||||
print()
|
||||
|
||||
print("Oxygen System found at", ox_pos)
|
||||
|
||||
def part1(self) -> Any:
|
||||
return len(self.get_grid().getPath(Coordinate(0, 0), OXYGEN_POS, includeDiagonal=False, walls=[True])) - 1
|
||||
|
||||
def part2(self) -> Any:
|
||||
grid = self.get_grid()
|
||||
queue = deque()
|
||||
queue.append(OXYGEN_POS)
|
||||
grid.set(OXYGEN_POS, 2)
|
||||
count = 0
|
||||
|
||||
while queue:
|
||||
count += 1
|
||||
next_queue = deque()
|
||||
for pos in queue:
|
||||
for next_pos in grid.getNeighboursOf(pos, includeDefault=True, includeDiagonal=False):
|
||||
if grid.get(next_pos) is False:
|
||||
next_queue.append(next_pos)
|
||||
grid.set(next_pos, 2)
|
||||
|
||||
queue = next_queue
|
||||
|
||||
return count - 1
|
||||
return ""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
day = Day(2019, 15)
|
||||
day = Day(15)
|
||||
day.run(verbose=True)
|
||||
|
||||
61
intcode.py
61
intcode.py
@ -1,33 +1,35 @@
|
||||
import threading
|
||||
from collections import defaultdict
|
||||
from queue import Queue, Empty
|
||||
from enum import Enum
|
||||
from typing import List
|
||||
from queue import Queue
|
||||
from typing import List, Union
|
||||
|
||||
|
||||
class IntCodeState(Enum):
|
||||
INITIALIZED = 0
|
||||
RUNNING = 1
|
||||
HALTED = 2
|
||||
STOPPED = 3
|
||||
|
||||
|
||||
class IntCode(threading.Thread):
|
||||
def __init__(self, memory: List[int]):
|
||||
super().__init__()
|
||||
self.instr_ptr = 0
|
||||
self.memory = defaultdict(int)
|
||||
for i, v in enumerate(memory):
|
||||
self.memory[i] = v
|
||||
self.memory = memory
|
||||
self.input_queue = Queue()
|
||||
self.output_queue = Queue()
|
||||
self.state = IntCodeState.INITIALIZED
|
||||
self.relative_base = 0
|
||||
|
||||
def getMemoryValue(self, address: int) -> int:
|
||||
return int(self.memory[address])
|
||||
if address > len(self.memory) - 1:
|
||||
self.memory.extend([0] * (address - len(self.memory) + 1))
|
||||
|
||||
return self.memory[address]
|
||||
|
||||
def setMemoryValue(self, address: int, value: int):
|
||||
if address > len(self.memory) - 1:
|
||||
self.memory.extend([0] * (address - len(self.memory) + 1))
|
||||
|
||||
self.memory[address] = value
|
||||
|
||||
def getParameterValue(self, address: int, mode: int = 0) -> int:
|
||||
@ -50,42 +52,30 @@ class IntCode(threading.Thread):
|
||||
def isHalted(self):
|
||||
return self.state == IntCodeState.HALTED
|
||||
|
||||
def isStopped(self):
|
||||
return self.state == IntCodeState.STOPPED
|
||||
|
||||
def _get_from_queue(self, queue: Queue, count: int = 1, timeout: int = 3) -> int | List[int] | None:
|
||||
try:
|
||||
if count == 1:
|
||||
return queue.get(timeout=timeout)
|
||||
else:
|
||||
return [queue.get(timeout=timeout) for _ in range(count)]
|
||||
except Empty as e:
|
||||
if self.state == IntCodeState.STOPPED:
|
||||
return None
|
||||
else:
|
||||
raise e
|
||||
def sendOutputTo(self, target_queue: Queue):
|
||||
self.output_queue = target_queue
|
||||
|
||||
def addInput(self, value: int):
|
||||
self.input_queue.put(value)
|
||||
|
||||
def addOutput(self, value: int):
|
||||
self.output_queue.put(value)
|
||||
|
||||
def hasOutput(self):
|
||||
return self.output_queue.qsize() > 0
|
||||
|
||||
def getOutput(self, count: int = 1, timeout: int = 3) -> int | List[int] | None:
|
||||
return self._get_from_queue(self.output_queue, count, timeout)
|
||||
def getOutput(self, count: int = 1, block: bool = True, timeout: int = None) -> Union[int, List[int]]:
|
||||
if count == 1:
|
||||
res = self.output_queue.get(block=block, timeout=timeout)
|
||||
self.output_queue.task_done()
|
||||
else:
|
||||
res = []
|
||||
for _ in range(count):
|
||||
res.append(self.output_queue.get(block=block, timeout=timeout))
|
||||
self.output_queue.task_done()
|
||||
|
||||
def getInput(self, count: int = 1, timeout: int = 3) -> int | List[int] | None:
|
||||
return self._get_from_queue(self.input_queue, count, timeout)
|
||||
|
||||
def stop(self):
|
||||
self.state = IntCodeState.STOPPED
|
||||
return res
|
||||
|
||||
def run(self):
|
||||
self.state = IntCodeState.RUNNING
|
||||
while not self.isHalted() and not self.isStopped():
|
||||
while not self.isHalted():
|
||||
instr = self.getMemoryValue(self.instr_ptr)
|
||||
op_code = instr % 100
|
||||
p1_mode = instr // 100 % 10
|
||||
@ -106,10 +96,11 @@ class IntCode(threading.Thread):
|
||||
self.instr_ptr += 4
|
||||
elif op_code == 3: # input
|
||||
target_addr = self.getTargetAddress(self.instr_ptr + 1, p1_mode)
|
||||
self.setMemoryValue(target_addr, self.getInput())
|
||||
self.setMemoryValue(target_addr, self.input_queue.get(timeout=30))
|
||||
self.input_queue.task_done()
|
||||
self.instr_ptr += 2
|
||||
elif op_code == 4: # output
|
||||
self.addOutput(self.getParameterValue(self.instr_ptr + 1, p1_mode))
|
||||
self.output_queue.put(self.getParameterValue(self.instr_ptr + 1, p1_mode))
|
||||
self.instr_ptr += 2
|
||||
elif op_code == 5: # jump-if-true
|
||||
if self.getParameterValue(self.instr_ptr + 1, p1_mode) != 0:
|
||||
|
||||
@ -10,8 +10,8 @@ import webbrowser
|
||||
|
||||
YEAR = 2019
|
||||
CHARMS = {
|
||||
'Linux': '~/bin/charm',
|
||||
'Windows': r'C:\Program Files\JetBrains\PyCharm 2020.2.4\bin\pycharm64.exe'
|
||||
'Linux': '/usr/local/bin/charm',
|
||||
'Windows': r'C:\somewhere\pycharm64.exe'
|
||||
}
|
||||
|
||||
arg_parser = ArgumentParser()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user