113 lines
2.0 KiB
Go
113 lines
2.0 KiB
Go
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
|
|
}
|