8000 feat: Implemented solution for puzzle 2022/day01 (#207) · obalunenko/advent-of-code@ce7ca53 · GitHub
[go: up one dir, main page]

Skip to content

Commit ce7ca53

Browse files
authored
feat: Implemented solution for puzzle 2022/day01 (#207)
* feat(puzzles): Add spec and tests for 2022/day01 puzzle * feat(puzzles): Register solver for 2022/day01 * feat: Implement 2022/day01 part1 solution * feat: Add spec and test for 2022/day01 part2 * feat: Implement 2022/day01 part2 solution * feat: Add regression test for 2022/day01 * fix: SA9003 * fix: Linter warnings * style: Fmt
1 parent ed2a9f5 commit ce7ca53

File tree

5 files changed

+416
-3
lines changed

5 files changed

+416
-3
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Package day01 contains solution for https://adventofcode.com/2022/day/1 puzzle.
2+
package day01
3+
4+
import (
5+
"bufio"
6+
"fmt"
7+
"io"
8+
"sort"
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) Year() string {
21+
return puzzles.Year2022.String()
22+
}
23+
24+
func (s solution) Day() string 8000 {
25+
return puzzles.Day01.String()
26+
}
27+
28+
func (s solution) Part1(input io.Reader) (string, error) {
29+
list, err := makeElvesList(input)
30+
if err != nil {
31+
return "", err
32+
}
33+
34+
res := list.maxTotalCalories()
35+
36+
return strconv.Itoa(res), nil
37+
}
38+
39+
func (s solution) Part2(input io.Reader) (string, error) {
40+
list, err := makeElvesList(input)
41+
if err != nil {
42+
return "", err
43+
}
44+
45+
res := list.backupSnackCalc()
46+
47+
return strconv.Itoa(res), nil
48+
}
49+
50+
func makeElvesList(input io.Reader) (elves, error) {
51+
scanner := bufio.NewScanner(input)
52+
53+
var (
54+
list elves
55+
e elve
56+
prev string
57+
line string
58+
n int
59+
err error
60+
)
61+
62+
for scanner.Scan() {
63+
prev = line
64+
65+
line = scanner.Text()
66+
if line == "" {
67+
list = append(list, e)
68+
69+
e = elve{}
70+
71+
continue
72+
}
73+
74+
n, err = strconv.Atoi(line)
75+
if err != nil {
76+
return nil, fmt.Errorf("parse int: %w", err)
77+
}
78+
79+
e.food = append(e.food, n)
80+
}
81+
82+
if prev == "" {
83+
list = append(list, e)
84+
}
85+
86+
if err := scanner.Err(); err != nil {
87+
return nil, fmt.Errorf("scanner error: %w", err)
88+
}
89+
90+
return list, nil
91+
}
92+
93+
type elve struct {
94+
food []int
95+
total int
96+
}
97+
98+
func (e elve) String() string {
99+
return strconv.Itoa(e.totalCalories())
100+
}
101+
102+
func (e elve) totalCalories() int {
103+
if e.total != 0 {
104+
return e.total
105+
}
106+
107+
var sum int
108+
109+
for i := range e.food {
110+
f := e.food[i]
111+
112+
sum += f
113+
}
114+
115+
e.total = sum
116+
117+
return e.total
118+
}
119+
120+
type elves []elve
121+
122+
func (e elves) String() string {
123+
var resp string
124+
125+
for _, e2 := range e {
126+
resp += fmt.Sprintln(e2.String())
127+
}
128+
129+
return resp
130+
}
131+
132+
func (e elves) maxTotalCalories() int {
133+
var max int
134+
135+
for _, el := range e {
136+
if max == 0 {
137+
max = el.totalCalories()
138+
139+
continue
140+
}
141+
142+
c := el.totalCalories()
143+
144+
if c > max {
145+
max = c
146+
}
147+
}
148+
149+
return max
150+
}
151+
152+
func (e elves) backupSnackCalc() int {
153+
sort.Slice(e, func(i, j int) bool {
154+
return e[i].totalCalories() > e[j].totalCalories()
155+
})
156+
157+
var sum int
158+
159+
for i := 0; i < 3; i++ {
160+
sum += e[i].totalCalories()
161+
}
162+
163+
return sum
164+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package day01
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"io"
7+
"strings"
8+
"testing"
9+
"testing/iotest"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func Test_solution_Year(t *testing.T) {
15+
var s solution
16+
17+
want := "2022"
18+
got := s.Year()
19+
20+
assert.Equal(t, want, got)
21+
}
22+
23+
func Test_solution_Day(t *testing.T) {
24+
var s solution
25+
26+
want := "1"
27+
got := s.Day()
28+
29+
assert.Equal(t, want, got)
30+
}
31+
32+
func Test_solution_Part1(t *testing.T) {
33+
var s solution
34+
35+
type args struct {
36+
input io.Reader
37+
}
38+
39+
tests := []struct {
40+
name string
41+
args args
42+
want string
43+
wantErr assert.ErrorAssertionFunc
44+
}{
45+
{
46+
name: "test example from description",
47+
args: args{
48+
input: strings.NewReader("1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000"),
49+
},
50+
want: "24000",
51+
wantErr: assert.NoError,
52+
},
53+
{
54+
name: "",
55+
args: args{
56+
input: iotest.ErrReader(errors.New("custom error")),
57+
},
58+
want: "",
59+
wantErr: assert.Error,
60+
},
61+
}
62+
63+
for _, tt := range tests {
64+
t.Run(tt.name, func(t *testing.T) {
65+
got, err := s.Part1(tt.args.input)
66+
if !tt.wantErr(t, err) {
67+
return
68+
}
69+
70+
assert.Equal(t, tt.want, got)
71+
})
72+
}
73+
}
74+
75+
func Test_solution_Part2(t *testing.T) {
76+
var s solution
77+
78+
type args struct {
79+
input io.Reader
80+
}
81+
82+
tests := []struct {
83+
name string
84+
args args
85+
want string
86+
wantErr assert.ErrorAssertionFunc
87+
}{
88+
{
89+
name: "",
90+
args: args{
91+
input: strings.NewReader("1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000"),
92+
},
93+
want: "45000",
94+
wantErr: assert.NoError,
95+
},
96+
{
97+
name: "",
98+
args: args{
99+
input: iotest.ErrReader(errors.New("custom error")),
100+
},
101+
want: "",
102+
wantErr: assert.Error,
103+
},
104+
}
105+
106+
for _, tt := range tests {
107+
t.Run(tt.name, func(t *testing.T) {
108+
got, err := s.Part2(tt.args.input)
109+
if !tt.wantErr(t, err) {
110+
return
111+
}
112+
113+
assert.Equal(t, tt.want, got)
114+
})
115+
}
116+
}
117+
118+
func Test_makeElvesList(t *testing.T) {
119+
type args struct {
120+
input io.Reader
121+
}
122+
123+
tests := []struct {
124+
name string
125+
args args
126+
want elves
127+
wantErr assert.ErrorAssertionFunc
128+
}{
129+
{
130+
name: "",
131+
args: args{
132+
input: strings.NewReader("1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000"),
133+
},
134+
want: elves{
135+
{
136+
food: []int{1000, 2000, 3000},
137+
total: 0,
138+
},
139+
{
140+
food: []int{4000},
141+
total: 0,
142+
},
143+
{
144+
food: []int{5000, 6000},
145+
total: 0,
146+
},
147+
{
148+
food: []int{7000, 8000, 9000},
149+
total: 0,
150+
},
151+
{
152+
food: []int{10000},
153+
total: 0,
154+
},
155+
},
156+
wantErr: assert.NoError,
157+
},
158+
}
159+
160+
for _, tt := range tests {
161+
t.Run(tt.name, func(t *testing.T) {
162+
got, err := makeElvesList(tt.args.input)
163+
if !tt.wantErr(t, err, fmt.Sprintf("makeElvesList(%v)", tt.args.input)) {
164+
return
165+
}
166+
167+
assert.Equal(t, tt.want, got, "makeElvesList(%v)", tt.args.input)
168+
})
169+
}
170+
}

0 commit comments

Comments
 (0)
0