Advent of Code 2021 Day 6: Lanternfish
By Andreas Røssland
https://adventofcode.com/2021/day/6 https://github.com/roessland/advent-of-code
Here we have to model the growth of a bunch of exponentially growing lanternfish. The trick is to not model each lanternfish as a separate object, which would probably fail for part 2, but instead use map[int]int
to store the state, where the key is the days until multiplication, and the value is the number of fish in that state. That way the state of a population of billions of lanternfish can be stored in a map of length 9, since lanternfish have no properties other than daysLeft
.
I implemented the map as [9]int
since the maximum map key is 8. Such a short array should use much less memory and have a better memory access pattern than a map. It’s not relevant here though since it runs in < 100 ms.
A small Go gotcha one could stumble upon in this problem is that maps are mutable and passed by reference, but I avoided that by making a copy of the map in the Next
function (and also by using [9]int
).
package main
import (
"fmt"
"io/ioutil"
"strconv"
"strings"
)
type Population [9]int
func Next(pop0 Population) Population {
var pop Population
for days, count := range pop0 {
if days == 0 {
pop[6] += count
pop[8] += count
} else {
pop[days-1] += count
}
}
return pop
}
func Total(pop Population) int {
sum := 0
for _, count := range pop {
sum += count
}
return sum
}
func main() {
pop := ReadInput()
i := 0
for ; i < 80; i++ {
pop = Next(pop)
}
fmt.Println("Part 1:", Total(pop))
for ; i < 256; i++ {
pop = Next(pop)
}
fmt.Println("Part 2:", Total(pop))
}
func ReadInput() Population {
buf, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
var pop Population
for _, str := range strings.Split(string(buf), ",") {
n, err := strconv.Atoi(str)
if err != nil {
panic(err)
}
pop[n]++
}
return pop
}