diff --git a/days/23.go b/days/23.go new file mode 100644 index 0000000..681e50a --- /dev/null +++ b/days/23.go @@ -0,0 +1,170 @@ +package days + +import ( + "fmt" + "sync" + + u "parnic.com/aoc2019/utilities" +) + +type day23Computer struct { + program u.IntcodeProgram + id int + packetQueue chan u.Vec2[int64] + outputStep int + nextPacketDest int + sendingPacket u.Vec2[int64] + hasQueuedPacket bool + lastReceivedPacket u.Vec2[int64] + idle bool +} + +func (d Day23) makeComputer(id int) *day23Computer { + c := &day23Computer{ + program: d.program.Copy(), + id: id, + packetQueue: make(chan u.Vec2[int64]), + idle: true, + } + + return c +} + +type Day23 struct { + program u.IntcodeProgram +} + +func (d *Day23) Parse() { + d.program = u.LoadIntcodeProgram("23p") +} + +func (d Day23) Num() int { + return 23 +} + +func (d Day23) initComputers() []*day23Computer { + computers := make([]*day23Computer, 50) + for i := range computers { + computers[i] = d.makeComputer(i) + } + return computers +} + +func (d Day23) execComputers(computers []*day23Computer, nat chan u.Vec2[int64]) *sync.WaitGroup { + wg := &sync.WaitGroup{} + wg.Add(len(computers)) + for _, c := range computers { + go func(c *day23Computer) { + bootedUp := false + c.program.RunIn(func(inputStep int) int64 { + if !bootedUp { + bootedUp = true + return int64(c.id) + } + + if c.hasQueuedPacket { + // fmt.Printf(" %d finished processing packet %v\n", c.id, c.lastReceivedPacket) + c.hasQueuedPacket = false + return c.lastReceivedPacket.Y + } + + select { + case c.lastReceivedPacket = <-c.packetQueue: + // fmt.Printf("computer %d received packet %v\n", c.id, packet) + c.hasQueuedPacket = true + return c.lastReceivedPacket.X + default: + c.idle = true + return -1 + } + }, func(val int64, state u.IntcodeProgramState) { + c.idle = false + switch c.outputStep { + case 0: + c.nextPacketDest = int(val) + case 1: + c.sendingPacket.X = val + case 2: + c.sendingPacket.Y = val + + if c.nextPacketDest == 255 { + // fmt.Printf("computer %d sending %v to 255\n", c.id, c.sendingPacket) + nat <- c.sendingPacket + } else { + // fmt.Printf("computer %d sending %v to computer %d\n", c.id, c.sendingPacket, c.nextPacketDest) + computers[c.nextPacketDest].packetQueue <- c.sendingPacket + } + } + + c.outputStep = (c.outputStep + 1) % 3 + }) + + wg.Done() + }(c) + } + + return wg +} + +func (d *Day23) Part1() string { + computers := d.initComputers() + natChan := make(chan u.Vec2[int64]) + wg := d.execComputers(computers, natChan) + + answer := <-natChan + for _, c := range computers { + c.program.Stop() + } + // not really necessary, but let's make sure they all shut down in case + // we're running all days at once + wg.Wait() + + return fmt.Sprintf("First packet sent to 255 Y value: %s%d%s", u.TextBold, answer.Y, u.TextReset) +} + +func (d *Day23) Part2() string { + computers := d.initComputers() + natChan := make(chan u.Vec2[int64]) + wg := d.execComputers(computers, natChan) + + answerChan := make(chan int64) + + go func() { + var currVal u.Vec2[int64] + var lastVal u.Vec2[int64] + hasReceived := false + for { + select { + case currVal = <-natChan: + hasReceived = true + default: + } + + allIdle := true + for _, c := range computers { + if !c.idle { + allIdle = false + break + } + } + + if allIdle && hasReceived { + // fmt.Printf("all idle, sending %v to computer 0\n", currVal) + if lastVal.Y == currVal.Y { + // fmt.Printf("found answer? %d\n", currVal.Y) + answerChan <- currVal.Y + } + computers[0].packetQueue <- currVal + lastVal = currVal + } + } + }() + + answer := <-answerChan + for _, c := range computers { + c.program.Stop() + } + wg.Wait() + + return fmt.Sprintf("First Y value sent to the NAT twice in a row: %s%d%s", u.TextBold, answer, u.TextReset) +} diff --git a/inputs/23p.txt b/inputs/23p.txt new file mode 100644 index 0000000..c03c43b --- /dev/null +++ b/inputs/23p.txt @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2245,105,1,0,1864,1049,952,1732,738,1534,1319,662,602,1474,2181,1565,915,1604,1699,1348,1804,697,1016,1154,2068,2142,1383,1942,2035,810,1414,849,571,1666,2113,2212,1257,1905,1835,1220,880,2004,1637,1084,987,1117,1505,1185,775,1773,1973,633,1445,1288,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1106,0,73,3,65,21001,64,0,1,21001,66,0,2,21101,105,0,0,1106,0,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,132,1,132,68,132,1002,0,1,62,1001,132,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1102,1,1,0,1001,161,1,169,102,1,65,0,1101,0,1,61,1102,0,1,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1105,1,178,21102,1,210,0,106,0,69,1201,1,0,70,1101,0,0,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1106,0,73,109,4,21102,0,1,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1105,1,263,21201,-3,0,-3,109,-4,2105,1,0,109,4,21101,0,1,-3,21101,0,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,21202,-3,1,-3,109,-4,2105,1,0,109,1,101,1,68,359,20102,1,0,1,101,3,68,367,20101,0,0,2,21102,376,1,0,1106,0,436,22102,1,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21102,0,1,-4,21102,1,0,-3,21102,1,51,-2,21201,-2,-1,-2,1201,-2,385,471,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1106,0,547,21101,0,-1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1105,1,529,21201,-4,0,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2106,0,0,1102,23671,1,66,1102,1,1,67,1102,598,1,68,1101,0,556,69,1101,0,1,71,1101,0,600,72,1105,1,73,1,89,21,7583,1101,0,28087,66,1101,1,0,67,1101,629,0,68,1102,556,1,69,1102,1,1,71,1101,631,0,72,1105,1,73,1,160,17,224661,1101,67061,0,66,1101,0,1,67,1101,660,0,68,1101,556,0,69,1101,0,0,71,1101,0,662,72,1105,1,73,1,1963,1102,1,98993,66,1102,3,1,67,1102,689,1,68,1102,302,1,69,1102,1,1,71,1101,0,695,72,1106,0,73,0,0,0,0,0,0,11,21283,1102,1,74887,66,1101,0,6,67,1101,724,0,68,1101,0,302,69,1101,1,0,71,1101,736,0,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,31,93326,1102,8273,1,66,1102,4,1,67,1101,765,0,68,1102,1,302,69,1101,0,1,71,1101,0,773,72,1106,0,73,0,0,0,0,0,0,0,0,11,106415,1101,0,88261,66,1101,0,3,67,1101,802,0,68,1101,0,302,69,1101,0,1,71,1102,1,808,72,1106,0,73,0,0,0,0,0,0,21,30332,1101,14699,0,66,1102,1,1,67,1101,0,837,68,1101,556,0,69,1102,5,1,71,1101,0,839,72,1106,0,73,1,1,15,51477,7,296979,4,8273,44,176522,1,268089,1102,1,99257,66,1102,1,1,67,1102,876,1,68,1101,0,556,69,1101,1,0,71,1102,1,878,72,1105,1,73,1,941,7,197986,1102,24671,1,66,1101,3,0,67,1101,907,0,68,1102,1,302,69,1101,0,1,71,1102,913,1,72,1105,1,73,0,0,0,0,0,0,12,6261,1102,2087,1,66,1101,0,4,67,1102,942,1,68,1102,253,1,69,1102,1,1,71,1101,0,950,72,1105,1,73,0,0,0,0,0,0,0,0,31,46663,1102,104551,1,66,1102,1,3,67,1101,979,0,68,1102,302,1,69,1101,0,1,71,1102,1,985,72,1105,1,73,0,0,0,0,0,0,12,4174,1102,1,22651,66,1102,1,1,67,1102,1014,1,68,1101,556,0,69,1101,0,0,71,1102,1016,1,72,1106,0,73,1,1553,1101,0,16987,66,1101,0,1,67,1102,1,1043,68,1102,1,556,69,1101,0,2,71,1102,1045,1,72,1106,0,73,1,10,35,58171,17,149774,1101,0,89363,66,1102,3,1,67,1102,1,1076,68,1102,302,1,69,1101,0,1,71,1102,1082,1,72,1106,0,73,0,0,0,0,0,0,43,243291,1102,31957,1,66,1102,1,1,67,1101,0,1111,68,1101,556,0,69,1101,0,2,71,1101,1113,0,72,1105,1,73,1,2447,2,209102,1,89363,1101,14591,0,66,1102,1,4,67,1101,1144,0,68,1102,1,302,69,1102,1,1,71,1101,1152,0,72,1106,0,73,0,0,0,0,0,0,0,0,11,85132,1102,98299,1,66,1102,1,1,67,1102,1,1181,68,1101,556,0,69,1102,1,1,71,1102,1,1183,72,1105,1,73,1,470,33,161354,1102,81097,1,66,1102,3,1,67,1102,1212,1,68,1102,1,302,69,1101,0,1,71,1102,1218,1,72,1105,1,73,0,0,0,0,0,0,12,2087,1102,1,58171,66,1102,1,4,67,1102,1247,1,68,1102,302,1,69,1102,1,1,71,1102,1,1255,72,1105,1,73,0,0,0,0,0,0,0,0,17,74887,1102,1,76883,66,1101,1,0,67,1102,1284,1,68,1101,0,556,69,1101,0,1,71,1102,1286,1,72,1105,1,73,1,16,33,242031,1101,0,10799,66,1102,1,1,67,1102,1315,1,68,1102,556,1,69,1101,0,1,71,1101,0,1317,72,1106,0,73,1,-92,15,17159,1102,11579,1,66,1102,1,1,67,1101,0,1346,68,1102,1,556,69,1102,0,1,71,1101,1348,0,72,1105,1,73,1,1924,1102,1,17159,66,1101,0,3,67,1102,1375,1,68,1101,302,0,69,1101,0,1,71,1101,1381,0,72,1105,1,73,0,0,0,0,0,0,11,63849,1101,2083,0,66,1101,1,0,67,1101,0,1410,68,1101,556,0,69,1101,0,1,71,1102,1,1412,72,1106,0,73,1,107,41,58364,1102,43189,1,66,1101,0,1,67,1101,0,1441,68,1101,556,0,69,1102,1,1,71,1102,1,1443,72,1105,1,73,1,-334,41,43773,1102,1,10163,66,1101,1,0,67,1101,0,1472,68,1102,556,1,69,1101,0,0,71,1101,0,1474,72,1106,0,73,1,1373,1101,75161,0,66,1102,1,1,67,1101,0,1501,68,1101,0,556,69,1101,1,0,71,1101,1503,0,72,1106,0,73,1,125,35,174513,1101,11489,0,66,1102,1,1,67,1101,1532,0,68,1102,556,1,69,1101,0,0,71,1102,1534,1,72,1105,1,73,1,1075,1102,1,12451,66,1101,1,0,67,1101,1561,0,68,1102,1,556,69,1102,1,1,71,1102,1563,1,72,1106,0,73,1,2137,4,24819,1102,1,21283,66,1102,5,1,67,1101,1592,0,68,1102,1,253,69,1102,1,1,71,1102,1,1602,72,1105,1,73,0,0,0,0,0,0,0,0,0,0,29,81071,1101,1987,0,66,1101,2,0,67,1102,1,1631,68,1102,1,302,69,1102,1,1,71,1101,0,1635,72,1105,1,73,0,0,0,0,12,8348,1101,0,10957,66,1101,0,1,67,1101,0,1664,68,1102,556,1,69,1101,0,0,71,1102,1,1666,72,1106,0,73,1,1576,1101,0,81071,66,1102,2,1,67,1102,1,1693,68,1101,302,0,69,1102,1,1,71,1102,1697,1,72,1105,1,73,0,0,0,0,24,70853,1101,82193,0,66,1102,1,1,67,1102,1,1726,68,1102,1,556,69,1101,0,2,71,1101,1728,0,72,1106,0,73,1,17,44,88261,21,15166,1101,0,45557,66,1102,1,1,67,1101,0,1759,68,1102,1,556,69,1101,0,6,71,1102,1,1761,72,1106,0,73,1,2,41,14591,41,29182,33,322708,4,16546,17,374435,17,449322,1101,38557,0,66,1101,0,1,67,1102,1,1800,68,1102,556,1,69,1101,1,0,71,1102,1802,1,72,1105,1,73,1,13151,15,34318,1101,95383,0,66,1102,1,1,67,1102,1,1831,68,1101,0,556,69,1102,1,1,71,1102,1833,1,72,1105,1,73,1,1613,4,33092,1102,42751,1,66,1101,1,0,67,1102,1,1862,68,1101,0,556,69,1102,0,1,71,1102,1,1864,72,1105,1,73,1,1651,1101,21493,0,66,1101,1,0,67,1102,1,1891,68,1102,1,556,69,1101,0,6,71,1101,1893,0,72,1106,0,73,1,19669,13,1987,43,81097,43,162194,36,24671,36,49342,36,74013,1102,80677,1,66,1102,4,1,67,1102,1932,1,68,1102,302,1,69,1101,1,0,71,1101,0,1940,72,1105,1,73,0,0,0,0,0,0,0,0,11,42566,1101,0,77351,66,1101,0,1,67,1102,1,1969,68,1102,556,1,69,1101,1,0,71,1101,1971,0,72,1105,1,73,1,-15,1,178726,1102,74861,1,66,1102,1,1,67,1102,1,2000,68,1101,556,0,69,1101,0,1,71,1101,0,2002,72,1105,1,73,1,1787,44,264783,1102,1,23873,66,1102,1,1,67,1102,2031,1,68,1102,556,1,69,1101,0,1,71,1101,0,2033,72,1106,0,73,1,23,33,80677,1101,0,70853,66,1102,2,1,67,1101,0,2062,68,1101,0,302,69,1102,1,1,71,1102,2066,1,72,1105,1,73,0,0,0,0,2,313653,1102,1,99871,66,1101,1,0,67,1101,2095,0,68,1102,1,556,69,1102,1,8,71,1101,2097,0,72,1106,0,73,1,5,29,162142,24,141706,2,104551,21,22749,21,37915,35,116342,35,232684,17,299548,1102,22973,1,66,1101,0,1,67,1101,0,2140,68,1102,1,556,69,1101,0,0,71,1101,2142,0,72,1105,1,73,1,1317,1102,1,7583,66,1102,5,1,67,1102,2169,1,68,1101,0,302,69,1102,1,1,71,1101,0,2179,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,13,3974,1102,1,71191,66,1101,1,0,67,1101,0,2208,68,1101,556,0,69,1101,1,0,71,1101,0,2210,72,1106,0,73,1,133,7,98993,1102,1,46663,66,1102,2,1,67,1102,2239,1,68,1101,351,0,69,1102,1,1,71,1102,1,2243,72,1106,0,73,0,0,0,0,255,21493 \ No newline at end of file diff --git a/main.go b/main.go index 4dcd6f1..9564d8e 100644 --- a/main.go +++ b/main.go @@ -56,6 +56,7 @@ var dayMap = []day{ &days.Day20{}, &days.Day21{}, &days.Day22{}, + &days.Day23{}, } func main() {