adventofcode/2019/day23/network.go

122 lines
2.7 KiB
Go

package main
import (
"errors"
"fmt"
"time"
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
type System struct {
intcode.Program
Running bool
Address int
IncomingQueue []h.Coordinate
Network *Network
}
func NewSystem(program intcode.Program, addr int, network *Network) *System {
s := System{
Program: program,
Address: addr,
Network: network,
}
go func() {
fmt.Println("Booting", s.Address, "...")
for !s.Program.NeedsInput() {
time.Sleep(1)
}
s.Program.Input(s.Address)
fmt.Println(s.Address, "booted")
// System should just continue to run now
for {
if s.NeedsOutput() {
// There should be 3 outputs, an address and a coordinate
addr, x, y := s.Output(), s.Output(), s.Output()
coord := h.Coordinate{
X: x,
Y: y,
}
s.Network.Queue(addr, coord)
} else if s.NeedsInput() {
v, err := s.Network.Retrieve(s.Address)
if err != nil {
s.Input(v.X)
for !s.NeedsInput() {
time.Sleep(1)
}
s.Input(v.Y)
} else {
s.Input(-1)
}
}
}
}()
go s.Program.Run()
return &s
}
func (s System) String() string {
status := "."
if s.Program.NeedsInput() {
status = "<"
} else if s.Program.NeedsOutput() {
status = ">"
}
return fmt.Sprintf("[%d] %s\n", s.Address, status)
}
type Network struct {
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 {
return h.Coordinate{}, errors.New("No message")
}
}
func (n Network) String() string {
ret := fmt.Sprintf("Messages: %d\n", len(n.Messages))
for v := range n.Systems {
ret = ret + n.Systems[v].String()
}
return ret
}