Compare commits

..

No commits in common. "19acd22c9b853c613124c355a0ffa87067ef2b1f" and "895ad08565f0c6ab4183e18862a38a7a571aaf95" have entirely different histories.

9 changed files with 113 additions and 162 deletions

View File

@ -1,8 +0,0 @@
{
"16": {
"1": {
"wrong": [],
"correct": 59522422
}
}
}

View File

@ -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:
def part1(self):
fuel_sum = 0
for x in self.getInput(int):
fuel_sum += get_fuel(x, part2)
for x in self.getInputListAsType(int):
fuel_sum += x // 3 - 2
return fuel_sum
def part1(self):
return self.get_fuel()
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__':

View File

@ -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():

View File

@ -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__':

View File

@ -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__':

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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()