Skip to content

Commit 3401737

Browse files
authored
feat: Implement 2018/day02 (#53)
* feat: Initial commit for 2018/day02 * feat: Implement 2018/day02 part1 * fix: Add scanner error handling * docs: Add 2018/day02 part2 spec * chore: Remove input file * feat: Implement 2018/day02 part2 * chore: Cleanup 2018/day02 * chore: Add regression test for 2018/day02 part2 * docs: Mark 2018/day02 as solved
1 parent e39d308 commit 3401737

File tree

7 files changed

+482
-4
lines changed

7 files changed

+482
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ This repository contains solutions for puzzles and cli tool to run solutions to
125125
<summary>2018</summary>
126126

127127
- [x] [Day 1: Chronal Calibration](https://adventofcode.com/2018/day/1)
128-
- [ ] [Day 2: Inventory Management System](https://adventofcode.com/2018/day/2)
128+
- [x] [Day 2: Inventory Management System](https://adventofcode.com/2018/day/2)
129129
- [ ] [Day 3: No Matter How You Slice It](https://adventofcode.com/2018/day/3)
130130
- [ ] [Day 4: Repose Record](https://adventofcode.com/2018/day/4)
131131
- [ ] [Day 5: Alchemical Reduction](https://adventofcode.com/2018/day/5)

internal/puzzles/solutions/2017/day02/solution.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,9 @@ func findChecksum(spreadsheet io.Reader, f checksumFunc) (string, error) {
126126
checksum += n
127127
}
128128

129+
if err := scanner.Err(); err != nil {
130+
return "", fmt.Errorf("scanner error: %w", err)
131+
}
132+
129133
return strconv.Itoa(checksum), nil
130134
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Package day02 contains solution for https://adventofcode.com/2018/day/2 puzzle.
2+
package day02
3+
4+
import (
5+
"bufio"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"strconv"
10+
11+
"github.com/obalunenko/advent-of-code/internal/puzzles"
12+
)
13+
14+
func init() {
15+
puzzles.Register(solution{})
16+
}
17+
18+
type solution struct{}
19+
20+
func (s solution) Day() string {
21+
return puzzles.Day02.String()
22+
}
23+
24+
func (s solution) Year() string {
25+
return puzzles.Year2018.String()
26+
}
27+
28+
func (s solution) Part1(input io.Reader) (string, error) {
29+
boxes, err := makeBoxesList(input)
30+
if err != nil {
31+
return "", fmt.Errorf("make boxes: %w", err)
32+
}
33+
34+
const (
35+
two = 2
36+
three = 3
37+
)
38+
39+
var (
40+
twoCount, threeCount int
41+
)
42+
43+
for i := range boxes {
44+
box := boxes[i]
45+
46+
if hasNSameLetters(box, two) {
47+
twoCount++
48+
}
49+
50+
if hasNSameLetters(box, three) {
51+
threeCount++
52+
}
53+
}
54+
55+
checksum := twoCount * threeCount
56+
57+
return strconv.Itoa(checksum), nil
58+
}
59+
60+
var errNotFound = errors.New("not found")
61+
62+
func (s solution) Part2(input io.Reader) (string, error) {
63+
boxes, err := makeBoxesList(input)
64+
if err != nil {
65+
return "", fmt.Errorf("make boxes: %w", err)
66+
}
67+
68+
// finds same boxes
69+
// find common letters
70+
boxesnum := len(boxes)
71+
72+
var (
73+
box1, box2, common string
74+
)
75+
76+
loop:
77+
for i := 0; i <= boxesnum; i++ {
78+
for j := i + 1; j <= boxesnum-1; j++ {
79+
if hasNDiffLetters(boxes[i], boxes[j], 1) {
80+
box1, box2 = boxes[i], boxes[j]
81+
82+
common = getCommonBoxesPart(box1, box2)
83+
84+
break loop
85+
}
86+
}
87+
}
88+
89+
if common == "" {
90+
return "", errNotFound
91+
}
92+
93+
return common, nil
94+
}
95+
96+
func getCommonBoxesPart(box1, box2 string) string {
97+
if len(box1) != len(box2) {
98+
return ""
99+
}
100+
101+
br1, br2 := []rune(box1), []rune(box2)
102+
103+
common := make([]rune, 0, len(br1))
104+
105+
for i := 0; i < len(br1); i++ {
106+
a, b := br1[i], br2[i]
107+
if a == b {
108+
common = append(common, a)
109+
}
110+
}
111+
112+
return string(common)
113+
}
114+
115+
func hasNDiffLetters(box1, box2 string, n int) bool {
116+
if n < 0 {
117+
return false
118+
}
119+
120+
if len(box1) != len(box2) {
121+
return false
122+
}
123+
124+
var diff int
125+
126+
for i := 0; i < len(box1); i++ {
127+
if box1[i] == box2[i] {
128+
continue
129+
}
130+
131+
diff++
132+
}
133+
134+
return diff == n
135+
}
136+
137+
func makeBoxesList(input io.Reader) ([]string, error) {
138+
var boxes []string
139+
140+
scanner := bufio.NewScanner(input)
141+
for scanner.Scan() {
142+
line := scanner.Text()
143+
144+
boxes = append(boxes, line)
145+
}
146+
147+
if err := scanner.Err(); err != nil {
148+
return nil, fmt.Errorf("scanner error: %w", err)
149+
}
150+
151+
return boxes, nil
152+
}
153+
154+
func hasNSameLetters(s string, n int) bool {
155+
if n <= 0 {
156+
return false
157+
}
158+
159+
seen := make(map[rune]int)
160+
161+
for _, c := range s {
162+
seen[c]++
163+
}
164+
165+
for _, i := range seen {
166+
if i == n {
167+
return true
168+
}
169+
}
170+
171+
return false
172+
}

0 commit comments

Comments
 (0)