2023 #1

Open
aey wants to merge 22 commits from 2023 into main
Showing only changes of commit 741f7b89d8 - Show all commits

View file

@ -9,91 +9,67 @@ title = "If You Give A Seed A Fertilizer"
@answer(1, "Nearest location for seed id list is {}") @answer(1, "Nearest location for seed id list is {}")
def part_1(data): def part_1(presolved):
seeds, *process = data.split("\n\n") l, _ = presolved
seeds = [f"{v} 1" for v in seeds.split()[1:]] return l
return _bruteforce(seeds, process, 1)
@answer(2, "Interpreting ranges of seeds, nearest location is {}") @answer(2, "Interpreting ranges of seeds, nearest location is {}")
def part_2(data): def part_2(presolved):
_, l = presolved
return l
def presolve(data):
seeds, *process = data.split("\n\n") seeds, *process = data.split("\n\n")
seeds = re.findall(r"\d+ \d+", seeds) seed_ranges = [[int(x) for x in ar.split()] for ar in re.findall(r"\d+ \d+", seeds)]
return _bruteforce(seeds, process, 8) seed_values = [int(v) for v in seeds.split()[1:]]
processes = [
[tuple(map(int, line.split())) for line in step.splitlines()[1:]]
for step in process
]
p1 = _process(seed_values, processes)
p2 = 26829000 # takes 5m if starting from 0
while True:
g = _process([p2], processes, reverse=True)
if any(g >= a and g < a + r for a, r in seed_ranges):
break
p2 += 1
return p1, p2
def _bruteforce(seeds, process, p=1): def _process(seeds, processes, reverse=False):
processes = [[tuple(map(int, line.split())) for line in step.splitlines()[1:]] for step in process] n = inf
for start in seeds:
sm = [] n = min(n, _nearest(start, processes, reverse=reverse))
for start_r in seeds: return n
pool = Pool()
start, r = start_r.split()
d = int(r) // p
parts = [(d * n + int(start), d * n + int(start) + d) for n in range(p)]
sm += pool.starmap(_nearest, zip(parts, repeat(processes)))
return min(sm)
def _nearest(start_r, processes): def _nearest(start, processes, reverse=False):
a, b = start_r procs = processes if not reverse else processes[::-1]
nearest = inf v = start
for i in range(a, b): for steps in procs:
v = i for line in steps:
for steps in processes: dest, src, r = line
nid = -1 if reverse:
for line in steps: dest, src = src, dest
dest, src, r = line if v >= src and v < src + r:
if v >= src and v < src + r: v = dest + v - src
v = dest + v - src break
break return v
nearest = min(nearest, v)
return nearest
if __name__ == "__main__": if __name__ == "__main__":
# use dummy data with open(f"./input/05.txt", "r") as f:
inp = """ inp = f.read().strip()
seeds: 79 14 55 13
seed-to-soil map: inp = presolve(inp)
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4
""".strip()
# inp = parse_input()
a = part_1(inp) a = part_1(inp)
b = part_2(inp) b = part_2(inp)
# assert a == 278755257 assert a == 278755257
# assert b == 26829166 assert b == 26829166