From 92d37d76344814787fafd492defaa96442bc546a Mon Sep 17 00:00:00 2001 From: Rickard Natt och Dag Date: Sun, 22 Dec 2024 10:42:43 +0100 Subject: [PATCH] feat(2024): add day 22 --- go/2024/README.md | 2 + go/2024/puzzles/day22/main.go | 93 ++++++++++++++++++++++ go/2024/puzzles/day22/main_test.go | 35 ++++++++ go/2024/puzzles/day22/test-input-part2.txt | 4 + go/2024/puzzles/day22/test-input.txt | 4 + 5 files changed, 138 insertions(+) create mode 100644 go/2024/puzzles/day22/main.go create mode 100644 go/2024/puzzles/day22/main_test.go create mode 100644 go/2024/puzzles/day22/test-input-part2.txt create mode 100644 go/2024/puzzles/day22/test-input.txt diff --git a/go/2024/README.md b/go/2024/README.md index 101c87c..88de12b 100644 --- a/go/2024/README.md +++ b/go/2024/README.md @@ -35,6 +35,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day | [Day 19: Linen Layout](https://github.com/believer/advent-of-code/blob/master/go/2024/puzzles/day19/main.go) | 🌟 | 209 | 🌟 | 777669668613191 | | [Day 20: Race Condition](https://github.com/believer/advent-of-code/blob/master/go/2024/puzzles/day20/main.go) | 🌟 | 1351 | 🌟 | 966130 | | [Day 21: Keypad Conundrum](https://github.com/believer/advent-of-code/blob/master/go/2024/puzzles/day21/main.go) | 🌟 | 217662 | 🌟 | 263617786809000 | +| [Day 22: Monkey Market](https://github.com/believer/advent-of-code/blob/master/go/2024/puzzles/day22/main.go) | 🌟 | 20068964552 | 🌟 | 2246 | ## Benchmarks @@ -63,6 +64,7 @@ Using Go's built-in benchmarking with the [testing](https://pkg.go.dev/testing#h | 19 | 16126963 ns/op | 16206756 ns/op | | | 20 | 106801508 ns/op | 306290916 ns/op | `85.99%` / `63.78%` | | 21 | 16344 ns/op | 16282 ns/op | | +| 22 | 36743155 ns/op | 617890208 ns/op | | \* compared to first solution diff --git a/go/2024/puzzles/day22/main.go b/go/2024/puzzles/day22/main.go new file mode 100644 index 0000000..ae5c207 --- /dev/null +++ b/go/2024/puzzles/day22/main.go @@ -0,0 +1,93 @@ +package main + +import ( + "fmt" + + "github.com/believer/aoc-2024/utils" + "github.com/believer/aoc-2024/utils/files" +) + +func main() { + fmt.Println("Part 1: ", part1("input.txt")) + fmt.Println("Part 2: ", part2("input.txt")) +} + +func part1(name string) (total int) { + buyers := files.ReadLines(name) + + for _, buyer := range buyers { + secret := utils.MustIntFromString(buyer) + + for range 2000 { + secret = generateSecret(secret) + } + + total += secret + } + + return total +} + +type Pattern [4]int + +func part2(name string) (maxBananas int) { + buyers := files.ReadLines(name) + scores := map[Pattern]int{} + + for _, buyer := range buyers { + secret := utils.MustIntFromString(buyer) + patterns := [][2]int{} + seen := map[Pattern]bool{} + last := secret % 10 + + // Generate all secrets and their deltas + for range 2000 { + secret = generateSecret(secret) + temp := secret % 10 + patterns = append(patterns, [2]int{temp - last, temp}) + last = temp + } + + // Go through the patterns four by four and them to the total score + for i := range len(patterns) - 4 { + key := Pattern{ + patterns[i][0], + patterns[i+1][0], + patterns[i+2][0], + patterns[i+3][0], + } + + if _, ok := seen[key]; !ok { + seen[key] = true + scores[key] += patterns[i+3][1] + } + } + } + + for _, b := range scores { + maxBananas = max(maxBananas, b) + } + + return maxBananas +} + +func generateSecret(secret int) int { + prune := 16777216 + + // Step 1 + result := secret * 64 + secret ^= result + secret %= prune + + // Step 2 + result = secret / 32 + secret ^= result + secret %= prune + + // Step 3 + result = secret * 2048 + secret ^= result + secret %= prune + + return secret +} diff --git a/go/2024/puzzles/day22/main_test.go b/go/2024/puzzles/day22/main_test.go new file mode 100644 index 0000000..ffe71d9 --- /dev/null +++ b/go/2024/puzzles/day22/main_test.go @@ -0,0 +1,35 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPart1(t *testing.T) { + t.Run("Part 1", func(t *testing.T) { + expected := 37327623 + actual := part1("test-input.txt") + assert.Equal(t, expected, actual) + }) +} + +func TestPart2(t *testing.T) { + t.Run("Part 2", func(t *testing.T) { + expected := 23 + actual := part2("test-input-part2.txt") + assert.Equal(t, expected, actual) + }) +} + +func BenchmarkPart1(b *testing.B) { + for i := 0; i < b.N; i++ { + part1("input.txt") + } +} + +func BenchmarkPart2(b *testing.B) { + for i := 0; i < b.N; i++ { + part2("input.txt") + } +} diff --git a/go/2024/puzzles/day22/test-input-part2.txt b/go/2024/puzzles/day22/test-input-part2.txt new file mode 100644 index 0000000..201df76 --- /dev/null +++ b/go/2024/puzzles/day22/test-input-part2.txt @@ -0,0 +1,4 @@ +1 +2 +3 +2024 diff --git a/go/2024/puzzles/day22/test-input.txt b/go/2024/puzzles/day22/test-input.txt new file mode 100644 index 0000000..07b41ba --- /dev/null +++ b/go/2024/puzzles/day22/test-input.txt @@ -0,0 +1,4 @@ +1 +10 +100 +2024