Skip to content

Commit 981a425

Browse files
committed
Advent of Code (Go): solve 2019/13 using a synchronous mode; use Options pattern to build IntCode
1 parent 24cc162 commit 981a425

6 files changed

Lines changed: 96 additions & 46 deletions

File tree

advent_of_code.go/y2019/02.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ type Day02 struct {
99
}
1010

1111
func (q *Day02) run(data string, a, b int) int {
12-
ic := NewIntCode(data, false, nil, nil)
12+
ic := NewIntCode(data)
1313
ic.mem[1] = a
1414
ic.mem[2] = b
1515
ic.run()

advent_of_code.go/y2019/05.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,26 @@ type Day05 struct {
1111

1212
// Solve returns the solution for one part.
1313
func (q *Day05) Solve(data string, part int) string {
14-
input, output := make(chan int, 1), make(chan int, 1)
15-
ic := NewIntCode(data, false, input, output)
14+
i, o:= make(chan int, 1), make(chan int, 1)
15+
ic := NewIntCode(data, IO(i, o))
1616
go ic.run()
1717
if part == 1 {
18-
input <- 1
18+
i <- 1
1919
} else {
20-
input <- 5
20+
i <- 5
2121
}
22-
var i int
22+
var output int
2323
for {
2424
select {
25-
case v := <-output:
26-
i = v
25+
case v := <-o:
26+
output = v
2727
case <-time.After(100 * time.Millisecond):
2828
if ic.state == StateHalt {
29-
return helpers.Itoa(i)
29+
return helpers.Itoa(output)
3030
}
3131
}
3232
}
33-
return helpers.Itoa(i)
33+
return helpers.Itoa(output)
3434
}
3535

3636
func init() {

advent_of_code.go/y2019/07.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (q *Day07) Solve(data string, part int) string {
2626
var ics []*IntCode
2727
var wg sync.WaitGroup
2828
for i := 0; i < 5; i++ {
29-
ics = append(ics, NewIntCode(data, false, channels[i], channels[(i+1)%5]))
29+
ics = append(ics, NewIntCode(data, IO(channels[i], channels[(i+1)%5])))
3030
}
3131
for i, v := range gen.Permutation(nil) {
3232
channels[i] <- v + offset

advent_of_code.go/y2019/09.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Day09 struct {
1212
func (q *Day09) Solve(data string, part int) string {
1313
i, o := make(chan int, 1), make(chan int)
1414
i <- part
15-
ic := NewIntCode(data, false, i, o)
15+
ic := NewIntCode(data, IO(i, o))
1616
go ic.run()
1717
return helpers.Itoa(<-o)
1818
}

advent_of_code.go/y2019/13.go

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,62 @@ package y2019
22

33
import (
44
"isaacgood.com/aoc/helpers"
5-
"time"
65
)
76

87
// Day 13 solves 2019/13.
9-
type Day13 struct {
8+
type Day13 struct {}
9+
10+
func (q *Day13) read(ic *IntCode, o <-chan int) int {
11+
v := <- o
12+
ic.run()
13+
return v
1014
}
1115

1216
// Solve returns the solution for one part.
1317
func (q *Day13) Solve(data string, part int) string {
14-
blocks := make(map[[2]int]int)
1518

16-
i, o := make(chan int), make(chan int)
17-
ic := NewIntCode(data, false, i, o)
19+
i, o := make(chan int, 1), make(chan int, 1)
20+
ic := NewIntCode(data, IO(i, o), Synchronous())
1821
if part == 2 {
1922
ic.mem[0] = 2
2023
}
21-
go ic.run()
2224

2325
var ball, paddle, score = 0, 0, 0
26+
blocks := make(map[[2]int]int)
2427
for ic.state != StateHalt {
25-
for ic.state != StateHalt {
26-
x, ok := read(o, 2*time.Millisecond)
27-
if !ok {
28-
break
29-
}
30-
y, tileType := <-o, <-o
31-
if part == 1 && tileType == 2 { // block
28+
ic.run()
29+
for ic.state != StateBlockInput && ic.state != StateHalt {
30+
x := q.read(ic, o)
31+
y := q.read(ic, o)
32+
tileType := q.read(ic, o)
33+
if tileType == 2 {
3234
blocks[[2]int{x, y}] = 1
33-
} else if tileType == 3 {
34-
paddle = x
35-
} else if tileType == 4 {
36-
ball = x
3735
} else if x == -1 && y == 0 {
3836
score = tileType
37+
} else {
38+
if tileType == 3 {
39+
paddle = x
40+
} else if tileType == 4 {
41+
ball = x
42+
}
43+
delete(blocks, [2]int{x, y})
3944
}
40-
4145
}
4246
if part == 1 {
4347
return helpers.Itoa(len(blocks))
4448
}
49+
if len(blocks) == 0 {
50+
return helpers.Itoa(score)
51+
}
4552
if paddle == ball {
46-
if ok := write(i, 0, 10*time.Millisecond); !ok {
47-
break
48-
}
53+
i <- 0
4954
} else if paddle > ball {
50-
if ok := write(i, -1, 10*time.Millisecond); !ok {
51-
break
52-
}
55+
i <- -1
5356
} else {
54-
if ok := write(i, 1, 10*time.Millisecond); !ok {
55-
break
56-
}
57+
i <- 1
5758
}
5859
}
59-
return helpers.Itoa(score)
60+
return ""
6061
}
6162

6263
func init() {

advent_of_code.go/y2019/intcode.go

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import (
1010
const (
1111
StateReady = iota
1212
StateRun
13-
StateIOBlock
13+
StateBlockInput
14+
StateBlockOutput
1415
StateHalt
1516

1617
ParamModePosition = 0
@@ -63,6 +64,7 @@ type IntCode struct {
6364
debug bool
6465
state int
6566
relativeBase int
67+
synchronous bool
6668
}
6769

6870
func read(c <-chan int, wait time.Duration) (int, bool) {
@@ -142,10 +144,31 @@ func (ic *IntCode) run() {
142144
case OpMult:
143145
ic.mem[params[2]] = params[0] * params[1]
144146
case OpInput:
145-
v := <-ic.input
146-
ic.mem[params[0]] = v
147+
if ic.synchronous {
148+
select {
149+
case v := <-ic.input:
150+
ic.mem[params[0]] = v
151+
default:
152+
ic.pc -= 2
153+
ic.state = StateBlockInput
154+
return
155+
}
156+
} else {
157+
v := <-ic.input
158+
ic.mem[params[0]] = v
159+
}
147160
case OpOutput:
148-
ic.output <- params[0]
161+
if ic.synchronous {
162+
select {
163+
case ic.output <- params[0]:
164+
default:
165+
ic.pc -= 2
166+
ic.state = StateBlockOutput
167+
return
168+
}
169+
} else {
170+
ic.output <- params[0]
171+
}
149172
case OpJumpT:
150173
if params[0] != 0 {
151174
ic.pc = params[1]
@@ -175,12 +198,38 @@ func (ic *IntCode) run() {
175198
panic(fmt.Sprintf("Unhandled op %d", op))
176199
}
177200
}
201+
panic("Not good")
202+
}
203+
204+
type Option func(*IntCode)
205+
206+
func Synchronous() Option {
207+
return func(i *IntCode) {
208+
i.synchronous = true
209+
}
178210
}
179211

180-
func NewIntCode(program string, debug bool, input <-chan int, output chan<- int) *IntCode {
212+
func IO(input <-chan int, output chan<- int) Option {
213+
return func(i *IntCode) {
214+
i.input = input
215+
i.output = output
216+
}
217+
}
218+
219+
func Debug() Option {
220+
return func(i *IntCode) {
221+
i.debug = true
222+
}
223+
}
224+
225+
func NewIntCode(program string, opts ...Option) *IntCode {
181226
mem := make(map[int]int)
182227
for i, v := range strings.Split(program, ",") {
183228
mem[i] = helpers.Atoi(v)
184229
}
185-
return &IntCode{mem: mem, input: input, output: output, debug: debug, state: StateReady}
230+
i := &IntCode{mem: mem}
231+
for _, opt := range opts {
232+
opt(i)
233+
}
234+
return i
186235
}

0 commit comments

Comments
 (0)