94 lines
1.9 KiB
Go
94 lines
1.9 KiB
Go
|
|
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)
|
||
|
|
}
|