Skip to content

Commit da9a7d7

Browse files
committed
internal/solutions: Refactor day01 to implement Solver interface
1 parent e6c58bb commit da9a7d7

File tree

6 files changed

+315
-202
lines changed

6 files changed

+315
-202
lines changed

internal/solutions/day01/fuel.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package day01
2+
3+
import (
4+
"bufio"
5+
"io"
6+
"log"
7+
"strconv"
8+
9+
"github.com/pkg/errors"
10+
11+
"github.com/oleg-balunenko/advent-of-code/internal/puzzle"
12+
)
13+
14+
type solver struct {
15+
name string
16+
}
17+
18+
func init() {
19+
const puzzleName = "day01"
20+
21+
puzzle.Register(puzzleName, solver{
22+
name: puzzleName,
23+
})
24+
}
25+
26+
func (s solver) Part1(input io.Reader) (string, error) {
27+
return calc(input, calcPart1)
28+
}
29+
30+
func (s solver) Part2(input io.Reader) (string, error) {
31+
return calc(input, calcPart2)
32+
}
33+
34+
func (s solver) Name() string {
35+
return s.name
36+
}
37+
38+
type module struct {
39+
mass int
40+
}
41+
42+
func (m module) fuel() int {
43+
mass := m.mass
44+
45+
diff := mass % 3
46+
if diff != 0 {
47+
mass = mass - diff
48+
}
49+
50+
f := (mass / 3) - 2
51+
52+
return f
53+
}
54+
55+
type calcFunc func(in chan module, res chan int, done chan struct{})
56+
57+
func calc(input io.Reader, calcFn calcFunc) (string, error) {
58+
var (
59+
lines int
60+
mass int
61+
sum int
62+
err error
63+
)
64+
65+
in := make(chan module)
66+
res := make(chan int)
67+
done := make(chan struct{})
68+
69+
go calcFn(in, res, done)
70+
71+
scanner := bufio.NewScanner(input)
72+
73+
for scanner.Scan() {
74+
mass, err = strconv.Atoi(scanner.Text())
75+
if err != nil {
76+
return "", err
77+
}
78+
79+
in <- module{
80+
mass: mass,
81+
}
82+
lines++
83+
}
84+
log.Printf("lines: %d\n", lines)
85+
86+
close(in)
87+
88+
if err = scanner.Err(); err != nil {
89+
return "", errors.Wrap(err, "scanner error")
90+
}
91+
var resNumCount int
92+
for lines > 0 {
93+
select {
94+
case r := <-res:
95+
sum += r
96+
resNumCount++
97+
case <-done:
98+
lines--
99+
}
100+
}
101+
log.Printf("res count: %d \n", resNumCount)
102+
103+
close(res)
104+
105+
return strconv.Itoa(sum), nil
106+
}
107+
108+
func calcPart1(in chan module, res chan int, done chan struct{}) {
109+
for i := range in {
110+
go func(m module, res chan int, done chan struct{}) {
111+
f := m.fuel()
112+
113+
res <- f
114+
115+
done <- struct{}{}
116+
}(i, res, done)
117+
}
118+
}
119+
120+
func calcPart2(in chan module, res chan int, done chan struct{}) {
121+
for i := range in {
122+
go func(m module, res chan int, done chan struct{}) {
123+
var isDone bool
124+
125+
for !isDone {
126+
f := m.fuel()
127+
128+
res <- f
129+
130+
if f/3 > 1 {
131+
m.mass = f
132+
} else {
133+
isDone = true
134+
}
135+
}
136+
137+
done <- struct{}{}
138+
}(i, res, done)
139+
}
140+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
package day01
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func Test_module_fuel(t *testing.T) {
10+
type fields struct {
11+
mass int
12+
}
13+
14+
tests := []struct {
15+
name string
16+
fields fields
17+
want int
18+
}{
19+
{
20+
name: "mass 12",
21+
fields: fields{
22+
mass: 12,
23+
},
24+
want: 2,
25+
},
26+
{
27+
name: "mass 14",
28+
fields: fields{
29+
mass: 14,
30+
},
31+
want: 2,
32+
},
33+
{
34+
name: "mass 1969",
35+
fields: fields{
36+
mass: 1969,
37+
},
38+
want: 654,
39+
},
40+
{
41+
name: "mass 100756",
42+
fields: fields{
43+
mass: 100756,
44+
},
45+
want: 33583,
46+
},
47+
}
48+
49+
for _, tt := range tests {
50+
tt := tt
51+
52+
t.Run(tt.name, func(t *testing.T) {
53+
m := module{
54+
mass: tt.fields.mass,
55+
}
56+
57+
got := m.fuel()
58+
assert.Equal(t, tt.want, got)
59+
})
60+
}
61+
}
62+
63+
func Test_calcPart1(t *testing.T) {
64+
in := make(chan module)
65+
res := make(chan int)
66+
done := make(chan struct{})
67+
68+
go calcPart1(in, res, done)
69+
70+
tests := []struct {
71+
name string
72+
input int
73+
want int
74+
}{
75+
{
76+
name: "mass 12",
77+
input: 12,
78+
want: 2,
79+
},
80+
{
81+
name: "mass 14",
82+
input: 14,
83+
want: 2,
84+
},
85+
{
86+
name: "mass 1969",
87+
input: 1969,
88+
want: 654,
89+
},
90+
{
91+
name: "mass 100756",
92+
input: 100756,
93+
want: 33583,
94+
},
95+
}
96+
for _, tt := range tests {
97+
t.Run(tt.name, func(t *testing.T) {
98+
in <- module{mass: tt.input}
99+
100+
var got int
101+
102+
LOOP:
103+
for {
104+
select {
105+
case r := <-res:
106+
got += r
107+
case <-done:
108+
break LOOP
109+
}
110+
}
111+
112+
assert.Equal(t, tt.want, got)
113+
})
114+
}
115+
116+
close(in)
117+
}
118+
119+
func Test_calcPart2(t *testing.T) {
120+
in := make(chan module)
121+
res := make(chan int)
122+
done := make(chan struct{})
123+
124+
go calcPart2(in, res, done)
125+
126+
tests := []struct {
127+
name string
128+
input int
129+
want int
130+
}{
131+
{
132+
name: "mass 12",
133+
input: 12,
134+
want: 2,
135+
},
136+
{
137+
name: "mass 14",
138+
input: 14,
139+
want: 2,
140+
},
141+
{
142+
name: "mass 1969",
143+
input: 1969,
144+
want: 966,
145+
},
146+
{
147+
name: "mass 100756",
148+
input: 100756,
149+
want: 50346,
150+
},
151+
}
152+
for _, tt := range tests {
153+
tt := tt
154+
155+
t.Run(tt.name, func(t *testing.T) {
156+
in <- module{mass: tt.input}
157+
158+
var got int
159+
160+
LOOP:
161+
for {
162+
select {
163+
case r := <-res:
164+
got += r
165+
case <-done:
166+
break LOOP
167+
}
168+
}
169+
170+
assert.Equal(t, tt.want, got)
171+
})
172+
}
173+
174+
close(in)
175+
}
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)