2021-12-06 - Lanternfish
(original .ipynb)
Day 6 puzzle input is a sequence of integers representing the ages of lanternfish (mine is here). Part 1 involves following the lifecycle of these lanternfish over 80 days, where every 7 days lanternfish will spawn a new one (so a lanternfish that starts with age 4 will produce a new fish in 4 days, then another 7 days after that). Part 2 involves doing this over 256 days.
puzzle_input_str = open("puzzle_input/day6.txt").read()
test_input_str = """3,4,3,1,2"""
def part_one(input_str, days=80):
fish = [int(age) for age in input_str.split(",")]
while days > 0:
new_fish = 0
for i in range(len(fish)):
if fish[i] == 0:
fish[i] = 6
new_fish += 1
else:
fish[i] -= 1
fish += [8] * new_fish
days -= 1
return len(fish)
assert 5934 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 356190
# part_one(puzzle_input_str, 256) <--- with 102 steps remaining the naive algo reports
# that there are 244,225,750 fish which suggests
# I do not have enough memory to keep this going
#
# so after seeing the O(N^2) algo won't run in reasonable time my heart sunk and I realised
# I might actually have to think about this one. first thought: could I maybe keep the
# existing brute force algo and chunk it into 12 processes and just run it on my 12 core
# cpu at home ... then when trying to break the problem down like that realised the order
# of the fish doesn't matter - just need to count how many there are at each step
#
# we are not our best selves at 6:00am
def part_two(input_str):
fish = [0] * 9
for age in input_str.split(","):
fish[int(age)] += 1
days = 256
while days > 0:
next_fish = [0] * 9
for age, count in enumerate(fish):
if age == 0:
next_fish[6] += count
next_fish[8] += count
else:
next_fish[age-1] += count
fish = next_fish
days -= 1
return sum(fish)
assert 26984457539 == part_two(test_input_str)
print("part two:", part_two(puzzle_input_str))
part two: 1617359101538