advent2023/five.py

71 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env python3
from useful import *
seedstr, rest = headerfooter(open(0))
seeds = numbers(seedstr)
def getmap(l):
"""
{'fertilizer': ('water', [[49, 53, 8], ...
"""
name, rest = l.split(' map:\n')
source, _, dest = name.split('-')
trips = batched(numbers(rest), 3)
return source, (dest, list(trips))
guide = {k: v for (k, v) in (getmap(p) for p in pgphs(rest))} # ugh
def move(origin, kart):
for dst, src, size in kart:
if src <= origin < src + size:
return origin + dst - src
return origin
def ship(element, target, origin): # ship('seed', 'light', 42)
if element == target:
return origin
dest, kart = guide[element]
return ship(dest, target, move(origin, kart))
def chop(origin, kart):
bego, leno = origin
endo = bego + leno
if not leno:
return []
if not kart:
return origin,
dst, src, size = kart[0]
"""
how generically can we do this?
well, when we chop the thing, there's at most going to be
- something < dst
- something inside dst (to be transformed)
- something >= dst+size
simply grab these three chunks, and recurse on the first and last.
(something already transformed obviously shouldn't be transformed back)
"""
before = (bego, min(endo, src)) if bego < src else (0, 0)
after = (max(bego, src+size), endo) if src + size < endo else (0, 0)
inside = (max(bego, src), min(endo, src+size)) if not endo <= src or bego >= src+size else (0, 0)
during = inside if inside[1] > inside[0] else (0, 0)
bl = before[0], before[1]-before[0]
dl = during[0]+dst-src, during[1]-during[0]
al = after[0], after[1]-after[0]
return (a for a in (*chop(bl, kart[1:]),
dl,
*chop(al, kart[1:])) if a[0] >= 0 and a[1] > 0)
def twoship(element, target, origin, indent=0): # ship('seed', 'light', (420, 69))
if len(sys.argv) > 1 and sys.argv[1] == '-v':
print(' ' * indent, element, origin)
if element == target:
return origin
dest, kart = guide[element]
bis = [twoship(dest, target, c, indent+1) for c in chop(origin, kart)]
return bis
print(min(ship('seed', 'location', s) for s in seeds))
print(min(beg for (beg, sz) in batched(
collapse([twoship('seed', 'location', p) for p in batched(seeds, 2)]), 2)))