Redid day23 from scratch...
It's working but I'm not happy about it yet.
This commit is contained in:
parent
f6e0792525
commit
08cb79c5cb
BIN
2019/day23-scratch/day23-scratch
Executable file
BIN
2019/day23-scratch/day23-scratch
Executable file
Binary file not shown.
1
2019/day23-scratch/input
Normal file
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
123
2019/day23-scratch/main.go
Normal 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]
|
||||
}
|
||||
}
|
@ -1,78 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
"fmt"
|
||||
|
||||
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor"
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//pt := helpers.GetArgNumber(1)
|
||||
prog := intcode.ReadIntCodeFile("input")
|
||||
//if pt == "1" {
|
||||
part1(prog)
|
||||
//} else {
|
||||
// part2(prog)
|
||||
//}
|
||||
}
|
||||
|
||||
func part1(prog []int) {
|
||||
p := intcode.NewProgram(prog)
|
||||
n := StartNetwork(*p)
|
||||
for !n.CrashOverride {
|
||||
time.Sleep(1)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func part1o(prog []int) {
|
||||
var network []*intcode.Program
|
||||
msgQueue := make([][]int, 255)
|
||||
for k := 0; k < 50; k++ {
|
||||
p := intcode.NewProgram(prog)
|
||||
//p.EnableDebug()
|
||||
network = append(network, p)
|
||||
msgQueue = append(msgQueue, []int{})
|
||||
go func(addr int) {
|
||||
for !network[addr].NeedsInput() {
|
||||
time.Sleep(1)
|
||||
}
|
||||
network[addr].Input(addr)
|
||||
for {
|
||||
if !network[addr].NeedsOutput() && !network[addr].NeedsInput() {
|
||||
time.Sleep(1)
|
||||
} else if network[addr].NeedsOutput() {
|
||||
msgD := network[addr].Output()
|
||||
msgQueue[msgD] = append(msgQueue[msgD], network[addr].Output())
|
||||
msgQueue[msgD] = append(msgQueue[msgD], network[addr].Output())
|
||||
fmt.Println(addr, "->", msgD, msgQueue[msgD])
|
||||
} else if network[addr].NeedsInput() {
|
||||
if len(msgQueue[addr]) > 0 {
|
||||
var v int
|
||||
v, msgQueue[addr] = msgQueue[addr][0], msgQueue[addr][1:]
|
||||
fmt.Println(addr, "<-", v)
|
||||
network[addr].Input(v)
|
||||
pt := h.GetArgNumber(1)
|
||||
if pt != "2" {
|
||||
part1()
|
||||
} else {
|
||||
network[addr].Input(-1)
|
||||
part2()
|
||||
}
|
||||
}
|
||||
}
|
||||
}(k)
|
||||
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 {
|
||||
for !p.NeedsOutput() {
|
||||
time.Sleep(1)
|
||||
func part1() {
|
||||
devices, queue := NewNetwork()
|
||||
for {
|
||||
//fmt.Print(h.CLEAR_SCREEN)
|
||||
for i, dev := range devices {
|
||||
var packet h.Coordinate
|
||||
if len(queue[i]) > 0 {
|
||||
packet = queue[i][0]
|
||||
} else {
|
||||
packet = h.Coordinate{X: -1, Y: -1}
|
||||
}
|
||||
select {
|
||||
case dest := <-dev.Channel:
|
||||
x := <-dev.Channel
|
||||
y := <-dev.Channel
|
||||
//fmt.Printf("%s: [%d] -> [%d]: {%d, %d}\n", time.Now().Format(time.Stamp), i, dest, x, y)
|
||||
if dest == 255 {
|
||||
fmt.Println(y)
|
||||
return
|
||||
}
|
||||
queue[dest] = append(queue[dest], h.Coordinate{X: x, Y: y})
|
||||
case dev.Channel <- packet.X:
|
||||
//if packet.X != -1 && packet.Y != -1 {
|
||||
// fmt.Printf("%s: [%d] <-: {%d, %d}\n", time.Now().Format(time.Stamp), i, packet.X, packet.Y)
|
||||
//}
|
||||
if packet.X != -1 {
|
||||
dev.Channel <- packet.Y
|
||||
queue[i] = queue[i][1:]
|
||||
}
|
||||
}
|
||||
//fmt.Println(dev)
|
||||
}
|
||||
}
|
||||
return p.Output()
|
||||
}
|
||||
|
||||
func part2() {
|
||||
}
|
||||
|
@ -1,121 +1,163 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor"
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
type System struct {
|
||||
intcode.Program
|
||||
Running bool
|
||||
var incache []int
|
||||
|
||||
type Computer struct {
|
||||
Address int
|
||||
IncomingQueue []h.Coordinate
|
||||
Network *Network
|
||||
Program []int
|
||||
Position int
|
||||
Offset int
|
||||
Channel chan int
|
||||
}
|
||||
|
||||
func NewSystem(program intcode.Program, addr int, network *Network) *System {
|
||||
s := System{
|
||||
Program: program,
|
||||
Address: addr,
|
||||
Network: network,
|
||||
func (c Computer) String() string {
|
||||
status := "○"
|
||||
if c.Position%2 == 0 {
|
||||
status = "●"
|
||||
}
|
||||
go func() {
|
||||
fmt.Println("Booting", s.Address, "...")
|
||||
for !s.Program.NeedsInput() {
|
||||
time.Sleep(1)
|
||||
return fmt.Sprintf("[%2d] %s {%d}", c.Address, status, c.Offset)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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)
|
||||
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 {
|
||||
s.Input(-1)
|
||||
params[i] = c.read(c.read(c.Position+i+1) + c.Offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
go s.Program.Run()
|
||||
return &s
|
||||
return params
|
||||
}
|
||||
|
||||
func (s System) String() string {
|
||||
status := "."
|
||||
if s.Program.NeedsInput() {
|
||||
status = "<"
|
||||
} else if s.Program.NeedsOutput() {
|
||||
status = ">"
|
||||
func (c *Computer) read(pos int) int {
|
||||
if pos >= len(c.Program) {
|
||||
return 0
|
||||
}
|
||||
return fmt.Sprintf("[%d] %s\n", s.Address, status)
|
||||
return c.Program[pos]
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
Systems []*System
|
||||
Messages map[int][]h.Coordinate
|
||||
CrashOverride bool
|
||||
func (c *Computer) write(pos, val, mode int) {
|
||||
if mode == 2 {
|
||||
pos += c.Offset
|
||||
}
|
||||
if pos >= len(c.Program) {
|
||||
prog := make([]int, pos*2)
|
||||
copy(prog, c.Program)
|
||||
c.Program = prog
|
||||
}
|
||||
c.Program[pos] = val
|
||||
}
|
||||
|
||||
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
|
||||
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 {
|
||||
return h.Coordinate{}, errors.New("No message")
|
||||
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
|
||||
}
|
||||
}
|
||||
close(c.Channel)
|
||||
}
|
||||
|
||||
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()
|
||||
func NewComputer() Computer {
|
||||
var ints []int
|
||||
if incache == nil {
|
||||
input, _ := ioutil.ReadFile("input")
|
||||
ints = make([]int, 0)
|
||||
for _, v := range strings.Split(string(input), ",") {
|
||||
i, _ := strconv.Atoi(v)
|
||||
ints = append(ints, i)
|
||||
}
|
||||
return ret
|
||||
incache = make([]int, len(ints))
|
||||
copy(incache, ints)
|
||||
} else {
|
||||
ints = make([]int, len(incache))
|
||||
copy(ints, incache)
|
||||
}
|
||||
c := Computer{Program: ints, Channel: make(chan int)}
|
||||
go c.run()
|
||||
return c
|
||||
}
|
||||
|
||||
func NewNetwork() ([]Computer, [][]h.Coordinate) {
|
||||
devices := make([]Computer, 50)
|
||||
queue := make([][]h.Coordinate, len(devices))
|
||||
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 devices, queue
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user