Skip to content

Commit 1f33a16

Browse files
authored
feat: Implement 2017/day02 (#48)
* feat: 2017/day02 initial commit * feat: Register 2017/day02 * chore: Add tests * feat: Implement 2017/day02 part1 * feat: Implement 2017/day02 solution * refactor: Fix code smells and linter bugs
1 parent f81000a commit 1f33a16

File tree

18 files changed

+528
-3
lines changed

18 files changed

+528
-3
lines changed

cmd/aoc-cli/main_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -833,10 +833,10 @@ func testcases2017() []testcase {
833833
want: puzzles.Result{
834834
Year: year,
835835
Name: puzzles.Day02.String(),
836-
Part1: "",
837-
Part2: "",
836+
Part1: "32020",
837+
Part2: "236",
838838
},
839-
wantErr: true,
839+
wantErr: false,
840840
},
841841
{
842842
name: "2017/day03",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
116 1470 2610 179 2161 2690 831 1824 2361 1050 2201 118 145 2275 2625 2333
2+
976 220 1129 553 422 950 332 204 1247 1092 1091 159 174 182 984 713
3+
84 78 773 62 808 83 1125 1110 1184 145 1277 982 338 1182 75 679
4+
3413 3809 3525 2176 141 1045 2342 2183 157 3960 3084 2643 119 108 3366 2131
5+
1312 205 343 616 300 1098 870 1008 1140 1178 90 146 980 202 190 774
6+
4368 3905 3175 4532 3806 1579 4080 259 2542 221 4395 4464 208 3734 234 4225
7+
741 993 1184 285 1062 372 111 118 63 843 325 132 854 105 956 961
8+
85 79 84 2483 858 2209 2268 90 2233 1230 2533 322 338 68 2085 1267
9+
2688 2022 112 130 1185 103 1847 3059 911 107 2066 1788 2687 2633 415 1353
10+
76 169 141 58 161 66 65 225 60 152 62 64 156 199 80 56
11+
220 884 1890 597 3312 593 4259 222 113 2244 3798 4757 216 1127 4400 178
12+
653 369 216 132 276 102 265 889 987 236 239 807 1076 932 84 864
13+
799 739 75 1537 82 228 69 1397 1396 1203 1587 63 313 1718 1375 469
14+
1176 112 1407 136 1482 1534 1384 1202 604 851 190 284 1226 113 114 687
15+
73 1620 81 1137 812 75 1326 1355 1545 1666 1356 1681 1732 85 128 902
16+
571 547 160 237 256 30 496 592 385 576 183 692 192 387 647 233

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ import (
88
"github.com/stretchr/testify/assert"
99
)
1010

11+
func Test_solution_Year(t *testing.T) {
12+
var s solution
13+
14+
want := "2015"
15+
got := s.Year()
16+
17+
assert.Equal(t, want, got)
18+
}
19+
20+
func Test_solution_Day(t *testing.T) {
21+
var s solution
22+
23+
want := "day01"
24+
got := s.Day()
25+
26+
assert.Equal(t, want, got)
27+
}
28+
1129
func Test_solution_Part1(t *testing.T) {
1230
var s solution
1331

internal/puzzles/solutions/2015/day02/solution_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ import (
88
"github.com/stretchr/testify/assert"
99
)
1010

11+
func Test_solution_Year(t *testing.T) {
12+
var s solution
13+
14+
want := "2015"
15+
got := s.Year()
16+
17+
assert.Equal(t, want, got)
18+
}
19+
20+
func Test_solution_Day(t *testing.T) {
21+
var s solution
22+
23+
want := "day02"
24+
got := s.Day()
25+
26+
assert.Equal(t, want, got)
27+
}
28+
1129
func Test_solution_Part1(t *testing.T) {
1230
var s solution
1331

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ import (
88
"github.com/stretchr/testify/assert"
99
)
1010

11+
func Test_solution_Year(t *testing.T) {
12+
var s solution
13+
14+
want := "2016"
15+
got := s.Year()
16+
17+
assert.Equal(t, want, got)
18+
}
19+
20+
func Test_solution_Day(t *testing.T) {
21+
var s solution
22+
23+
want := "day01"
24+
got := s.Day()
25+
26+
assert.Equal(t, want, got)
27+
}
28+
1129
func Test_solution_Part1(t *testing.T) {
1230
var s solution
1331

internal/puzzles/solutions/2016/day02/solution_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@ import (
99
"github.com/stretchr/testify/require"
1010
)
1111

12+
func Test_solution_Year(t *testing.T) {
13+
var s solution
14+
15+
want := "2016"
16+
got := s.Year()
17+
18+
assert.Equal(t, want, got)
19+
}
20+
21+
func Test_solution_Day(t *testing.T) {
22+
var s solution
23+
24+
want := "day02"
25+
got := s.Day()
26+
27+
assert.Equal(t, want, got)
28+
}
29+
1230
func Test_solution_Part1(t *testing.T) {
1331
var s solution
1432

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ import (
88
"github.com/stretchr/testify/assert"
99
)
1010

11+
func Test_solution_Year(t *testing.T) {
12+
var s solution
13+
14+
want := "2017"
15+
got := s.Year()
16+
17+
assert.Equal(t, want, got)
18+
}
19+
20+
func Test_solution_Day(t *testing.T) {
21+
var s solution
22+
23+
want := "day01"
24+
got := s.Day()
25+
26+
assert.Equal(t, want, got)
27+
}
28+
1129
func Test_solution_Part1(t *testing.T) {
1230
var s solution
1331

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Package day02 contains solution for https://adventofcode.com/2017/day/2 puzzle.
2+
package day02
3+
4+
import (
5+
"bufio"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"strconv"
10+
"strings"
11+
12+
"github.com/obalunenko/advent-of-code/internal/puzzles"
13+
)
14+
15+
func init() {
16+
puzzles.Register(solution{})
17+
}
18+
19+
type solution struct{}
20+
21+
func (s solution) Day() string {
22+
return puzzles.Day02.String()
23+
}
24+
25+
func (s solution) Year() string {
26+
return puzzles.Year2017.String()
27+
}
28+
29+
func (s solution) Part1(input io.Reader) (string, error) {
30+
var f checksumFunc = func(row []string) (int, error) {
31+
var min, max int
32+
33+
for i, number := range row {
34+
d, err := strconv.Atoi(number)
35+
if err != nil {
36+
return 0, fmt.Errorf("atoi: %w", err)
37+
}
38+
39+
if i == 0 {
40+
min, max = d, d
41+
}
42+
43+
if d < min {
44+
min = d
45+
}
46+
47+
if d > max {
48+
max = d
49+
}
50+
}
51+
52+
return max - min, nil
53+
}
54+
55+
return findChecksum(input, f)
56+
}
57+
58+
func (s solution) Part2(input io.Reader) (string, error) {
59+
var f checksumFunc = func(row []string) (int, error) {
60+
numbers, err := stringsToNumbers(row)
61+
if err != nil {
62+
return 0, fmt.Errorf("strings to numbers: %w", err)
63+
}
64+
65+
for i := 0; i < len(numbers); i++ {
66+
d1 := numbers[i]
67+
68+
for j := i + 1; j < len(numbers); j++ {
69+
d2 := numbers[j]
70+
71+
var a, b = d1, d2
72+
73+
if a < b {
74+
a, b = b, a
75+
}
76+
77+
if a%b == 0 {
78+
return a / b, nil
79+
}
80+
}
81+
}
82+
83+
return 0, ErrNotFound
84+
}
85+
86+
return findChecksum(input, f)
87+
}
88+
89+
func stringsToNumbers(row []string) ([]int, error) {
90+
numbers := make([]int, 0, len(row))
91+
92+
for _, n := range row {
93+
d, err := strconv.Atoi(n)
94+
if err != nil {
95+
return nil, fmt.Errorf("atoi: %w", err)
96+
}
97+
98+
numbers = append(numbers, d)
99+
}
100+
101+
return numbers, nil
102+
}
103+
104+
// ErrNotFound returns when checksum could not be found.
105+
var ErrNotFound = errors.New("checksum not found")
106+
107+
type checksumFunc func(row []string) (int, error)
108+
109+
func findChecksum(spreadsheet io.Reader, f checksumFunc) (string, error) {
110+
scanner := bufio.NewScanner(spreadsheet)
111+
112+
var checksum int
113+
114+
for scanner.Scan() {
115+
line := scanner.Text()
116+
117+
line = strings.ReplaceAll(line, "\t", " ")
118+
119+
numbers := strings.Split(line, " ")
120+
121+
n, err := f(numbers)
122+
if err != nil {
123+
return "", err
124+
}
125+
126+
checksum += n
127+
}
128+
129+
return strconv.Itoa(checksum), nil
130+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package day02
2+
3+
import (
4+
"io"
5+
"strings"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func Test_solution_Year(t *testing.T) {
13+
var s solution
14+
15+
want := "2017"
16+
got := s.Year()
17+
18+
assert.Equal(t, want, got)
19+
}
20+
21+
func Test_solution_Day(t *testing.T) {
22+
var s solution
23+
24+
want := "day02"
25+
got := s.Day()
26+
27+
assert.Equal(t, want, got)
28+
}
29+
30+
func Test_solution_Part1(t *testing.T) {
31+
var s solution
32+
33+
type args struct {
34+
input io.Reader
35+
}
36+
37+
tests := []struct {
38+
name string
39+
args args
40+
want string
41+
wantErr bool
42+
}{
43+
{
44+
name: "example from spec",
45+
args: args{
46+
input: strings.NewReader("5 1 9 5\n7 5 3\n2 4 6 8\n"),
47+
},
48+
want: "18",
49+
wantErr: false,
50+
},
51+
}
52+
53+
for _, tt := range tests {
54+
t.Run(tt.name, func(t *testing.T) {
55+
got, err := s.Part1(tt.args.input)
56+
if tt.wantErr {
57+
require.Error(t, err)
58+
59+
return
60+
}
61+
62+
require.NoError(t, err)
63+
assert.Equal(t, tt.want, got)
64+
})
65+
}
66+
}
67+
68+
func Test_solution_Part2(t *testing.T) {
69+
var s solution
70+
71+
type args struct {
72+
input io.Reader
73+
}
74+
75+
tests := []struct {
76+
name string
77+
args args
78+
want string
79+
wantErr bool
80+
}{
81+
{
82+
name: "example from spec",
83+
args: args{
84+
input: strings.NewReader("5 9 2 8\n9 4 7 3\n3 8 6 5\n"),
85+
},
86+
want: "9",
87+
wantErr: false,
88+
},
89+
}
90+
91+
for _, tt := range tests {
92+
t.Run(tt.name, func(t *testing.T) {
93+
got, err := s.Part2(tt.args.input)
94+
if tt.wantErr {
95+
require.Error(t, err)
96+
97+
return
98+
}
99+
100+
require.NoError(t, err)
101+
assert.Equal(t, tt.want, got)
102+
})
103+
}
104+
}

0 commit comments

Comments
 (0)