Skip to content

Instantly share code, notes, and snippets.

@torarvid
Created December 12, 2019 19:16
Show Gist options
  • Save torarvid/f27654899e358a822d949d93a4291ecf to your computer and use it in GitHub Desktop.
Save torarvid/f27654899e358a822d949d93a4291ecf to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"log"
"math"
"strconv"
"strings"
"github.com/torarvid/aoc19/util"
)
func play(name string, input chan int64, ints []int64) (out, done chan int64) {
out, done = make(chan int64), make(chan int64)
loop := func() {
var ip, lastValue, relativeBase int64
alloc := func(v int64) int64 {
if v < 0 {
panic("V < 0")
}
if v >= int64(len(ints)) {
countToAdd := v - int64(len(ints)) + 1
toAdd := make([]int64, countToAdd)
ints = append(ints, toAdd...)
}
return v
}
fetch := func(i int64) int64 {
divisor := int64(math.Pow(10, float64(i+1)))
flag := ints[ip] / divisor % 10
v := ints[alloc(ip+i)]
switch flag {
case 0:
return ints[alloc(v)]
case 1:
return v
case 2:
return ints[alloc(relativeBase+v)]
default:
log.Fatalf("flag was %d\n", flag)
}
return -1
}
fetchAddr := func(i int64) int64 {
divisor := int64(math.Pow(10, float64(i+1)))
flag := ints[ip] / divisor % 10
v := ints[alloc(ip+i)]
switch flag {
case 0:
return v
case 1:
panic("Can't fetch an address of an immediate")
case 2:
return relativeBase + v
default:
log.Fatalf("flag was %d\n", flag)
}
return -1
}
for {
op, mx := ints[ip]%100, ints[ip]/100%10
fmt.Println("OP", op)
switch op {
case 1:
x, y, dest := fetch(1), fetch(2), fetchAddr(3)
ints[alloc(dest)] = x + y
ip += 4
case 2:
x, y, dest := fetch(1), fetch(2), fetchAddr(3)
ints[alloc(dest)] = x * y
ip += 4
case 3:
i := <-input
// fmt.Println("IN", i)
x := fetchAddr(1)
if mx != 1 {
ints[alloc(x)] = i
}
ip += 2
case 4:
x := fetch(1)
lastValue = x
out <- x
ip += 2
case 5:
x, y := fetch(1), fetch(2)
if x != 0 {
ip = y
} else {
ip += 3
}
case 6:
x, y := fetch(1), fetch(2)
if x == 0 {
ip = alloc(y)
} else {
ip += 3
}
case 7:
x, y, dest := fetch(1), fetch(2), fetchAddr(3)
if x < y {
ints[alloc(dest)] = 1
} else {
ints[alloc(dest)] = 0
}
ip += 4
case 8:
x, y, dest := fetch(1), fetch(2), fetchAddr(3)
if x == y {
ints[alloc(dest)] = 1
} else {
ints[alloc(dest)] = 0
}
ip += 4
case 9:
x := fetch(1)
relativeBase += x
ip += 2
case 99:
done <- lastValue
close(input)
return
default:
log.Fatalf("Oi! op was %d (%d)\n", op, ints[ip])
}
}
}
go loop()
return out, done
}
type pos struct{ x, y int }
type paint struct {
color int64
painted bool
}
type dir int
const (
up dir = iota
left
down
right
)
type robot struct {
p pos
d dir
}
func (r *robot) turnAndMove(d dir) {
switch d {
case left:
r.d = (r.d + left) % 4
case right:
r.d = (r.d + right) % 4
default:
panic("Can't turn")
}
switch r.d {
case up:
r.p.y--
case down:
r.p.y++
case left:
r.p.x--
case right:
r.p.x++
}
}
func run(initialColor int64, raw []string) map[pos]paint {
ints := make([]int64, len(raw))
for i, r := range raw {
n, _ := strconv.Atoi(r)
ints[i] = int64(n)
}
area := make(map[pos]paint)
in := make(chan int64)
r := robot{}
area[r.p] = paint{color: initialColor}
out, done := play("main", in, ints)
for {
select {
case in <- area[r.p].color:
case color := <-out:
fmt.Println("COL", color, r.p)
area[r.p] = paint{color: color, painted: true}
direction := <-out
// fmt.Println("POS", direction)
switch direction {
case 0:
r.turnAndMove(left)
case 1:
r.turnAndMove(right)
}
case <-done:
return area
}
}
}
func main() {
input := util.FileToLines("input.txt")[0]
raw := strings.Split(input, ",")
// area := run(0, raw)
// count := 0
// for _, v := range area {
// if v.painted {
// count++
// }
// }
// fmt.Println("Part 1:", count)
area := run(1, raw)
pixels := make([][]int64, 0)
for k, v := range area {
if len(pixels) < (k.y + 1) {
newP := make([][]int64, k.y+1-len(pixels))
pixels = append(pixels, newP...)
}
if len(pixels[k.y]) < (k.x + 1) {
newP := make([]int64, k.x+1-len(pixels[k.y]))
pixels[k.y] = append(pixels[k.y], newP...)
}
pixels[k.y][k.x] = v.color
}
fmt.Println("Part 2:")
for _, row := range pixels {
for _, col := range row {
if col == 0 {
fmt.Printf("⚫️")
} else {
fmt.Printf("⚪️")
}
}
fmt.Println()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment