diff --git a/README.md b/README.md index 6b945cc..61fcf60 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Advent of Code 2023 [![Tests](https://github.com/devries/advent_of_code_2023/actions/workflows/main.yml/badge.svg)](https://github.com/devries/advent_of_code_2023/actions/workflows/main.yml) -[![Stars: 28](https://img.shields.io/badge/⭐_Stars-28-yellow)](https://adventofcode.com/2023) +[![Stars: 30](https://img.shields.io/badge/⭐_Stars-30-yellow)](https://adventofcode.com/2023) ## Plan for This Year @@ -243,3 +243,11 @@ the third run of my solution after compilation on my Raspberry Pi. While programming it seems like I don't really want to shift gears to ask AI for help. + +- [Day 15: Lens Library](https://adventofcode.com/2023/day/15) - [⭐ part 1](day15p1/solution.go), [⭐ part 2](day15p2/solution.go) + + This was also a very straightforward problem, although I did have to fix a + number of bugs I introduced. This problem illustrates how a hash map works + and then requires operations on the hashmapped values. I created a Lens object + which I passed around by value, and forgot when I changed an attribute in that + object, I need to reassign it to the lens in the box array. diff --git a/day15p1/solution.go b/day15p1/solution.go new file mode 100644 index 0000000..e215b81 --- /dev/null +++ b/day15p1/solution.go @@ -0,0 +1,31 @@ +package day15p1 + +import ( + "io" + "strings" + + "aoc/utils" +) + +func Solve(r io.Reader) any { + lines := utils.ReadLines(r) + + steps := strings.Split(lines[0], ",") + + var sum uint64 + for _, s := range steps { + sum += uint64(elfHash(s)) + } + return sum +} + +func elfHash(s string) byte { + var res byte + + for _, r := range s { + res += byte(r) + res *= 17 + } + + return res +} diff --git a/day15p1/solution_test.go b/day15p1/solution_test.go new file mode 100644 index 0000000..4babc07 --- /dev/null +++ b/day15p1/solution_test.go @@ -0,0 +1,54 @@ +package day15p1 + +import ( + "strings" + "testing" + + "aoc/utils" +) + +var testInput = `rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7` + +func TestSolve(t *testing.T) { + tests := []struct { + input string + answer uint64 + }{ + {testInput, 1320}, + } + + if testing.Verbose() { + utils.Verbose = true + } + + for _, test := range tests { + r := strings.NewReader(test.input) + + result := Solve(r).(uint64) + + if result != test.answer { + t.Errorf("Expected %d, got %d", test.answer, result) + } + } +} + +func TestHash(t *testing.T) { + tests := []struct { + input string + answer byte + }{ + {"HASH", 52}, + } + + if testing.Verbose() { + utils.Verbose = true + } + + for _, test := range tests { + result := elfHash(test.input) + + if result != test.answer { + t.Errorf("Expected %d, got %d", test.answer, result) + } + } +} diff --git a/day15p2/solution.go b/day15p2/solution.go new file mode 100644 index 0000000..3ffb475 --- /dev/null +++ b/day15p2/solution.go @@ -0,0 +1,89 @@ +package day15p2 + +import ( + "io" + "strconv" + "strings" + + "aoc/utils" +) + +func Solve(r io.Reader) any { + lines := utils.ReadLines(r) + + steps := strings.Split(lines[0], ",") + + boxes := make(map[byte][]Lens) + for _, s := range steps { + if strings.Contains(s, "=") { + parts := strings.Split(s, "=") + fl, err := strconv.Atoi(parts[1]) + utils.Check(err, "unable to convert %s to integer", parts[1]) + + h := elfHash(parts[0]) + + lenses := boxes[h] + found := false + for i, l := range lenses { + if l.Label == parts[0] { + found = true + l.FocalLength = fl + lenses[i] = l + break + } + } + + if !found { + newlenses := make([]Lens, len(lenses)+1) + copy(newlenses, lenses) + newlenses[len(lenses)] = Lens{parts[0], fl} + boxes[h] = newlenses + } + } else { + label, _ := strings.CutSuffix(s, "-") + + h := elfHash(label) + + lenses := boxes[h] + + newlenses := make([]Lens, 0, len(lenses)) + for _, l := range lenses { + if l.Label != label { + newlenses = append(newlenses, l) + } + } + + boxes[h] = newlenses + } + } + + // Find focusing power + var sum uint64 + + for i := 0; i < 256; i++ { + lenses := boxes[byte(i)] + if len(lenses) != 0 { + for j, l := range lenses { + boxpower := (uint64(i) + 1) * uint64((j+1)*l.FocalLength) + sum += boxpower + } + } + } + return sum +} + +func elfHash(s string) byte { + var res byte + + for _, r := range s { + res += byte(r) + res *= 17 + } + + return res +} + +type Lens struct { + Label string + FocalLength int +} diff --git a/day15p2/solution_test.go b/day15p2/solution_test.go new file mode 100644 index 0000000..d171980 --- /dev/null +++ b/day15p2/solution_test.go @@ -0,0 +1,54 @@ +package day15p2 + +import ( + "strings" + "testing" + + "aoc/utils" +) + +var testInput = `rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7` + +func TestSolve(t *testing.T) { + tests := []struct { + input string + answer uint64 + }{ + {testInput, 145}, + } + + if testing.Verbose() { + utils.Verbose = true + } + + for _, test := range tests { + r := strings.NewReader(test.input) + + result := Solve(r).(uint64) + + if result != test.answer { + t.Errorf("Expected %d, got %d", test.answer, result) + } + } +} + +func TestHash(t *testing.T) { + tests := []struct { + input string + answer byte + }{ + {"HASH", 52}, + } + + if testing.Verbose() { + utils.Verbose = true + } + + for _, test := range tests { + result := elfHash(test.input) + + if result != test.answer { + t.Errorf("Expected %d, got %d", test.answer, result) + } + } +} diff --git a/inputs b/inputs index 053b213..8349214 160000 --- a/inputs +++ b/inputs @@ -1 +1 @@ -Subproject commit 053b213f2e19c15acced72a5c847e481470b74a5 +Subproject commit 83492142589035c8683abcbff479c696fa532de4