package day22 import ( "fmt" "strconv" "strings" ) type Queue struct { data []int size int } func NewQueue(size int) *Queue { return &Queue{ data: make([]int, 0, size), size: size, } } func (queue *Queue) Push(value int) { if len(queue.data) == queue.size { queue.data = queue.data[1:] } queue.data = append(queue.data, value) } func (queue *Queue) Get() []int { return queue.data } func (queue *Queue) String() string { strs := make([]string, len(queue.data)) for i, val := range queue.data { strs[i] = fmt.Sprintf("%d", val) } return strings.Join(strs, ", ") } func Part1(input string) int { secretNumbers := parseInput(input) total := 0 for _, number := range secretNumbers { for i := 0; i < 2000; i++ { number = getNextNumber(number) } total += number } return total } func Part2(input string) int { secretNumbers := parseInput(input) memo := make(map[string]int) for _, number := range secretNumbers { seen := make(map[string]bool) queue := NewQueue(4) prevNumber := secretNumbers[0] % 10 for i := 0; i < 2000; i++ { singleNumber := number % 10 cost := singleNumber - prevNumber queue.Push(cost) if i > 3 { if _, ok := seen[queue.String()]; !ok { memo[queue.String()] += singleNumber seen[queue.String()] = true } } prevNumber = singleNumber number = getNextNumber(number) } } return maxMapValue(memo) } func parseInput(input string) []int { parts := strings.Split(input, "\n") secretNumbers := []int{} for _, part := range parts { num, _ := strconv.Atoi(part) secretNumbers = append(secretNumbers, num) } return secretNumbers } func getNextNumber(number int) int { step1 := (number * 64) ^ number step1 = step1 % 16777216 step2 := (step1 / 32) ^ step1 step2 = step2 % 16777216 step3 := (step2 * 2048) ^ step2 step3 = step3 % 16777216 return step3 } func maxMapValue(memo map[string]int) int { maxValue := 0 for _, value := range memo { if value > maxValue { maxValue = value } } return maxValue }