Skip to content

Commit 6a362c2

Browse files
committed
feat: Implement solution for 2024 day 1
1 parent 2715e9a commit 6a362c2

File tree

5 files changed

+500
-5
lines changed

5 files changed

+500
-5
lines changed

internal/puzzles/solutions/2024/day01/solution.go

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
package day01
33

44
import (
5+
"bufio"
6+
"fmt"
57
"io"
8+
"slices"
9+
"strconv"
10+
"strings"
611

712
"github.com/obalunenko/advent-of-code/internal/puzzles"
813
)
@@ -22,9 +27,100 @@ func (s solution) Day() string {
2227
}
2328

2429
func (s solution) Part1(input io.Reader) (string, error) {
25-
return "", puzzles.ErrNotImplemented
30+
l, err := parseInput(input)
31+
if err != nil {
32+
return "", fmt.Errorf("failed to parse input: %w", err)
33+
}
34+
35+
slices.Sort(l.itemsA)
36+
slices.Sort(l.itemsB)
37+
38+
var sum int
39+
40+
for i := 0; i < len(l.itemsA); i++ {
41+
d := l.itemsA[i] - l.itemsB[i]
42+
if d < 0 {
43+
d = -d
44+
}
45+
46+
sum += d
47+
}
48+
49+
return strconv.Itoa(sum), nil
2650
}
2751

2852
func (s solution) Part2(input io.Reader) (string, error) {
29-
return "", puzzles.ErrNotImplemented
53+
l, err := parseInput(input)
54+
if err != nil {
55+
return "", fmt.Errorf("failed to parse input: %w", err)
56+
}
57+
58+
seenA := make(map[int]int)
59+
60+
for _, a := range l.itemsA {
61+
seenA[a] = 0
62+
63+
for _, b := range l.itemsB {
64+
if a == b {
65+
seenA[a]++
66+
}
67+
}
68+
}
69+
70+
var sum int
71+
72+
for _, a := range l.itemsA {
73+
sum += a * seenA[a]
74+
}
75+
76+
return strconv.Itoa(sum), nil
77+
}
78+
79+
type lists struct {
80+
itemsA []int
81+
itemsB []int
82+
}
83+
84+
func parseInput(input io.Reader) (lists, error) {
85+
const (
86+
listsNum = 2
87+
listAIdx = 0
88+
listBIdx = 1
89+
)
90+
91+
l := lists{
92+
itemsA: make([]int, 0),
93+
itemsB: make([]int, 0),
94+
}
95+
96+
scanner := bufio.NewScanner(input)
97+
for scanner.Scan() {
98+
line := scanner.Text()
99+
100+
parts := strings.Split(line, " ")
101+
if len(parts) != listsNum {
102+
return lists{}, fmt.Errorf("invalid input line: %s", line)
103+
}
104+
105+
// Parse parts[0] and parts[1] to integers and append them to l.itemsA and l.itemsB respectively.
106+
a, err := strconv.Atoi(parts[listAIdx])
107+
if err != nil {
108+
return lists{}, fmt.Errorf("failed to parse int: %w", err)
109+
}
110+
111+
b, err := strconv.Atoi(parts[listBIdx])
112+
if err != nil {
113+
return lists{}, fmt.Errorf("failed to parse int: %w", err)
114+
}
115+
116+
l.itemsA = append(l.itemsA, a)
117+
118+
l.itemsB = append(l.itemsB, b)
119+
}
120+
121+
if scanner.Err() != nil {
122+
return lists{}, fmt.Errorf("scanner error: %w", scanner.Err())
123+
}
124+
125+
return l, nil
30126
}

internal/puzzles/solutions/2024/day01/solution_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ func Test_solution_Part2(t *testing.T) {
8787
wantErr assert.ErrorAssertionFunc
8888
}{
8989
{
90-
name: "",
90+
name: "test example from description",
9191
args: args{
9292
input: utils.ReaderFromFile(t, filepath.Join("testdata", "input.txt")),
9393
},
94-
want: "",
94+
want: "31",
9595
wantErr: assert.NoError,
9696
},
9797
{

internal/puzzles/solutions/2024/day01/spec.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,39 @@ Your actual left and right lists contain many location IDs. What is the total di
6666

6767
## --- Part Two ---
6868

69-
<!--- Pass here the description for part two --->
69+
Your analysis only confirmed what everyone feared: the two lists of location IDs are indeed very different.
70+
71+
Or are they?
72+
73+
The Historians can't agree on which group made the mistakes or how to read most of the Chief's handwriting,
74+
but in the commotion you notice an interesting detail: a lot of location IDs appear in both lists! Maybe the other
75+
numbers aren't location IDs at all but rather misinterpreted handwriting.
76+
77+
This time, you'll need to figure out exactly how often each number from the left list appears in the right list.
78+
Calculate a total similarity score by adding up each number in the left list after multiplying it by the number of
79+
times that number appears in the right list.
80+
81+
Here are the same example lists again:
82+
83+
```text
84+
3 4
85+
4 3
86+
2 5
87+
1 3
88+
3 9
89+
3 3
90+
```
91+
92+
For these example lists, here is the process of finding the similarity score:
93+
94+
- The first number in the left list is 3. It appears in the right list three times, so the similarity score increases by 3 * 3 = 9.
95+
- The second number in the left list is 4. It appears in the right list once, so the similarity score increases by 4 * 1 = 4.
96+
- The third number in the left list is 2. It does not appear in the right list, so the similarity score does not increase (2 * 0 = 0).
97+
- The fourth number, 1, also does not appear in the right list.
98+
- The fifth number, 3, appears in the right list three times; the similarity score increases by 9.
99+
- The last number, 3, appears in the right list three times; the similarity score again increases by 9.
100+
101+
So, for these example lists, the similarity score at the end of this process is `31` `(9 + 4 + 0 + 0 + 9 + 9)`.
102+
103+
Once again consider your left and right lists. What is their similarity score?
70104

0 commit comments

Comments
 (0)