From fcbca441c5f2c03dbaa7c8cd982aa501851b0733 Mon Sep 17 00:00:00 2001 From: Parnic Date: Sun, 26 Jun 2022 00:00:25 -0500 Subject: [PATCH] Day 23 solution This one takes around a second to arrive at the first answer and around 30 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 | 171 +++++++++++++++++++++++++++++++++++++++++++++++++ inputs/23p.txt | 1 + main.go | 1 + 3 files changed, 173 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..6109db0 --- /dev/null +++ b/days/23.go @@ -0,0 +1,171 @@ +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 packet := <-c.packetQueue: + // fmt.Printf("computer %d received packet %v\n", c.id, packet) + c.hasQueuedPacket = true + c.lastReceivedPacket = packet + return packet.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() {