Refactor 2023:05
Increasing speed from 66mins to 4mins. Caching the location value in the code to keep things at highest speed. From the subreddit, the algorithm looks like this. 1. Start att location 0 2. Traverse the whole process backwards, by reversing process steps and flipping dest/src positions. 3. Output is not a location, instead it's a seed. 4. if seed is in any seed range, use seed to get location as in step 1. 5. If not, increase location by 1 and repeat 2-4.
This commit is contained in:
parent
08288964bd
commit
741f7b89d8
1 changed files with 48 additions and 72 deletions
|
|
@ -9,91 +9,67 @@ title = "If You Give A Seed A Fertilizer"
|
|||
|
||||
|
||||
@answer(1, "Nearest location for seed id list is {}")
|
||||
def part_1(data):
|
||||
seeds, *process = data.split("\n\n")
|
||||
seeds = [f"{v} 1" for v in seeds.split()[1:]]
|
||||
return _bruteforce(seeds, process, 1)
|
||||
def part_1(presolved):
|
||||
l, _ = presolved
|
||||
return l
|
||||
|
||||
|
||||
@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 = re.findall(r"\d+ \d+", seeds)
|
||||
return _bruteforce(seeds, process, 8)
|
||||
seed_ranges = [[int(x) for x in ar.split()] for ar in re.findall(r"\d+ \d+", seeds)]
|
||||
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):
|
||||
processes = [[tuple(map(int, line.split())) for line in step.splitlines()[1:]] for step in process]
|
||||
|
||||
sm = []
|
||||
for start_r in seeds:
|
||||
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 _process(seeds, processes, reverse=False):
|
||||
n = inf
|
||||
for start in seeds:
|
||||
n = min(n, _nearest(start, processes, reverse=reverse))
|
||||
return n
|
||||
|
||||
|
||||
def _nearest(start_r, processes):
|
||||
a, b = start_r
|
||||
nearest = inf
|
||||
for i in range(a, b):
|
||||
v = i
|
||||
for steps in processes:
|
||||
nid = -1
|
||||
for line in steps:
|
||||
dest, src, r = line
|
||||
if v >= src and v < src + r:
|
||||
v = dest + v - src
|
||||
break
|
||||
nearest = min(nearest, v)
|
||||
|
||||
return nearest
|
||||
def _nearest(start, processes, reverse=False):
|
||||
procs = processes if not reverse else processes[::-1]
|
||||
v = start
|
||||
for steps in procs:
|
||||
for line in steps:
|
||||
dest, src, r = line
|
||||
if reverse:
|
||||
dest, src = src, dest
|
||||
if v >= src and v < src + r:
|
||||
v = dest + v - src
|
||||
break
|
||||
return v
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# use dummy data
|
||||
inp = """
|
||||
seeds: 79 14 55 13
|
||||
with open(f"./input/05.txt", "r") as f:
|
||||
inp = f.read().strip()
|
||||
|
||||
seed-to-soil map:
|
||||
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()
|
||||
inp = presolve(inp)
|
||||
|
||||
a = part_1(inp)
|
||||
b = part_2(inp)
|
||||
|
||||
# assert a == 278755257
|
||||
# assert b == 26829166
|
||||
assert a == 278755257
|
||||
assert b == 26829166
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue