Redid day23 from scratch...

It's working but I'm not happy about it yet.
This commit is contained in:
Brian Buller 2020-11-04 09:50:08 -06:00
parent f6e0792525
commit 08cb79c5cb
5 changed files with 302 additions and 160 deletions

BIN
2019/day23-scratch/day23-scratch Executable file

Binary file not shown.

1
2019/day23-scratch/input Normal file

File diff suppressed because one or more lines are too long

123
2019/day23-scratch/main.go Normal file
View File

@ -0,0 +1,123 @@
package main
import (
"fmt"
"io/ioutil"
"strconv"
"strings"
)
func main() {
input, _ := ioutil.ReadFile("input")
// Build the memory
mem := map[int]int{}
for i, s := range strings.Split(strings.TrimSpace(string(input)), ",") {
mem[i], _ = strconv.Atoi(s)
}
// Mesage Buffers
in, out := make([]chan int, 50), make([]chan int, 50)
for i := 0; i < 50; i++ {
in[i], out[i] = make(chan int), make(chan int)
go run(mem, in[i], out[i])
// Send address to each computer first
in[i] <- i
in[i] <- -1
}
idle := 0
var old, nat [2]int
for i := 0; ; i = (i + 1) % 50 {
select {
case addr := <-out[i]:
if addr == 255 {
new := [2]int{<-out[i], <-out[i]}
if nat == [2]int{} {
fmt.Println(new[1])
}
nat = new
} else {
in[addr] <- <-out[i]
in[addr] <- <-out[i]
}
idle = 0
case in[i] <- -1:
idle++
}
if idle >= 50 {
if nat[1] == old[1] {
fmt.Println(nat[1])
return
}
in[0] <- nat[0]
in[0] <- nat[1]
old = nat
idle = 0
}
}
}
func run(init map[int]int, in <-chan int, out chan<- int) {
ip, rb := 0, 0
mem := map[int]int{}
for i, v := range init {
mem[i] = v
}
for {
ins := fmt.Sprintf("%05d", mem[ip])
op, _ := strconv.Atoi(ins[3:])
par := func(i int) int {
switch ins[3-i] {
case '1':
return ip + i
case '2':
return rb + mem[ip+i]
default:
return mem[ip+i]
}
}
switch op {
case 1:
mem[par(3)] = mem[par(1)] + mem[par(2)]
case 2:
mem[par(3)] = mem[par(1)] * mem[par(2)]
case 3:
mem[par(1)] = <-in
case 4:
out <- mem[par(1)]
case 5:
if mem[par(1)] != 0 {
ip = mem[par(2)]
continue
}
case 6:
if mem[par(1)] == 0 {
ip = mem[par(2)]
continue
}
case 7:
if mem[par(1)] < mem[par(2)] {
mem[par(3)] = 1
} else {
mem[par(3)] = 0
}
case 8:
if mem[par(1)] == mem[par(2)] {
mem[par(3)] = 1
} else {
mem[par(3)] = 0
}
case 9:
rb += mem[par(1)]
case 99:
return
}
ip += []int{1, 4, 4, 2, 2, 3, 3, 4, 4, 2}[op]
}
}

View File

@ -1,78 +1,54 @@
package main package main
import ( import (
"time" "fmt"
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor" h "git.bullercodeworks.com/brian/adventofcode/helpers"
) )
func main() { func main() {
//pt := helpers.GetArgNumber(1) pt := h.GetArgNumber(1)
prog := intcode.ReadIntCodeFile("input") if pt != "2" {
//if pt == "1" { part1()
part1(prog) } else {
//} else { part2()
// part2(prog)
//}
}
func part1(prog []int) {
p := intcode.NewProgram(prog)
n := StartNetwork(*p)
for !n.CrashOverride {
time.Sleep(1)
} }
} }
/* func part1() {
func part1o(prog []int) { devices, queue := NewNetwork()
var network []*intcode.Program for {
msgQueue := make([][]int, 255) //fmt.Print(h.CLEAR_SCREEN)
for k := 0; k < 50; k++ { for i, dev := range devices {
p := intcode.NewProgram(prog) var packet h.Coordinate
//p.EnableDebug() if len(queue[i]) > 0 {
network = append(network, p) packet = queue[i][0]
msgQueue = append(msgQueue, []int{}) } else {
go func(addr int) { packet = h.Coordinate{X: -1, Y: -1}
for !network[addr].NeedsInput() {
time.Sleep(1)
} }
network[addr].Input(addr) select {
for { case dest := <-dev.Channel:
if !network[addr].NeedsOutput() && !network[addr].NeedsInput() { x := <-dev.Channel
time.Sleep(1) y := <-dev.Channel
} else if network[addr].NeedsOutput() { //fmt.Printf("%s: [%d] -> [%d]: {%d, %d}\n", time.Now().Format(time.Stamp), i, dest, x, y)
msgD := network[addr].Output() if dest == 255 {
msgQueue[msgD] = append(msgQueue[msgD], network[addr].Output()) fmt.Println(y)
msgQueue[msgD] = append(msgQueue[msgD], network[addr].Output()) return
fmt.Println(addr, "->", msgD, msgQueue[msgD]) }
} else if network[addr].NeedsInput() { queue[dest] = append(queue[dest], h.Coordinate{X: x, Y: y})
if len(msgQueue[addr]) > 0 { case dev.Channel <- packet.X:
var v int //if packet.X != -1 && packet.Y != -1 {
v, msgQueue[addr] = msgQueue[addr][0], msgQueue[addr][1:] // fmt.Printf("%s: [%d] <-: {%d, %d}\n", time.Now().Format(time.Stamp), i, packet.X, packet.Y)
fmt.Println(addr, "<-", v) //}
network[addr].Input(v) if packet.X != -1 {
} else { dev.Channel <- packet.Y
network[addr].Input(-1) queue[i] = queue[i][1:]
}
} }
} }
}(k) //fmt.Println(dev)
go network[k].Run() }
} }
for len(msgQueue[255]) < 2 {
time.Sleep(1)
}
fmt.Println(msgQueue[255])
}
*/
func part2(prog []int) {
} }
func getOutput(p *intcode.Program) int { func part2() {
for !p.NeedsOutput() {
time.Sleep(1)
}
return p.Output()
} }

View File

@ -1,121 +1,163 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"time" "io/ioutil"
"strconv"
"strings"
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor"
h "git.bullercodeworks.com/brian/adventofcode/helpers" h "git.bullercodeworks.com/brian/adventofcode/helpers"
) )
type System struct { var incache []int
intcode.Program
Running bool type Computer struct {
Address int Address int
IncomingQueue []h.Coordinate Program []int
Network *Network Position int
Offset int
Channel chan int
} }
func NewSystem(program intcode.Program, addr int, network *Network) *System { func (c Computer) String() string {
s := System{ status := "○"
Program: program, if c.Position%2 == 0 {
Address: addr, status = "●"
Network: network,
} }
go func() { return fmt.Sprintf("[%2d] %s {%d}", c.Address, status, c.Offset)
fmt.Println("Booting", s.Address, "...") }
for !s.Program.NeedsInput() {
time.Sleep(1) func (c *Computer) parseInstruction() (int, []int) {
inst := c.read(c.Position)
opcode := inst % 100
modes := make([]int, 4)
inst /= 100
for i := 0; inst > 0; i++ {
modes[i] = inst % 10
inst /= 10
}
return opcode, modes
}
func (c *Computer) parseParameters(modes []int, num int) []int {
params := make([]int, num)
for i := 0; i < num; i++ {
if i >= len(modes) || modes[i] == 0 {
params[i] = c.read(c.read(c.Position + i + 1))
} else if modes[i] == 1 {
params[i] = c.read(c.Position + i + 1)
} else {
params[i] = c.read(c.read(c.Position+i+1) + c.Offset)
} }
s.Program.Input(s.Address) }
fmt.Println(s.Address, "booted") return params
// System should just continue to run now }
for {
if s.NeedsOutput() { func (c *Computer) read(pos int) int {
// There should be 3 outputs, an address and a coordinate if pos >= len(c.Program) {
addr, x, y := s.Output(), s.Output(), s.Output() return 0
coord := h.Coordinate{ }
X: x, return c.Program[pos]
Y: y, }
}
s.Network.Queue(addr, coord) func (c *Computer) write(pos, val, mode int) {
} else if s.NeedsInput() { if mode == 2 {
v, err := s.Network.Retrieve(s.Address) pos += c.Offset
if err != nil { }
s.Input(v.X) if pos >= len(c.Program) {
for !s.NeedsInput() { prog := make([]int, pos*2)
time.Sleep(1) copy(prog, c.Program)
} c.Program = prog
s.Input(v.Y) }
} else { c.Program[pos] = val
s.Input(-1) }
}
func (c *Computer) run() {
for c.read(c.Position) != 99 {
inst, modes := c.parseInstruction()
switch inst {
case 1:
params := c.parseParameters(modes, 2)
c.write(c.read(c.Position+3), params[0]+params[1], modes[2])
c.Position += 4
case 2:
params := c.parseParameters(modes, 2)
c.write(c.read(c.Position+3), params[0]*params[1], modes[2])
c.Position += 4
case 3:
c.write(c.read(c.Position+1), <-c.Channel, modes[0])
c.Position += 2
case 4:
params := c.parseParameters(modes, 1)
c.Channel <- params[0]
c.Position += 2
case 5:
params := c.parseParameters(modes, 2)
if params[0] != 0 {
c.Position = params[1]
} else {
c.Position += 3
} }
case 6:
params := c.parseParameters(modes, 2)
if params[0] == 0 {
c.Position = params[1]
} else {
c.Position += 3
}
case 7:
params := c.parseParameters(modes, 2)
if params[0] < params[1] {
c.write(c.read(c.Position+3), 1, modes[2])
} else {
c.write(c.read(c.Position+3), 0, modes[2])
}
c.Position += 4
case 8:
params := c.parseParameters(modes, 2)
if params[0] == params[1] {
c.write(c.read(c.Position+3), 1, modes[2])
} else {
c.write(c.read(c.Position+3), 0, modes[2])
}
c.Position += 4
case 9:
params := c.parseParameters(modes, 1)
c.Offset += params[0]
c.Position += 2
} }
}() }
go s.Program.Run() close(c.Channel)
return &s
} }
func (s System) String() string { func NewComputer() Computer {
status := "." var ints []int
if s.Program.NeedsInput() { if incache == nil {
status = "<" input, _ := ioutil.ReadFile("input")
} else if s.Program.NeedsOutput() { ints = make([]int, 0)
status = ">" for _, v := range strings.Split(string(input), ",") {
} i, _ := strconv.Atoi(v)
return fmt.Sprintf("[%d] %s\n", s.Address, status) ints = append(ints, i)
} }
incache = make([]int, len(ints))
type Network struct { copy(incache, ints)
Systems []*System
Messages map[int][]h.Coordinate
CrashOverride bool
}
func StartNetwork(nic intcode.Program) *Network {
n := Network{
Messages: make(map[int][]h.Coordinate),
}
for i := 0; i < 50; i++ {
n.Systems = append(n.Systems, NewSystem(nic, i, &n))
}
return &n
}
func (n *Network) Queue(addr int, coord h.Coordinate) {
fmt.Println("Network Queue", addr, coord, len(n.Messages))
if addr == 255 {
fmt.Printf("First packet to 255: {X: %d, Y: %d}\n", coord.X, coord.Y)
n.CrashOverride = true
}
if n.CrashOverride {
return
}
fmt.Printf("Queuing Packet for %d: {X: %d, Y: %d}\n", addr, coord.X, coord.Y)
n.Messages[addr] = append(n.Messages[addr], coord)
}
func (n *Network) Retrieve(addr int) (h.Coordinate, error) {
fmt.Println("Network Retrieve", addr, len(n.Messages))
if n.CrashOverride {
return h.Coordinate{}, errors.New("Network is down")
}
var ret h.Coordinate
if len(n.Messages[addr]) > 0 {
ret, n.Messages[addr] = n.Messages[addr][0], n.Messages[addr][1:]
fmt.Printf("%d Retriving Packet: {X: %d, Y: %d}\n", addr, ret.X, ret.Y)
return ret, nil
} else { } else {
return h.Coordinate{}, errors.New("No message") ints = make([]int, len(incache))
copy(ints, incache)
} }
c := Computer{Program: ints, Channel: make(chan int)}
go c.run()
return c
} }
func (n Network) String() string { func NewNetwork() ([]Computer, [][]h.Coordinate) {
ret := fmt.Sprintf("Messages: %d\n", len(n.Messages)) devices := make([]Computer, 50)
for v := range n.Systems { queue := make([][]h.Coordinate, len(devices))
ret = ret + n.Systems[v].String() for i := 0; i < len(devices); i++ {
devices[i] = NewComputer()
devices[i].Address = i
devices[i].Channel <- i
queue[i] = make([]h.Coordinate, 0)
} }
return ret return devices, queue
} }