Solve 2019 day 14 and 15

This commit is contained in:
felixm 2024-08-16 19:45:10 -04:00
parent 6efa70ea51
commit f88eb14d24
6 changed files with 258 additions and 2 deletions

53
2019/d12.py Normal file
View File

@ -0,0 +1,53 @@
from lib import get_data, str_to_ints
def freeze(coords, velos):
coords = tuple(map(tuple, coords))
velos = tuple(map(tuple, velos))
return coords + velos
def part_1(data):
coords = []
velos = []
for line in data.splitlines():
coords.append(str_to_ints(line))
velos.append([0, 0, 0])
for _ in range(1_000):
# apply gravity
for i in range(len(coords)):
for j in range(i + 1, len(coords)):
for d in range(3):
if coords[i][d] > coords[j][d]:
velos[i][d] -= 1
velos[j][d] += 1
elif coords[i][d] < coords[j][d]:
velos[i][d] += 1
velos[j][d] -= 1
# update coords
for i in range(len(coords)):
for d in range(3):
coords[i][d] += velos[i][d]
r = 0
for i in range(len(coords)):
p = sum(map(abs, coords[i]))
k = sum(map(abs, velos[i]))
r += p * k
print(r)
def part_2(data):
raise Exception("TBD")
def main():
data = get_data(__file__)
part_1(data)
part_2(data)
if __name__ == "__main__":
main()

83
2019/d14.py Normal file
View File

@ -0,0 +1,83 @@
from lib import get_data
from math import ceil
def ore_for_fuel(fuel_n, reactions_store):
ore_qty = 0
required = [(fuel_n, "FUEL")]
store = {}
while required:
required_qty, required_code = required.pop()
if required_code == "ORE":
ore_qty += required_qty
continue
if required_code in store:
if store[required_code] == required_qty:
del store[required_code]
continue
elif store[required_code] > required_qty:
store[required_code] -= required_qty
continue
elif store[required_code] < required_qty:
required_qty -= store[required_code]
del store[required_code]
inputs, output = reactions_store[required_code]
output_qty, output_code = output
assert required_code == output_code
# how often must this process be executed
n = ceil(required_qty / output_qty)
leftover_output_qty = n * output_qty - required_qty
assert leftover_output_qty >= 0
if leftover_output_qty > 0:
store[output_code] = leftover_output_qty
for qty_input, input_code in inputs:
required.append((qty_input * n, input_code))
return ore_qty
def part_1(data):
reactions = []
to_get = {}
for line in data.splitlines():
left, right = line.split(" => ")
inputs = left.split(", ")
inputs = [(int(i.split()[0]), i.split()[1]) for i in inputs]
output = (int(right.split()[0]), right.split()[1])
reactions.append((inputs, output))
if output[1] in to_get:
assert False
else:
to_get[output[1]] = (inputs, output)
ore_qty = ore_for_fuel(1, to_get)
print(ore_qty)
min_fuel, max_fuel = 1, 100_000_000
target = 10**12 # trillion
while max_fuel - min_fuel > 1:
half_fuel = min_fuel + (max_fuel - min_fuel) // 2
ore_qty = ore_for_fuel(half_fuel, to_get)
if ore_qty < target:
min_fuel = half_fuel
elif ore_qty > target:
max_fuel = half_fuel
else:
min_fuel = half_fuel
max_fuel = half_fuel
print(min_fuel)
def main():
data = get_data(__file__)
part_1(data)
if __name__ == "__main__":
main()

116
2019/d15.py Normal file
View File

@ -0,0 +1,116 @@
from lib import get_data, str_to_ints, add2
from collections import deque
from d9 import Amp
DIRS = {1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 1)}
PATH_REVERSED = {1: 2, 2: 1, 3: 4, 4: 3}
def print_field(fields, walls, pos):
dim = 40
for y in range(-dim, dim + 1):
row = ""
for x in range(-dim, dim + 1):
if (y, x) == pos:
row += "X"
elif (y, x) in fields:
row += "."
elif (y, x) in walls:
row += "|"
else:
row += " "
print(row)
def part_1(data):
xs = str_to_ints(data)
a = Amp(xs)
walls = set()
pos = (0, 0)
target = None
dir = None
path = []
dir_cmds_for_pos = {pos: [1, 2, 3, 4]}
while not a.done:
if len(dir_cmds_for_pos[pos]) > 0:
dir_cmd = dir_cmds_for_pos[pos].pop()
dir = DIRS[dir_cmd]
new_pos = add2(pos, dir)
if new_pos in dir_cmds_for_pos:
continue
a.feed(dir_cmd)
a.go()
status = a.pop()
if status == 0:
walls.add(new_pos)
elif status == 1:
pos = new_pos
path.append(dir_cmd)
elif status == 2:
pos = new_pos
path.append(dir_cmd)
target = pos
if pos not in dir_cmds_for_pos:
dir_cmds_for_pos[pos] = [1, 2, 3, 4]
elif len(path) > 0:
dir_cmd = PATH_REVERSED[path.pop()]
dir = DIRS[dir_cmd]
pos = add2(pos, dir)
a.feed(dir_cmd)
a.go()
status = a.pop()
assert status == 1 or status == 2
elif target is not None:
break
else:
break
fields = set(dir_cmds_for_pos.keys())
# print_field(fields, walls, pos)
seen = set()
to_visit = [(0, 0)]
steps = 0
while len(to_visit) > 0:
new = []
for current in to_visit:
if current == target:
print(steps)
seen.add(current)
for dir in DIRS.values():
nb = add2(current, dir)
if nb in fields and nb not in seen:
new.append(nb)
to_visit = new
steps += 1
seen = set()
to_visit = [target]
steps = 0
while len(to_visit) > 0:
new = []
for current in to_visit:
seen.add(current)
for dir in DIRS.values():
nb = add2(current, dir)
if nb in fields and nb not in seen:
new.append(nb)
to_visit = new
steps += 1
print(steps - 1)
def main():
data = get_data(__file__)
part_1(data)
if __name__ == "__main__":
main()

View File

@ -13,6 +13,7 @@ class Amp:
self.rel_base = 0
def feed(self, input):
self.input_required = False
self.inputs.append(input)
def pop(self):

View File

@ -123,6 +123,9 @@ Solutions and utility script for Advent of Code challenges in Python.
- Day 11: 21:04 (Too slow, but fun.)
- Day 12:
- Day 13: >120:00 (Just struggling so much for some reason.)
- Day 14: >120:00 (Hmm, wasn't that hard either.)
- Day 15: >120:00 (I am really weak at the moment.)
- Day 16:
## AoC 2022