From 7e4b44a3b693a53133647e02539bda41e894ee60 Mon Sep 17 00:00:00 2001 From: Parnic Date: Wed, 20 Jul 2022 08:35:34 -0500 Subject: [PATCH] Day 23 solution This one takes around a second to arrive at the first answer and around 15 seconds to arrive at the second answer. I don't know why, since I'm just running the given program as fast as possible (is my interpreter slow?). Go channels should be about as fast as we can get here. Maybe it would actually run faster if everyone stopped and processed their inputs at the same time or something? I dunno. Part 2 was pretty simple, though I feel like my idle detection could be improved. Seems to work, though. --- days/23.go | 170 +++++++++++++++++++++++++++++++++++++++++++++++++ inputs/23p.txt | 1 + main.go | 1 + 3 files changed, 172 insertions(+) create mode 100644 days/23.go create mode 100644 inputs/23p.txt 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() {