From 3c5e92749f4cdb6c2f8f933062de58b4a436b55a Mon Sep 17 00:00:00 2001 From: Elias Kohout Date: Sun, 15 Dec 2024 21:38:26 +0100 Subject: [PATCH] add part 2 of day 11 --- day11/stones.go | 2 +- day11/stones_cached.go | 93 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 day11/stones_cached.go diff --git a/day11/stones.go b/day11/stones.go index 6b31afa..70a7b90 100644 --- a/day11/stones.go +++ b/day11/stones.go @@ -69,7 +69,7 @@ func main() { numbers = append(numbers, num) } - for range 75 { + for range 25 { numbers = apply_rules(numbers) } fmt.Println(len(numbers)) diff --git a/day11/stones_cached.go b/day11/stones_cached.go new file mode 100644 index 0000000..94c8a1e --- /dev/null +++ b/day11/stones_cached.go @@ -0,0 +1,93 @@ +package main + +import ( + "os" + "fmt" + "strconv" + "strings" +) + + +// --------------------------------------- +type Stone int64 + +func (s Stone) blink() [2]Stone { + stones := [...]Stone{-1, -1} + num_str := strconv.Itoa(int(s)) + + switch { + // rule 1 + case s == 0: + stones[0] = 1 + // rule 2 + case len(num_str) % 2 == 0: + num1, err := strconv.Atoi(num_str[:len(num_str) / 2]) + check(err) + num2, err := strconv.Atoi(num_str[len(num_str) / 2:]) + check(err) + + stones[0] = Stone(num1) + stones[1] = Stone(num2) + // rule 3 + default: + stones[0] = s * 2024 + } + + return stones +} + + +// --------------------------------------- +type Pair struct { + s Stone + n_steps uint32 +} +var population_number_cache map[Pair]uint64 + +func population_number(s Stone, n_steps uint32) uint64 { + cache := population_number_cache[Pair{s, n_steps}] + if cache != 0 { return cache } + + new_stones := s.blink() + + if n_steps == 0 { return 1 } + + p := population_number(new_stones[0], n_steps - 1) + if new_stones[1] > -1 { + p += population_number(new_stones[1], n_steps - 1) + } + + population_number_cache[Pair{s, n_steps}] = p + return p +} + +func check(e error) { if e != nil { panic(e) } } + + +func main() { + + // read in file + dat, err := os.ReadFile("data.txt") + check(err) + dat_str := strings.TrimSpace(string(dat)) + line_arr := strings.Split(dat_str, " ") + + // convert to list of numbers + stones := make([]Stone, 0, len(line_arr)) + + for _, e := range line_arr { + num, err := strconv.Atoi(e) + check(err) + stones = append(stones, Stone(num)) + } + + // init cache + population_number_cache = make(map[Pair]uint64) + + // main calc + len_acc := uint64(0) + for _, stone := range stones { + len_acc += population_number(stone, 75) + } + fmt.Println(len_acc) +}