22 Commits
main ... dev/20

Author SHA1 Message Date
dbc4b5cf6b Day 20 completed
The key feature for part 2 is changing up what the Dijkstra solver views as an "adjacent" node, injecting the appropriate depth as we traverse inner/outer portals. The main thing that tripped me up here from part 1 was that I needed to be carrying more data along with portals than just their locations, and I could no longer get away with storing the portals as pairs of their inner/outer locations, so a small refactor was needed. Once I made those corrections, it was mostly a matter of ironing out the "get neighbors" function to adhere to part 2's rules, which took me a lot of debugging to get just right.
2022-06-22 23:32:33 -05:00
23a75d8f95 Day 20 part 1
This was pretty much just day 18 again, but without doors and with an input data parsing skill check. I simplified day 18 and went with a basic Dijkstra algorithm after the DFS to crawl the maze which solved this just fine.

Part 2 is...ugh.
2022-06-22 16:53:03 -05:00
c4faba7636 Day 19 solution
I had some trouble with the logic of this puzzle in my head, and the visuals were too large to realistically render for me to spot-check my solution, so I kept getting part 2 wrong. I eventually realized what needed to be done to get the right answer, which was partially the realization that I needed to check +99 instead of +100, and partially that I probably didn't need to check the entire space, just the bounding points, at least for the initial filters.

And then I optimized it with a bisect instead of a linear search. Always a good idea when you need to narrow a large range to a single point.
2022-06-22 16:52:32 -05:00
982576dc68 Intcode Reset optimization
Initially I noticed that I was copying twice unnecessarily (once in init() after nulling out memory, and again after returning from init()). After cleaning that up, I realized that we don't need to create a new buffer at all if the program never malloc-ed, so sometimes we can skip the re-init and we can always avoid the double-copy. I don't know if this is actually measurable anywhere, but I spot-checked some results and I still seem to be getting the same answers, so I'm gonna roll with it.
2022-06-22 16:52:32 -05:00
19f91dbc50 Add bisect utility
This is too common of an optimization to not have this readily accessible. And I kinda like how this worked out, too. Go is fun. Plus this both speeds up and "fixes" day 14's part 2 solution (it was always giving a correct answer, but mostly by chance based on how the input numbers worked out).
2022-06-22 16:52:25 -05:00
2ef1e0656a Day 18 solution
This one was a doozy and took far more time than I'd like to admit. I hope it's the hardest problem of the year. My original solution gave correct answers, but took on the order of 3+ minutes to run, even with memoization (it wasn't finishing any time soon without it). I then tried dropping in some A* and Dijkstra libraries, but wasn't really happy with how things were progressing with them. Some research pointed me toward double-ended queues and priority queues as better solutions, which I should have come up with my own since they've been used along with memoization in other AoC's, and dropping those in took the runtimes down to 4-15 seconds on my m1 macbook air. Once I swapped out the memoized data structures from arrays to maps, the runtime finally dropped to a much more palatable 50-180 millisecond range.

I'm always suspicious when my solution is hundreds of lines of code, though, since you tend to see much more terse solutions from others in the AoC subreddit, but I attribute at least some of the bloat to "Go things" like how maps and arrays usually need to be "make"d first, how there's no easy "list comprehension" or "linq" style data structure queries, etc.

Finally: note that I've seen _dramatically_ different runtimes based on the input. One set of input I checked against ran in 30ms/10ms while another ran in 180ms/54ms. I guess it's never been promised that all inputs are created equally...
2022-06-22 16:52:18 -05:00
a0867490c9 Add utility for array AddUnique 2022-06-18 23:07:38 -05:00
3d3ea6e266 Add support for cpu and memory profiling
My day 18 was slow and I wasn't completely certain where it was all coming from, so I dove into Go's profiling stuff. It was super helpful in identifying the problem and giving me easy wins that took runtime from 4.6s/14.4s (part 1/part 2) to 180ms/50ms just from swapping some arrays for maps, which the profile pointed out very clearly.
2022-06-18 23:07:38 -05:00
4b5bd0d4e0 Display part1 output as soon as it's ready
When we start having problems that take a while to run, it sucks to have to wait for everything to finish before we see any output.
2022-06-18 22:49:28 -05:00
5bc089c83d Day 17 solution
My initial idea for a solution ended up working out great, but I had a hard time getting it all down on "paper," so to speak, so this is probably 200 lines of code too many, but it definitely does exactly what I envisioned (and quickly) even if it's not the most succinct.
2022-06-14 14:37:06 -05:00
c788813cd2 Day 16 solution
Following the formula for part 1 was straightforward enough, but finding the pattern for part 2 and deducing the shortcut formula took me a while. That first 0 1 propagate enough that by the time we get halfway through applying the formula, it's all 0s and 1s, so sort of like an addition with a mask on what numbers we're adding.
2022-06-13 15:30:17 -05:00
788239e531 Day 15 solution
I wanted to use something like a right-hand wall solver, but the fact that you don't know the maze ahead of time and you can't see what something is without trying to move into it made that difficult. This semi-brute-force approach works well enough. I originally stopped as soon as I found the oxygen system and figured out the shortest path, but once I submitted that answer and saw that part 2 wanted the full map explored, I figured I might as well just fill the map all at once.

I think I would have been stuck on part 1 longer if my input set didn't happen to find the goal system fairly easily (or maybe my debug drawing helped me work through it with that input set specifically, I'm not sure) since a different input set required some tweaking to the max-visited threshold in order to find things that my first input set found with a lower setting.

Regardless, I'm pretty excited that I came to Trémaux's algorithm, more or less, on my own. I went to Wikipedia to see if I was on the right track and lo and behold, I had come to a version of it myself.

Part 2 turned out easier than I originally thought. I suspected this solution would work, but wasn't completely confident. It can only work for the type of maze used by this problem (where there are no loops of open areas). I'm just glad I didn't need A* or anything.

Oh, and this `stringer` command that allows debug printing of enums can be installed with `go install golang.org/x/tools/cmd/stringer@latest`
2022-06-13 15:30:17 -05:00
37928d7138 Day 14 solution
This one's part 1 destroyed me. I had a very difficult time, trying 3 separate approaches, each one of which worked for most cases but eventually fell apart on the 5th sample or my actual puzzle input. I ended up reading a bunch of hints from the subreddit which eventually led me to a blog post describing this solution, which wasn't far off from what I had, but I was overcomplicating things.

Part 2 surprised me in that I expected a simple "ore available divided by ore needed for 1 fuel" would solve it, but of course the excess chemicals produced in any given reaction meant that it wasn't that simple. So this approach uses that estimate as a lower bound, since it always underestimates, and then bisects its way to the solution (starting at the lower bound and adding 1 each time took too long). I'm sure a smarter upper bound choice could lower the runtime of this by a bit, but runtime isn't bad enough right now for me to try any additional optimizations.
2022-06-13 15:30:17 -05:00
da5823aa17 Day 13 solution
This was incredibly cool and I had a really fun time with it. Uncomment everything to see the game play itself! Note that I'm not seeking around in the terminal window to make the drawing smooth, I'm just outputting each new frame as it happens, so there's some jitter, but it still looks great!

I messed around a bit with control codes to move the cursor around instead of the "draw the buffer over and over again" approach, and they work, mostly, but I'm sticking with this for now.
2022-06-13 15:30:17 -05:00
8282e09a42 Day 12 solution
Okay, I had to seek help on this one. The orbital period + least-common-multiple solution was not coming to me.
2022-06-13 15:30:17 -05:00
343007481a Day 11 solution 2022-06-13 15:30:17 -05:00
44eeb5a8a6 Day 10 solution
This one was an absolute beating for me. I am so bad at these sorts of problems. Ultimately I settled on a probably-not-ideal solution that crawls the graph with offsets of each variant of (+/-x,+/-y), marking nodes visited as we come across them so that we end up with a list of asteroids that we can see. Given that this is day 10, and knowing how bad I am at math, I'm assuming this is very far from the intended solution, but it works reasonably quickly and I managed to come up with it myself, so I'm not going to stress too much about it.

For asteroid destruction, the best method I could come up with for finding the correct order was to implement an entire Vector class and sort by angle, which worked, but again, I can't decide if it was the intended solution or not. I should start reusing past years' codebases so I don't have to keep building a utility library from scratch.
2022-06-13 15:30:17 -05:00
f8d2758c90 Move Pair to a more reusable location
I originally used this in my day 10 solution, but ended up removing it. Either way, it's a general utility so it belongs here.
2022-06-13 15:30:17 -05:00
d9e0d9b649 Day 9 solution
This day showed me that when the input instruction was introduced and said "write addresses will never be in immediate mode", that didn't mean "so don't bother handling modes for input addresses", it meant "handle the mode, but assert if it's immediate mode". It was super helpful that this program contained a bootstrap sequence to validate each instruction.

Memory expansion came with a few caveats: obviously reads and writes needed to handle expanding the memory space, but a Reset also can no longer get away with simply copying the program into memory again because we need to ensure that any additional memory is cut off (or at least zeroed), so the quickest way to handle that in Go is to simply allocate a new buffer; I'd rather manipulate the existing buffer, but I'm having a hard time finding the best way to do that.

And finally, make sure you reset your relativeBase when resetting the program...that one was ugly to track down.
2022-06-13 15:30:17 -05:00
94d83695bf Day 8 solution
I had fun with this one. I liked how straightforward it was, and it's always satisfying to see the code print a message visually when you're done.
2022-06-13 15:30:17 -05:00
365edf82b1 Day 7 solution
I will probably end up regretting this since I assume the "wait to be given an input from some other process before continuing execution" paradigm is going to come up again, but this part 2 goroutine+channel solution felt good (taking advantage of Go features) and made me happy, so I rolled with it.
2022-06-13 15:30:16 -05:00
a099a86511 Day 6 solution
I'm reasonably happy with this. I started with a bi-directional linked list, but realized that a flat list of all nodes came in handy for one use case while the linked list came in handy for another, so I settled on that.
2022-06-13 15:30:10 -05:00
27 changed files with 192 additions and 1108 deletions

View File

@ -28,6 +28,9 @@ func (d *Day02) Part1() string {
d.setParams(12, 2)
d.program.Run()
if d.program.GetMemory(0) != 4138658 {
panic("")
}
return fmt.Sprintf("Position 0 = %s%d%s", utilities.TextBold, d.program.GetMemory(0), utilities.TextReset)
}
@ -56,6 +59,9 @@ func (d *Day02) Part2() string {
if !found {
panic("!found")
}
if noun != 72 || verb != 64 {
panic("")
}
return fmt.Sprintf("%d created by noun=%d, verb=%d. 100 * noun + verb = %s%d%s",
sentinel,

View File

@ -45,9 +45,9 @@ func (d Day10) Num() int {
// }
// }
func (d Day10) getVisibleAsteroids(i1, j1 int) map[u.Vec2[int]]bool {
visited := make(map[u.Vec2[int]]bool, 0)
foundAsteroids := make(map[u.Vec2[int]]bool, 0)
func (d Day10) getVisibleAsteroids(i1, j1 int) []u.Vec2[int] {
visited := make([]u.Vec2[int], 0)
foundAsteroids := make([]u.Vec2[int], 0)
findNext := func(startX, startY, incX, incY int) *u.Vec2[int] {
var found *u.Vec2[int]
@ -59,8 +59,8 @@ func (d Day10) getVisibleAsteroids(i1, j1 int) map[u.Vec2[int]]bool {
y := startY + incY
for x < len(d.asteroids) && x >= 0 && y < len(d.asteroids[x]) && y >= 0 {
currPair := u.Vec2[int]{X: x, Y: y}
if _, exists := visited[currPair]; !exists {
visited[currPair] = true
if !u.ArrayContains(visited, currPair) {
visited = append(visited, currPair)
if d.asteroids[x][y] {
if found == nil {
@ -91,16 +91,16 @@ func (d Day10) getVisibleAsteroids(i1, j1 int) map[u.Vec2[int]]bool {
}
if found := findNext(i1, j1, incX, incY); found != nil {
foundAsteroids[*found] = true
foundAsteroids = append(foundAsteroids, *found)
}
if found := findNext(i1, j1, incX, -incY); found != nil {
foundAsteroids[*found] = true
foundAsteroids = append(foundAsteroids, *found)
}
if found := findNext(i1, j1, -incX, incY); found != nil {
foundAsteroids[*found] = true
foundAsteroids = append(foundAsteroids, *found)
}
if found := findNext(i1, j1, -incX, -incY); found != nil {
foundAsteroids[*found] = true
foundAsteroids = append(foundAsteroids, *found)
}
incY++
@ -116,8 +116,8 @@ func (d Day10) numVisibleAsteroids(i1, j1 int) int {
return len(d.getVisibleAsteroids(i1, j1))
}
func (d *Day10) removeAsteroids(locs map[u.Vec2[int]]bool) {
for loc := range locs {
func (d *Day10) removeAsteroids(locs ...u.Vec2[int]) {
for _, loc := range locs {
if !d.asteroids[loc.X][loc.Y] {
panic("tried to remove non-asteroid")
}
@ -156,15 +156,14 @@ func (d *Day10) Part2() string {
if vaporized+len(visibleAsteroids) < findNumVaporized {
vaporized += len(visibleAsteroids)
d.removeAsteroids(visibleAsteroids)
d.removeAsteroids(visibleAsteroids...)
continue
}
vecs := u.MapKeys(visibleAsteroids)
sort.Slice(vecs, func(i, j int) bool {
return d.idealLocation.AngleBetween(vecs[i]) > d.idealLocation.AngleBetween(vecs[j])
sort.Slice(visibleAsteroids, func(i, j int) bool {
return d.idealLocation.AngleBetween(visibleAsteroids[i]) > d.idealLocation.AngleBetween(visibleAsteroids[j])
})
targetLocation = vecs[findNumVaporized-1-vaporized]
targetLocation = visibleAsteroids[findNumVaporized-1-vaporized]
break
}

View File

@ -2,7 +2,6 @@ package days
import (
"fmt"
"strings"
u "parnic.com/aoc2019/utilities"
)
@ -46,36 +45,36 @@ func (d Day13) getNumBlocks() int {
return blockTiles
}
func (d Day13) Draw() {
s := strings.Builder{}
for x := range d.gameBoard {
for y := range d.gameBoard[x] {
block := d.gameBoard[x][y]
if block == tileBlock {
s.WriteString(u.ColorBlue)
s.WriteRune('█')
s.WriteString(u.TextReset)
} else if block == tileBall {
s.WriteString(u.ColorGreen)
s.WriteRune('█')
s.WriteString(u.TextReset)
} else if block == tileWall {
s.WriteString(u.ColorWhite)
s.WriteRune('█')
s.WriteString(u.TextReset)
} else if block == tileHPaddle {
s.WriteString(u.ColorRed)
s.WriteRune('█')
s.WriteString(u.TextReset)
} else if block == tileEmpty {
s.WriteRune(' ')
}
}
s.WriteRune('\n')
}
// func (d Day13) drawGameBoard() {
// s := strings.Builder{}
// for x := range d.gameBoard {
// for y := range d.gameBoard[x] {
// block := d.gameBoard[x][y]
// if block == tileBlock {
// s.WriteString(u.ColorBlue)
// s.WriteRune('█')
// s.WriteString(u.TextReset)
// } else if block == tileBall {
// s.WriteString(u.ColorGreen)
// s.WriteRune('█')
// s.WriteString(u.TextReset)
// } else if block == tileWall {
// s.WriteString(u.ColorWhite)
// s.WriteRune('█')
// s.WriteString(u.TextReset)
// } else if block == tileHPaddle {
// s.WriteString(u.ColorRed)
// s.WriteRune('█')
// s.WriteString(u.TextReset)
// } else if block == tileEmpty {
// s.WriteRune(' ')
// }
// }
// s.WriteRune('\n')
// }
fmt.Print(s.String())
}
// fmt.Print(s.String())
// }
func (d *Day13) Part1() string {
outputStep := 0
@ -98,7 +97,7 @@ func (d *Day13) Part1() string {
}
})
return fmt.Sprintf("%d total tiles, # block tiles: %s%d%s", len(d.tiles), u.TextBold, d.getNumBlocks(), u.TextReset)
return fmt.Sprintf("# block tiles: %s%d%s (%d total tiles)", u.TextBold, d.getNumBlocks(), u.TextReset, len(d.tiles))
}
func (d *Day13) Part2() string {
@ -135,7 +134,7 @@ func (d *Day13) Part2() string {
ball = newTilePos
} else if val == tileHPaddle {
paddle = newTilePos
// d.Draw()
// d.drawGameBoard()
// time.Sleep(time.Millisecond * 33)
}
}

View File

@ -314,7 +314,7 @@ func (d *Day15) Part1() string {
visited.timesVisited = 1
}
d.pos = point{}
// d.Draw()
d.Draw()
return fmt.Sprintf("Moves required to reach target: %s%d%s", u.TextBold, d.visited[d.goalPos].distanceFromStart, u.TextReset)
}

View File

@ -48,7 +48,6 @@ type Day17 struct {
func (d *Day17) Parse() {
d.program = u.LoadIntcodeProgram("17p")
// d.program.SetDebugASCIIPrint(true)
}
func (d Day17) Num() int {
@ -389,8 +388,9 @@ func (d *Day17) Part2() string {
row := 0
var outputState int
var lastOutput int64
var instructionStr string
d.program.RunIn(func(inputStep int) int64 {
panic("unexpected read")
return int64(instructionStr[inputStep-1])
}, func(val int64, state u.IntcodeProgramState) {
rVal := rune(val)
if outputState == 0 {
@ -401,7 +401,7 @@ func (d *Day17) Part2() string {
if rVal == '\n' && lastOutput == '\n' {
if outputState == 0 {
d.program.FeedInputString(beforeGrid.solvePath(beforeBotLocation, beforeBotFacing))
instructionStr = beforeGrid.solvePath(beforeBotLocation, beforeBotFacing)
}
outputState++
row = 0

View File

@ -1,86 +0,0 @@
package days
import (
"fmt"
"strings"
u "parnic.com/aoc2019/utilities"
)
type Day21 struct {
program u.IntcodeProgram
}
func (d *Day21) Parse() {
d.program = u.LoadIntcodeProgram("21p")
// d.program.SetDebugASCIIPrint(true)
}
func (d Day21) Num() int {
return 21
}
func (d *Day21) Part1() string {
// if there's any hole up to 3 ahead of us but there's ground where we'd land if we jumped
// (a jump takes 4 spaces), go ahead and jump
cmds := []string{
// check if a hole at 1 or 2 ahead
"NOT A T",
"NOT B J",
// store that result in J
"OR T J",
// check if a hole at 3 ahead
"NOT C T",
// store hole in 1, 2, or 3 in T
"OR J T",
// set J true if hole in 1, 2, or 3
"OR T J",
// set J true if also no hole at 4 ahead
"AND D J",
"WALK",
}
instructionStr := strings.Join(cmds, "\n") + "\n"
d.program.FeedInputString(instructionStr)
res := d.program.Run()
return fmt.Sprintf("Hull damage value when walking: %s%d%s", u.TextBold, res, u.TextReset)
}
func (d *Day21) Part2() string {
d.program.Reset()
// @
// #####.#.##.##.###
// ABCDEFGHI
// using the first program, this kills us. if we jump, we land at D and H becomes our new D, so it won't jump again.
// but if we waited to jump until we got one more ahead, we'd be ok.
// so now we want to know essentially the same thing as part 1, but also if our multiple (immediate second jump) would be successful.
// in problem terms, that's: if there's a hole at 1 or 2 ahead, and there's a hole at C with ground at H, and there's ground at D.
// so now for the above example we'd wait to jump until here:
// @
// #####.#.##.##.###
// ABCDEFGHI
// and all will be well.
cmds := []string{
// check if a hole at 1 or 2 ahead
"NOT A J",
"NOT B T",
// store that result in J
"OR T J",
// check if a hole at 3 ahead...
"NOT C T",
// and ground at 8 ahead (so we can immediately jump again if needed)...
"AND H T",
// combine those into J
"OR T J",
// and ensure we also still have a place to land if we jumped right away
"AND D J",
"RUN",
}
instructionStr := strings.Join(cmds, "\n") + "\n"
d.program.FeedInputString(instructionStr)
res := d.program.Run()
return fmt.Sprintf("Hull damage value when running: %s%d%s", u.TextBold, res, u.TextReset)
}

View File

@ -1,155 +0,0 @@
package days
import (
"fmt"
"math"
"math/big"
"strconv"
"strings"
u "parnic.com/aoc2019/utilities"
)
type day22Instruction int
const (
day22InstructionNewStack day22Instruction = iota
day22InstructionCut
day22InstructionDealIncrement
)
type day22Shuffle struct {
instruction day22Instruction
arg int
}
type Day22 struct {
shuffles []day22Shuffle
}
func (d *Day22) Parse() {
lines := u.GetStringLines("22p")
d.shuffles = make([]day22Shuffle, len(lines))
for idx, line := range lines {
split := strings.Split(line, " ")
if split[0] == "deal" {
if split[1] == "into" {
d.shuffles[idx] = day22Shuffle{instruction: day22InstructionNewStack}
} else if split[1] == "with" {
arg, err := strconv.Atoi(split[3])
if err != nil {
panic(err)
}
d.shuffles[idx] = day22Shuffle{
instruction: day22InstructionDealIncrement,
arg: arg,
}
}
} else if split[0] == "cut" {
arg, err := strconv.Atoi(split[1])
if err != nil {
panic(err)
}
d.shuffles[idx] = day22Shuffle{
instruction: day22InstructionCut,
arg: arg,
}
}
}
}
func (d Day22) Num() int {
return 22
}
func (d Day22) applyShuffle(s day22Shuffle, stack, scratch []int) {
switch s.instruction {
case day22InstructionNewStack:
for i := 0; i < len(stack)/2; i++ {
stack[i], stack[len(stack)-1-i] = stack[len(stack)-1-i], stack[i]
}
// there's probably a way to do these two in place...
case day22InstructionCut:
absArg := int(math.Abs(float64(s.arg)))
for i, v := range stack {
if s.arg > 0 {
if i < absArg {
scratch[len(scratch)-absArg+i] = v
} else {
scratch[i-absArg] = v
}
} else {
if i < absArg {
scratch[i] = stack[len(stack)-absArg+i]
} else {
scratch[i] = stack[i-absArg]
}
}
}
copy(stack, scratch)
case day22InstructionDealIncrement:
for i, v := range stack {
scratch[(i*s.arg)%len(stack)] = v
}
copy(stack, scratch)
}
}
func (d *Day22) Part1() string {
deckSize := 10007
// deckSize := 10
stack := make([]int, deckSize)
for i := range stack {
stack[i] = i
}
scratch := make([]int, len(stack))
for _, s := range d.shuffles {
d.applyShuffle(s, stack, scratch)
}
pos := -1
for i, v := range stack {
if v == 2019 {
pos = i
break
}
}
return fmt.Sprintf("Card 2019 is at position %s%d%s", u.TextBold, pos, u.TextReset)
}
func (d *Day22) Part2() string {
n, iter := big.NewInt(119315717514047), big.NewInt(101741582076661)
offset, increment := big.NewInt(0), big.NewInt(1)
for _, s := range d.shuffles {
switch s.instruction {
case day22InstructionNewStack:
increment.Mul(increment, big.NewInt(-1))
offset.Add(offset, increment)
case day22InstructionCut:
offset.Add(offset, big.NewInt(0).Mul(big.NewInt(int64(s.arg)), increment))
case day22InstructionDealIncrement:
increment.Mul(increment, big.NewInt(0).Exp(big.NewInt(int64(s.arg)), big.NewInt(0).Sub(n, big.NewInt(2)), n))
}
}
finalIncr := big.NewInt(0).Exp(increment, iter, n)
finalOffs := big.NewInt(0).Exp(increment, iter, n)
finalOffs.Sub(big.NewInt(1), finalOffs)
invmod := big.NewInt(0).Exp(big.NewInt(0).Sub(big.NewInt(1), increment), big.NewInt(0).Sub(n, big.NewInt(2)), n)
finalOffs.Mul(finalOffs, invmod)
finalOffs.Mul(finalOffs, offset)
answer := big.NewInt(0).Mul(big.NewInt(2020), finalIncr)
answer.Add(answer, finalOffs)
answer.Mod(answer, n)
return fmt.Sprintf("Card at position 2020: %s%d%s", u.TextBold, answer, u.TextReset)
}

View File

@ -1,170 +0,0 @@
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)
}

View File

@ -1,289 +0,0 @@
package days
import (
"fmt"
"math"
u "parnic.com/aoc2019/utilities"
)
var (
day24AdjacentOffsets = []u.Vec2i{
{X: -1, Y: 0},
{X: 1, Y: 0},
{X: 0, Y: -1},
{X: 0, Y: 1},
}
)
type Day24 struct {
grid [][]bool
}
func (d *Day24) Parse() {
lines := u.GetStringLines("24p")
d.grid = make([][]bool, len(lines))
for i, line := range lines {
d.grid[i] = make([]bool, len(line))
for j, ch := range line {
d.grid[i][j] = ch == '#'
}
}
}
func (d Day24) Num() int {
return 24
}
func (d Day24) calcActivatedNeighbors(grid [][]bool, i, j int) int {
activatedNeighbors := 0
for _, o := range day24AdjacentOffsets {
newI := i + o.X
newJ := j + o.Y
if newI < 0 || newI >= len(grid) || newJ < 0 || newJ >= len(grid[i]) {
continue
}
if grid[newI][newJ] {
activatedNeighbors++
}
}
return activatedNeighbors
}
func (d Day24) recursiveCalcActivatedNeighbors(gridMap map[int][][]bool, mapIdx, i, j int) int {
activatedNeighbors := 0
numNeighbors := 0
thisGrid := gridMap[mapIdx]
for _, o := range day24AdjacentOffsets {
newI := i + o.X
newJ := j + o.Y
if newI < 0 || newI >= len(thisGrid) || newJ < 0 || newJ >= len(thisGrid[i]) {
continue
}
if newI == 2 && newJ == 2 {
continue
}
numNeighbors++
if thisGrid[newI][newJ] {
activatedNeighbors++
}
}
checkLower := (i == 1 && j == 2) ||
(i == 2 && (j == 1 || j == 3)) ||
(i == 3 && j == 2)
if checkLower {
if lowerGrid, exists := gridMap[mapIdx+1]; exists {
if i == 1 {
for _, b := range lowerGrid[0] {
numNeighbors++
if b {
activatedNeighbors++
}
}
} else if i == 2 {
if j == 1 {
for _, r := range lowerGrid {
numNeighbors++
if r[0] {
activatedNeighbors++
}
}
} else if j == 3 {
for _, r := range lowerGrid {
numNeighbors++
if r[len(lowerGrid[0])-1] {
activatedNeighbors++
}
}
}
} else if i == 3 {
for _, b := range lowerGrid[len(lowerGrid)-1] {
numNeighbors++
if b {
activatedNeighbors++
}
}
}
}
}
checkUpper := (i == 0) || (i == len(thisGrid)-1) ||
((i != 0 && i != len(thisGrid)) && (j == 0 || j == len(thisGrid[0])-1))
if checkUpper {
if upperGrid, exists := gridMap[mapIdx-1]; exists {
if i == 0 {
numNeighbors++
if upperGrid[1][2] {
activatedNeighbors++
}
} else if i == len(thisGrid)-1 {
numNeighbors++
if upperGrid[3][2] {
activatedNeighbors++
}
}
if j == 0 {
numNeighbors++
if upperGrid[2][1] {
activatedNeighbors++
}
} else if j == len(thisGrid[0])-1 {
numNeighbors++
if upperGrid[2][3] {
activatedNeighbors++
}
}
}
}
return activatedNeighbors
}
func (d Day24) calcRating(grid [][]bool) int {
rating := 0
for i, r := range grid {
for j := range r {
pow := (i * len(r)) + j
if grid[i][j] {
result := int(math.Pow(2, float64(pow)))
rating += result
}
}
}
return rating
}
func (d Day24) getNumBugs(gridMap map[int][][]bool) int {
ret := 0
for _, v := range gridMap {
for _, r := range v {
for _, b := range r {
if b {
ret++
}
}
}
}
return ret
}
func copy2d[T comparable](dest [][]T, src [][]T) {
for i, r := range src {
copy(dest[i], r)
}
}
func (d Day24) Draw(grid [][]bool) {
for _, r := range grid {
for _, c := range r {
if c {
fmt.Print("#")
} else {
fmt.Print(".")
}
}
fmt.Println()
}
fmt.Println()
}
func (d *Day24) Part1() string {
grid := make([][]bool, len(d.grid))
scratch := make([][]bool, len(grid))
for i, g := range d.grid {
grid[i] = make([]bool, len(g))
scratch[i] = make([]bool, len(g))
copy(grid[i], d.grid[i])
}
found := false
answer := 0
seenRatings := make([]int, 0)
for i := 1; !found; i++ {
// d.Draw(grid)
for i, r := range grid {
for j := range r {
numActivated := d.calcActivatedNeighbors(grid, i, j)
if grid[i][j] {
scratch[i][j] = numActivated == 1
} else {
scratch[i][j] = numActivated == 1 || numActivated == 2
}
}
}
rating := d.calcRating(scratch)
if u.ArrayContains(seenRatings, rating) {
found = true
// d.Draw(scratch)
answer = rating
}
seenRatings = append(seenRatings, rating)
copy2d(grid, scratch)
}
return fmt.Sprintf("First repeated biodiversity rating is %s%d%s", u.TextBold, answer, u.TextReset)
}
func (d *Day24) Part2() string {
makeGrid := func(initialGrid [][]bool) ([][]bool, [][]bool) {
grid := make([][]bool, len(d.grid))
scratch := make([][]bool, len(grid))
for i, g := range d.grid {
grid[i] = make([]bool, len(g))
scratch[i] = make([]bool, len(g))
if initialGrid != nil {
copy(grid[i], initialGrid[i])
}
}
return grid, scratch
}
gridMap := make(map[int][][]bool)
scratchMap := make(map[int][][]bool)
gridMap[0], scratchMap[0] = makeGrid(d.grid)
min := 0
max := 0
for i := 0; i < 200; i++ {
gridMap[min-1], scratchMap[min-1] = makeGrid(nil)
gridMap[max+1], scratchMap[max+1] = makeGrid(nil)
min, max = min-1, max+1
// if i == 10 {
// keys := u.MapKeys(gridMap)
// sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
// for _, k := range keys {
// fmt.Println("Depth", k)
// d.Draw(gridMap[k])
// }
// fmt.Println("# bugs:", d.numBugs(gridMap))
// }
for depth, grid := range gridMap {
for i, r := range grid {
for j := range r {
if i == 2 && j == 2 {
continue
}
numActivated := d.recursiveCalcActivatedNeighbors(gridMap, depth, i, j)
if grid[i][j] {
scratchMap[depth][i][j] = numActivated == 1
} else {
scratchMap[depth][i][j] = numActivated == 1 || numActivated == 2
}
}
}
}
for d := range gridMap {
copy2d(gridMap[d], scratchMap[d])
}
}
return fmt.Sprintf("Bugs present after 200 minutes: %s%d%s", u.TextBold, d.getNumBugs(gridMap), u.TextReset)
}

View File

@ -1,61 +0,0 @@
package days
import (
"bufio"
"fmt"
"os"
"strings"
u "parnic.com/aoc2019/utilities"
)
type Day25 struct {
program u.IntcodeProgram
}
func (d *Day25) Parse() {
d.program = u.LoadIntcodeProgram("25p")
}
func (d Day25) Num() int {
return 25
}
func (d *Day25) Part1() string {
lastCmdStrings := make([]string, 0)
sb := strings.Builder{}
inReader := bufio.NewReader(os.Stdin)
d.program.SetDebugASCIIPrint(true)
d.program.RunIn(func(inputStep int) int64 {
lastCmdStrings = lastCmdStrings[:0]
text, _ := inReader.ReadString('\n')
d.program.FeedInputString(text[1:])
return int64(text[0])
}, func(val int64, state u.IntcodeProgramState) {
if val == '\n' {
str := sb.String()
if len(str) > 0 {
lastCmdStrings = append(lastCmdStrings, sb.String())
sb.Reset()
}
} else {
sb.WriteRune(rune(val))
}
})
lastString := lastCmdStrings[len(lastCmdStrings)-1]
var answer string
if idx := strings.Index(lastString, " by typing "); idx >= 0 {
startIdx := idx + len(" by typing ")
endIdx := startIdx + strings.Index(lastString[startIdx:], " ")
answer = lastString[startIdx:endIdx]
}
return fmt.Sprintf("Door passcode: %s%s%s", u.TextBold, answer, u.TextReset)
}
func (d *Day25) Part2() string {
return "There is no part 2"
}

View File

@ -1 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,252,1,1023,1102,36,1,1008,1102,24,1,1017,1101,25,0,1013,1102,479,1,1026,1101,0,259,1022,1102,1,38,1001,1102,1,713,1024,1101,0,708,1025,1102,1,22,1006,1101,0,32,1010,1101,476,0,1027,1102,1,516,1029,1102,1,34,1009,1101,0,23,1016,1102,1,37,1011,1102,525,1,1028,1101,0,35,1004,1102,31,1,1002,1102,39,1,1019,1102,28,1,1015,1102,1,1,1021,1101,0,30,1007,1101,0,27,1014,1101,21,0,1018,1101,0,29,1005,1102,26,1,1000,1102,1,0,1020,1101,0,20,1012,1101,33,0,1003,109,13,21108,40,40,6,1005,1019,199,4,187,1106,0,203,1001,64,1,64,1002,64,2,64,109,15,1205,-7,221,4,209,1001,64,1,64,1105,1,221,1002,64,2,64,109,-25,1208,-3,26,63,1005,63,243,4,227,1001,64,1,64,1106,0,243,1002,64,2,64,109,25,2105,1,-5,1001,64,1,64,1106,0,261,4,249,1002,64,2,64,109,-4,21108,41,42,-8,1005,1016,281,1001,64,1,64,1106,0,283,4,267,1002,64,2,64,109,-6,1206,2,301,4,289,1001,64,1,64,1105,1,301,1002,64,2,64,109,-4,21102,42,1,2,1008,1016,42,63,1005,63,323,4,307,1106,0,327,1001,64,1,64,1002,64,2,64,109,-7,2108,35,1,63,1005,63,343,1105,1,349,4,333,1001,64,1,64,1002,64,2,64,109,-13,1208,7,35,63,1005,63,369,1001,64,1,64,1106,0,371,4,355,1002,64,2,64,109,24,21102,43,1,-1,1008,1017,42,63,1005,63,391,1105,1,397,4,377,1001,64,1,64,1002,64,2,64,109,-13,2101,0,-4,63,1008,63,38,63,1005,63,419,4,403,1105,1,423,1001,64,1,64,1002,64,2,64,109,21,1206,-5,435,1106,0,441,4,429,1001,64,1,64,1002,64,2,64,109,-22,21101,44,0,10,1008,1014,44,63,1005,63,463,4,447,1105,1,467,1001,64,1,64,1002,64,2,64,109,25,2106,0,-2,1106,0,485,4,473,1001,64,1,64,1002,64,2,64,109,-19,2107,37,-2,63,1005,63,501,1106,0,507,4,491,1001,64,1,64,1002,64,2,64,109,8,2106,0,10,4,513,1001,64,1,64,1105,1,525,1002,64,2,64,109,-6,21107,45,46,0,1005,1012,547,4,531,1001,64,1,64,1105,1,547,1002,64,2,64,109,-5,1202,-1,1,63,1008,63,21,63,1005,63,567,1105,1,573,4,553,1001,64,1,64,1002,64,2,64,109,2,1207,-3,21,63,1005,63,589,1105,1,595,4,579,1001,64,1,64,1002,64,2,64,109,1,1201,-8,0,63,1008,63,34,63,1005,63,619,1001,64,1,64,1106,0,621,4,601,1002,64,2,64,109,-6,2102,1,-1,63,1008,63,33,63,1005,63,643,4,627,1105,1,647,1001,64,1,64,1002,64,2,64,109,10,21101,46,0,3,1008,1017,43,63,1005,63,667,1106,0,673,4,653,1001,64,1,64,1002,64,2,64,109,-13,2102,1,8,63,1008,63,35,63,1005,63,697,1001,64,1,64,1106,0,699,4,679,1002,64,2,64,109,23,2105,1,0,4,705,1105,1,717,1001,64,1,64,1002,64,2,64,109,-1,1205,-3,729,1106,0,735,4,723,1001,64,1,64,1002,64,2,64,109,-15,2101,0,0,63,1008,63,38,63,1005,63,755,1106,0,761,4,741,1001,64,1,64,1002,64,2,64,109,-2,2107,28,-1,63,1005,63,779,4,767,1106,0,783,1001,64,1,64,1002,64,2,64,109,-2,2108,35,0,63,1005,63,801,4,789,1105,1,805,1001,64,1,64,1002,64,2,64,109,1,1201,-5,0,63,1008,63,26,63,1005,63,831,4,811,1001,64,1,64,1105,1,831,1002,64,2,64,109,-5,1207,5,30,63,1005,63,849,4,837,1106,0,853,1001,64,1,64,1002,64,2,64,109,2,1202,-2,1,63,1008,63,26,63,1005,63,879,4,859,1001,64,1,64,1105,1,879,1002,64,2,64,109,15,21107,47,46,0,1005,1017,899,1001,64,1,64,1105,1,901,4,885,4,64,99,21102,1,27,1,21101,915,0,0,1106,0,922,21201,1,66416,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,942,1,0,1105,1,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1105,1,968,22102,1,-2,-2,109,-3,2105,1,0
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,3,0,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,31,1018,1102,352,1,1023,1101,0,1,1021,1101,0,33,1003,1102,1,36,1007,1102,21,1,1005,1101,359,0,1022,1101,0,787,1024,1102,1,24,1011,1101,30,0,1014,1101,22,0,1016,1101,0,0,1020,1102,1,29,1000,1101,778,0,1025,1102,23,1,1017,1102,1,28,1002,1101,38,0,1019,1102,1,27,1013,1102,1,32,1012,1101,0,37,1006,1101,444,0,1027,1102,1,20,1009,1101,0,447,1026,1101,0,39,1008,1101,35,0,1010,1102,559,1,1028,1102,26,1,1004,1102,1,25,1015,1102,1,34,1001,1101,0,554,1029,109,-3,2101,0,9,63,1008,63,34,63,1005,63,205,1001,64,1,64,1105,1,207,4,187,1002,64,2,64,109,23,21107,40,39,-7,1005,1013,227,1001,64,1,64,1106,0,229,4,213,1002,64,2,64,109,-17,1202,-2,1,63,1008,63,36,63,1005,63,249,1106,0,255,4,235,1001,64,1,64,1002,64,2,64,109,-6,1202,10,1,63,1008,63,36,63,1005,63,277,4,261,1106,0,281,1001,64,1,64,1002,64,2,64,109,-2,1208,9,26,63,1005,63,303,4,287,1001,64,1,64,1106,0,303,1002,64,2,64,109,32,1206,-7,321,4,309,1001,64,1,64,1106,0,321,1002,64,2,64,109,-29,1207,7,20,63,1005,63,337,1105,1,343,4,327,1001,64,1,64,1002,64,2,64,109,27,2105,1,-2,1001,64,1,64,1106,0,361,4,349,1002,64,2,64,109,-25,2108,39,7,63,1005,63,377,1106,0,383,4,367,1001,64,1,64,1002,64,2,64,109,1,1201,6,0,63,1008,63,36,63,1005,63,409,4,389,1001,64,1,64,1105,1,409,1002,64,2,64,109,1,2102,1,1,63,1008,63,33,63,1005,63,435,4,415,1001,64,1,64,1105,1,435,1002,64,2,64,109,28,2106,0,-3,1106,0,453,4,441,1001,64,1,64,1002,64,2,64,109,-13,21101,41,0,1,1008,1018,44,63,1005,63,477,1001,64,1,64,1106,0,479,4,459,1002,64,2,64,109,4,21108,42,42,-2,1005,1019,501,4,485,1001,64,1,64,1106,0,501,1002,64,2,64,109,-21,2101,0,2,63,1008,63,28,63,1005,63,523,4,507,1105,1,527,1001,64,1,64,1002,64,2,64,109,26,1205,-5,545,4,533,1001,64,1,64,1105,1,545,1002,64,2,64,109,3,2106,0,-1,4,551,1106,0,563,1001,64,1,64,1002,64,2,64,109,-33,1201,4,0,63,1008,63,28,63,1005,63,583,1105,1,589,4,569,1001,64,1,64,1002,64,2,64,109,11,2107,27,-3,63,1005,63,609,1001,64,1,64,1106,0,611,4,595,1002,64,2,64,109,8,21102,43,1,3,1008,1018,43,63,1005,63,637,4,617,1001,64,1,64,1105,1,637,1002,64,2,64,109,-5,21108,44,41,0,1005,1010,653,1105,1,659,4,643,1001,64,1,64,1002,64,2,64,109,-13,2108,21,8,63,1005,63,681,4,665,1001,64,1,64,1106,0,681,1002,64,2,64,109,6,1207,0,34,63,1005,63,703,4,687,1001,64,1,64,1105,1,703,1002,64,2,64,109,7,1208,-7,35,63,1005,63,723,1001,64,1,64,1106,0,725,4,709,1002,64,2,64,109,-13,2102,1,7,63,1008,63,23,63,1005,63,745,1105,1,751,4,731,1001,64,1,64,1002,64,2,64,109,13,1205,10,767,1001,64,1,64,1105,1,769,4,757,1002,64,2,64,109,14,2105,1,0,4,775,1001,64,1,64,1106,0,787,1002,64,2,64,109,-20,21107,45,46,7,1005,1011,809,4,793,1001,64,1,64,1105,1,809,1002,64,2,64,109,-3,2107,25,3,63,1005,63,827,4,815,1106,0,831,1001,64,1,64,1002,64,2,64,109,13,1206,7,847,1001,64,1,64,1106,0,849,4,837,1002,64,2,64,109,-11,21101,46,0,7,1008,1010,46,63,1005,63,871,4,855,1106,0,875,1001,64,1,64,1002,64,2,64,109,15,21102,47,1,-4,1008,1014,48,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21102,27,1,1,21101,0,915,0,1106,0,922,21201,1,63208,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1105,1,922,22201,1,-1,-2,1106,0,968,21201,-2,0,-2,109,-3,2106,0,0

View File

@ -1,4 +1,4 @@
<x=14, y=4, z=5>
<x=12, y=10, z=8>
<x=1, y=7, z=-10>
<x=16, y=-5, z=3>
<x=-6, y=-5, z=-8>
<x=0, y=-3, z=-13>
<x=-15, y=10, z=-11>
<x=-3, y=-8, z=3>

File diff suppressed because one or more lines are too long

View File

@ -1,113 +1,125 @@
G R U E Z S S
W N C K Z G D
#################################.###########.###.#######.#########.#.#######.#####################################
#.#.......#.#.........#.#.#.....#.#.....#.#.#...#.....#.........#.....#...#.#...........#.......#.....#.....#.#...#
#.#####.###.###.###.#.#.#.###.###.#.###.#.#.###.#.###.###.#####.#.###.###.#.###.#########.###.###.#######.###.#.###
#.#.#.#...#...#.#.#.#.................#.#...#...#.#.#...#.#.....#.#.#.#.....................#.#.......#.........#.#
#.#.#.#.###.#####.#########.###########.#.#.#.###.#.#######.###.#.#.#####.###.#.###.#.###.#.###.#######.#######.#.#
#...#...#.#.#.#.........#...#...#.......#.#...#.......#.....#.#.#.....#.....#.#...#.#.#...#.#...#.#.........#.#.#.#
#.#.###.#.#.#.#####.#.#.#######.#.#######.###.#.###.#####.###.#####.#.###.#########.#.#.#######.#.#####.#####.#.#.#
#.#...#.#.#.#.#.....#.#.................#.#...#.#.#.....#...#.#.#...#...#.#.....#.#.#.#...#.#.#...........#.#.....#
###.###.#.#.#.#.#.#####.#.###.#########.#.#######.#.#####.###.#.#.#.#####.#.#.###.#.#######.#.#.###.#######.###.#.#
#...#.......#...#.#.#.#.#...#.#.........#.....#.......#.#.......#.#...#.....#.....#.#...#.........#...#.#.#.#.#.#.#
###.#######.#######.#.###########.#.#####.###.#####.###.#.#####.#.###.#.#.###.#.#######.###.#####.#####.#.#.#.#####
#.......#.#...#.......#.........#.#.#...#.#.#.#.....#.....#...#.#...#.#.#.#...#...#...#...#...#.#.#...........#.#.#
#.#.###.#.#.#########.#########.#.###.###.#.#####.#.###.#.#.#.#.#.###########.#.###.###.###.###.###.###.#.#####.#.#
#.#...#.....#.#...#.#.#.#.#.............#.....#...#...#.#.#.#...#...#.#.#.....#.........#...#.......#...#...#...#.#
###########.#.#.###.#.#.#.#######.#####.#.#####.#.#######.#####.###.#.#.#####.#.#.###.#####.###.#############.#.#.#
#.#.#.#.#.....#.#.....#.#.#.#.....#...#.#.....#.#.....#...#.#.#...#...#.#.#...#.#...#...#...#...#...#.#.......#.#.#
#.#.#.#.###.###.#####.#.#.#.#####.#.###.#.#########.#######.#.#.###.###.#.#.###.###.#####.#####.#.###.#####.#####.#
#.#...#.#...#.#.#...#...#.#.....#.#.....#.#...#.....#.......#.#.#...#.....#.#.#.#.......#.......#...#.#.#...#.#...#
#.#.#.#.###.#.#.###.#.###.#.#####.#.###.#.###.###.###.#.#.###.#.#.###.#.#.###.#.###.#####.#.#####.###.#.###.#.###.#
#.#.#.#.#...#.#...#...#.#.#...#...#...#.#.#.....#.#...#.#.#.....#.#...#.#.#.......#.......#...#.#.....#.........#.#
#.#.###.###.#.#.#####.#.#.#.###.#.#####.#.#.###.#.###.#.###.#.###.#.###.#####.#####.#####.#####.###.#########.#.#.#
#.....#...#.......#.#.#.......#.#.#...#.#...#.#.#.....#...#.#...#...#.#...#.......#...#.#...#...#...#.#.#.#.#.#.#.#
###.###.#######.###.#.#.#.#.#########.#.#####.#.#.#####.#######.#####.#.#####.#.#.###.#.#######.###.#.#.#.#.#.###.#
#.....#...#.#.#.......#.#.#.#.#.......#...#.....#.#.....#.......#.......#.#...#.#.#.#...#.....#.#.....#.#.#...#.#.#
###.###.###.#.#######.#.#####.#####.#.#.###.#########.#.###.#.#####.#####.###.#####.#######.###.###.###.#.#.###.#.#
#.....#.......#...#...#...#.#.#.#.#.#.#.#.......#.#...#.#.#.#...#.......#...#.......#...#.....#...#.#.........#...#
#.#####.#######.###.#.#.###.#.#.#.#.#.#.###.#.###.#.#####.#####.#####.#####.###.#######.###.###.###.#########.#.###
#...#...#...#.#.#...#.#.#.#.........#.....#.#.....#.......#.......#...#.............#...#...#.#.........#...#.#...#
#.###.###.###.#.#####.#.#.#.#####.#############.#######.#####.#####.#######.###########.###.#.###.#######.###.#.###
#...#...#...#...#.#...#...#.# S L B V G R #.#.#.#.....#.#.......#.#...#
#.###.#.#.#####.#.###.#.###.# D M E H X Q #.#.#.#####.#.###.#####.#.###
#.....#.#.................#.# #.........................#.#
#.###.###.#####.#.#.#.###.### #.#.#.###.#######.###.#.#.#.#
#.#.#.....#.#...#.#.#.#.....# RZ..#.#...#.....#.#...#.#.#.#..BE
#.#.#####.#.#####.#.#####.### #######.#####.#.#.#######.#.#
#.....#.#.....#.#.#.....#.#.# #.#.#.#.#.#...#.......#...#.#
###.###.###.#.#.#.#.###.#.#.# #.#.#.###.#####.#.#######.#.#
RI....#.....#.#.#...#.#.#.#....UW #.#.......#...#.#.#.#...#...#
#####.###############.###.### #.###.#####.#.#####.#.#.#####
#.....#.#.#...#.#.....#.#...# GW..........#.#.........#.#...#
#.###.#.#.#.###.###.###.##### #.###.#.#.###.#######.###.###
#...#...#.....#.#.......#....FM #.#...#.#.....#...#.........#
###.###.#.#.#.#.#.#########.# ###.#######.###.###########.#
AJ..#...#...#.#...#...#.....#.# #...#.#.#...#...#.#...#.#.#..GX
#.#.#########.#.#.#######.#.# #####.#.#######.#.###.#.#.###
#.....#.#.#.#.#.............# #...............#...#........DD
#######.#.#.###########.###.# ###.#######.###.#.#.#.#.###.#
#.....................#.#...# #.......#.....#...#.#.#.#...#
###.###.#.#.###.#####.####### #####.#########.###.#.###.###
GP..#...#.#.#.#.....#.#...#...# SG..#...#.....#...#.#.....#...#
#.###.#####.#.#.#.#.###.###.# #.#.###.#.#######.#######.###
#.#.....#.#.#.#.#.#.....#...# #.....#.#.#.#...#.#.#...#.#.#
#.#.#####.#########.#######.# #########.#.###.#.#.#.#####.#
#.....#...#..................SI DD....#........................UW
#.#######.#####.###.###.##### #.###.#####.#.###.#.###.#####
#.#.#...#...#.....#.#.#.#.#..AJ #.........#.#.#.#.#.#.....#.#
###.#.###.#.#########.###.#.# #.#####.###.#.#.#######.###.#
#.........#.#...#.....#.#.#.# #...#.....#.#...#.#.#.#.#....LM
#########.#.###.#.###.#.#.#.# #########.#.#.###.#.#.#####.#
AA......#.#.#.....#.#...#.....# #.#.#.#.#.#.#.#...#.#.#.....#
#.#####.#.#.###.#.#.###.#.### #.#.#.#.#########.#.#.#####.#
JO..........#...#...#.....#...# #.#.......#.#.............#.#
#####.###############.###.#.# #.#.#.#####.###.###.#.###.#.#
#.#.#...#.........#.#.#.#.#.# TX....#.............#.#...#...#
#.#.#######.#.#.#.#.###.###.# #.###.#.###.#####.###########
VH......#.....#.#.#.....#...#.# #.#...#.#...#...#.#.....#...#
#####.#.###########.###.##### #############.#####.###.#.#.#
#.....#.....#.#.......#.....# #.#...#...#.#.......#.#.#.#..RZ
#.#.#######.#.#######.#.##### #.###.###.#.###.#.###.#.#.###
#.#...........#.#............FW RN..#.....#...#.#.#.#.....#...#
#########.###.#.#.########### #.#.#.###.###.###.#.#####.###
#...#...#.#.....#.#.........# #...#.............#.......#.#
#.#.#.#################.#.#.# ###############.###########.#
AX..#...#.#...#.#...#...#.#.#..HR JO............#.#.#...........#
#.#.###.###.#.#.#####.###.#.# #.#.#####.#.#.###.#.#.#####.#
TX..#...#.......#...#.....#.#..EK #.#...#.#.#.......#.#...#.#..MM
###.#.###.#.#.#.#.###.#.#.### #.###.#.#######.#.###.###.#.#
#...#.....#.#...#.....#.....# #.#.#.....#.#...#...#.#.....#
#####.#.#.#####.###.#######.# R Y G U A M S #.#.#.#.###.#####.#.#.###.#.#
#.....#.#...#.....#.....#...# I Q P C X M Y #...#.#.#.....#...#.#...#.#.#
#####.#########.###.#####.###########.#####.###.###########.#####.###########.#.#######.#.###.#.#########.#.#####.#
#...#...#.#.......#.....#...#...#.....#.....#.....#.#.....#...#...........#...#...#...#.#.#.....#.#.......#.#.....#
#.#.#.###.###.#.#.#######.#####.###.###.###.#####.#.###.#.#.#########.#####.#####.#.#########.###.###.#####.###.#.#
#.#.......#...#.#.#.......#.....#.#.#.....#.#.....#...#.#.......#.#.#...#.......#.#.......#.#.#.#.....#.......#.#.#
#.#.#.#.#####.###########.#####.#.#.#.#.#.#####.###.###.#########.#.#.#######.###.#.#######.###.###.#.###.#.#.#.#.#
#.#.#.#...#.......#.......#.........#.#.#.....#.#.....#.........#.........#.#.#.....#.......#.......#.#.#.#.#.#.#.#
#######.#.#.#.#####.#.#########.#############.#.#.###.#######.#####.#.#####.#.#.#######.#####.#.#.###.#.#.#######.#
#.......#.#.#...#...#.#.........#.......#...#.#.....#.#.......#.....#...#.....#...........#.#.#.#.#.....#...#.....#
#.#.#.#####.#.#.#####.#.#######.#.###.###.###.#.###.#.#.###.#.#.#.###.#.#####.#.###.#.#.###.###.#.#.#.#####.#####.#
#.#.#.#.....#.#.#.....#...#.#.....#...#.......#.#...#.#...#.#.#.#...#.#.#.....#.#...#.#.......#.#.#.#...#.#.#.....#
#.###.###.#.###.###.#.#.###.#.#.#.#.###.###.#.#######.###.#.###.#######.#.#.#.#####.#.#.#.#############.#.#####.###
#.#.#.#.#.#...#.#...#.#.#.....#.#.#...#...#.#...#.....#...#...#...#.....#.#.#.....#.#.#.#.#.....#.#.#.......#...#.#
###.#.#.#.#.###.#####.#############.#.#.#.#.#######.###.###.###.#############.#####.#####.###.###.#.#.#####.###.#.#
#.......#.#.#.....#...#.#.......#...#.#.#.#.#.#.#.#...#...#.#.....#.#.#...#.....#.#.#...#...#.......#.....#...#...#
###.###.#.###.#########.#######.#####.#.#####.#.#.#.###.#######.###.#.#.#####.###.#.#.###.###.#####.#.#.###.###.###
#.....#.#.#.....#.....#.#.......#.#.#.#...#.......#.#.......#...#.....#.......#.........#.#.#.....#.#.#.#...#.....#
#.#####.#.###.#.#####.#.#######.#.#.#.#.#######.#.#.###.#####.#.###.#.###.#.#####.###.#####.#.#######.###.#.#.#.###
#.#.....#.#...#...#.......#.#.....#...#.#.#.....#...#.......#.#.....#.#...#...#.#...#...#.#.#.....#.#.#.#.#.#.#...#
#####.#.#.###.#######.#.###.###.#.#.###.#.#####.#######.#######.#.#####.###.###.###.#####.#.#.#####.###.#######.#.#
#.#.#.#.#.#.#.#...#...#...#.#.#.#...#.......#.#.....#.#.#...#...#.....#.#.......#.........#.#...#.#.........#.#.#.#
#.#.#######.#####.#####.###.#.#.#########.###.#####.#.#.#.#######.#########.#.###.#########.###.#.#.#########.#.#.#
#...#.#.#.#.....#.#...................#...#...#...#...#.....#...#.#...#...#.#.#.....#.#.......#.#.#.#.#.#.#...#.#.#
###.#.#.#.#.###.#.#####.#############.###.#.#.#.#.###.#.#.#####.#.#.#####.###.#.###.#.#####.###.#.#.#.#.#.###.#.###
#...........#.#.#...#...#.#.......#.#...#...#.#.#...#.#.#...#.#.......#.....#.#...#.#.#.#.#.....#.....#.#.....#...#
#####.#.#.#.#.###.#####.#.#.#.###.#.#.#######.#.###.#.#.###.#.#####.###.###.#.#.###.#.#.#.#.#####.###.#.#.#########
#.#...#.#.#.............#...#...#...#.....#...#...#...#.#.#.#...#...#...#.#...#.#...................#.............#
#.#####.#######.#.###.###.#.#.#####.#.#######.###.#####.#.###.#.#.#####.#.###.#.#.#####.###.#####.###.#.###.#.#####
#.......#.......#...#...#.#.#.#.........#.....#.....#.......#.#.......#.....#.#.#.....#...#.....#...#.#...#.#.....#
###################################.#######.###.#########.#######.#########.#######.###############################
Y S R S F F H
Q Y Q I M W R
J L P P V T X
G V M I O R C
#######################################.#######.###.###########.###.#.#######.#########################################
#...#.........#.#...#.#...#.........#.....#.#.....#.......#...#...#.....#.#...........#...........#.......#...#.......#
###.#########.#.#.###.#.#######.###.###.###.#####.#.###.###.#####.###.###.#####.#.#######.#####.###.#.#####.#####.#####
#.#.....#...........#...#...#.#.#.....#.....#.#...#.#.....#.#.#.....#.....#.....#.#.#.#.......#.#...#.....#.#.#.....#.#
#.#####.#####.###.#####.###.#.#######.#.#.###.#.#####.###.#.#.#.#########.#.#.#####.#.###.#######.#.#######.#.###.###.#
#...#...#.....#...#.#...#.#.#...#.#.....#.#.......#...#.#.#...#.#.#.......#.#.#...............#.#.#.........#.#.#.....#
###.#.#.#########.#.###.#.#.#.###.#.#.#########.#####.#.#.#.#.#.#.###.#####.###.#.#.#.###.#.###.###.#######.#.#.#.#####
#.....#...#.....#.........#...#.#...#.........#.....#.#...#.#.....#.....#.#.#...#.#.#.#...#...........#...#.........#.#
#########.#####.#.#.#.#.#.###.#.#######.#####.###.#####.###.###.###.#####.#.#.###.#.#.###.#.#####.#.###.#########.###.#
#.#.........#.....#.#.#.#.#.......#.......#.#.#.......#.#...#.#...#...#...#.....#.#.#...#.#.....#.#.............#.#...#
#.###.###.#####.#########.###.#####.###.#.#.#####.#####.###.#.###.#.###.###.#.###.#######.###.#.#.#.#######.#####.###.#
#...#...#.....#.#.#...#.........#...#...#.#.....#.#.#.....#...#...#.......#.#.#.........#...#.#.#.#.......#.#...#.#.#.#
#.#########.###.#.#.#####.#.###.###.#######.###.#.#.#.###.###.###.#.#.#.###.#####.#.###.#.#.###.#.#.#.#######.#.###.#.#
#...#.......#.#.#.....#.#.#.#...........#.....#.....#.#...#.....#.#.#.#.#.......#.#.#...#.#.#.#.#.#.#...#...#.#.#.#...#
#.#########.#.###.###.#.###########.#########.###########.#.###.###.###.#########.#########.#.#####.#.###.###.###.###.#
#...#.#.#.......#.#.....#.....#.....#.#.......#.#...#.#...#...#.#.#.#.#.#...#...........#.#.....#...#.....#...#.......#
###.#.#.#####.#####.###.#####.#####.#.#####.###.###.#.###.#.#####.#.#.###.#######.#######.#.#######.#.###.###.#####.###
#.....#.#.#.#.....#.#.#.........#.#.....#.#...........#...#.....#.........#...#...#...#...#.#.#...#.#.#.#...#.#.#.....#
#.#.#.#.#.#.#.#######.#########.#.###.###.###.#####.#####.#.#######.#########.###.###.###.###.#.#####.#.#####.#.#.#.###
#.#.#.......#.....#.#.#.#.#.#.#.#.....#...#...#.#.#.#...#.#.#.#.#.....#...#...#...#...#.....#.....#.#.#.#...#...#.#.#.#
#####.#####.#.#####.#.#.#.#.#.#.###.#####.#.###.#.###.###.#.#.#.#.#.###.###.#.#.#####.#.#.#######.#.###.#.#####.###.#.#
#.#.#.#.....#.....#.......................#...#...#.......#.....#.#.#.......#.#.........#...#.#.#.#...#.....#.#.#.....#
#.#.#######.#.#######.###.#.#####.#######.#.#####.#.#.###.###.#####.#######.#.###.#######.#.#.#.#.#.#####.###.#.###.###
#...#...........#.#.#.#...#.#...#.#...#.#.#.....#...#...#.#...#...........#.#...#.....#.#.#...........#...#...#.#...#.#
###.#.#.###.#.###.#.#.#.#####.#####.###.#.#.#######.#.#.#.#.###########.###.###.#.#.#.#.#.#.#.#.###.#.###.###.#.#.#.#.#
#.....#.#.#.#.#.....#.#...#...#.#.#.....#.#.....#...#.#.#.#...#.#.#...#.#...#.#.#.#.#.#.#.#.#.#.#.#.#...#.......#.#...#
###.#.#.#.#.#####.###########.#.#.#.###.#.#.#####.#.#######.###.#.#.#.#.#.#.#.#.#.#####.#.#######.#######.#.###.#.#####
#.#.#.#.#...#.#.......#.......#.....#.#.#.#...#.#.#.......#.......#.#...#.#.#.#...#.#...#.#...#...#...#...#.#...#.....#
#.#########.#.###.#.#####.#.#.#####.#.#.#.###.#.###.###.#########.#.#######.#.#####.###.###.###.#####.#########.###.###
#.....#.#.#.#.....#...#...#.#.#.......#...#.....#.....#...#.......#.....#.................#...#...#.........#.#.#.#...#
#.#####.#.#.#######.#######.#########.#########.#########.#.#########.#.#######.#########.#.###.#####.#######.#.#.#.###
#.....#.#.#.#...#.#.#.#.#.#...# F O O X N U W #.#.....#.#.#...#.#.#.........#
#.#####.#.#.#.###.#.#.#.#.#.### Z G D L B Y W ###.#####.#.###.#.#.###.###.###
#...#.#.#.#.#.#...#.......#...# #.......#.....#...#...#.#.#...#
#.###.#.#.#.#.###.#.#.###.#.#.# #.#.#######.###.#.###.#.#.#.###
PL....#.#.#...#...#...#...#...#.# #.#.#.#.#...#.#.#.....#.#.#.#.#
#.###.#.###.#.###.#.#.#.###.#.# #.###.#.#.###.###.#######.#.#.#
#.......#.#.......#.#.#.#...#..EL PM..#.........#.#.....#.#.......#
#.#.#.###.###.#.#.###########.# #.###.###.###.#.#.#.#.###.###.#
#.#.#.........#.#.#.....#...#.# #.#.#...#.......#.#.......#....BR
#############.#.#####.###.##### #.#.###.#########.#.#.###.###.#
YP..#.........#.#...#.#.#.#.....# #.#...#.....#.#.#.#.#...#...#.#
#.#.###.#.#####.###.#.#.###.#.# #.#.#.###.###.#.###########.#.#
#...#.#.#.#.#.#.#...#.....#.#.# #...#.....#.#.#.#...#.#...#.#.#
#.###.###.#.#.###.#.#.#.###.### ###########.#.#.#.###.###.###.#
#...#.#...........#...#........TH #.......#...............#...#.#
###.#.#####################.### #.#####.#.###.###.#####.#.#.###
EV..#.#...#.................#...# LV..#.#.....#...#...#.#.#...#.#..UN
#.###.#.#####.#.###.#.#.###.### #.#.#.###.###.#.#.#.#.#####.#.#
#.#...#...#...#.#...#.#.#.#...# #.#...#.#.#.#.#.#.#.#.......#.#
#.#.#####.#.#.#.###.###.#.##### #######.###.#######.#.#######.#
#.#.#.....#.#.#...#.#.#.......# #.#.......#.....#.#.#.........#
#.#.#.#######.#######.###.#.#.# #.#####.#.###.###.#.###########
#...#...........#...#...#.#.#..XC #...#.#.#.........#...........#
#######.#########.###.###.##### #.#.#.###.###.###.###.#.#.#.###
WV..#.#.#.#...............#.#.#.# #.#...#.#.#.#.#.......#.#.#....OD
#.#.#.#.#.#.#.###.#####.###.#.# #.###.#.#.#.#########.#########
#.....#.#.#.#...#.#.....#.#.#..PI #.#.....#...#.....#.#.....#...#
#####.###.#####.#.#####.#.#.#.# #.#.#.#.###.###.###.#########.#
AA........#.....#.#.#...#.......# UN..#.#.#.....#...#...#.#.#.#...#
#.#######.###########.###.###.# ###.###########.###.#.#.#.###.#
#...........#.#.#.#.....#.#.#.# #...#...#.......#..............OA
#.#.#.#.#.#.#.#.#.###.#####.### #####.#.#.#.###.#.#.###.###.#.#
#.#.#.#.#.#.....#.............# #.#...#...#.#.....#.#...#...#.#
#################.#########.### #.#.###.#.#########.###########
#.....#.#.#.#.......#.....#...# #.#...#.#.#.......#.#.#.....#.#
#.#.###.#.#.#######.#.###.###.# #.#.###.#.#.#########.#.#####.#
#.#.#...#...#.#...#.....#.#.#.# SL....#.#.#.#.#.#.....#...#.#...#
#.#.#.#.#.###.#.#.#######.#.#.# #####.#####.#.#.#.#####.#.#.###
EL..#...#.........#.........#.#..WV #...............#.#.#..........XP
#.###########.###.#########.### #.#########.###.###.###.#####.#
#.#.......#...#...#...........# #.#.....#...#...#...#.......#.#
###.#####.###.#########.#.###.# #.#.###.#.#.#####.#.#####.#.#.#
UY..#...#.....#.#.........#.#....XP PL..#...#...#.#.#.#.#...#...#.#.#
#.#.###.#.###########.#.#.##### #.###.#######.#.###.#.#.#####.#
#.#.#...#.#.#.#.#.#...#.#.....# #...#...............#.....#.#.#
#.#.#.#####.#.#.#.###.###.##### #.#.###############.#.#.###.#.#
#...#...................#.....# #.#.#...........#...#.#.#...#.#
###############.############### #.#.###.#######.###########.###
#...........#.#.#.............# #.#.#.....#...........#...#.#.#
#####.#.#.###.###.#######.###.# #########.#.#.###########.#.#.#
#.....#.#.#.#.#.........#.#...# #.#.#.....#.#.#...#...#...#....TH
#.#####.###.#.#######.#####.### #.#.###.#.#.#########.###.#.#.#
ZZ....#...#...#.#...........#.#.# JG........#.#.................#.#
###.#.###.#.#.###.#.#.#####.#.# #.###.#.###.#.#.#####.###.#.###
JH....#.....#.......#.#...#......EV #.#...#...#.#.#...#.....#.#...#
#.#.#######.#.#####.#.#####.### #.###.#########.###.#.#####.#.#
#.#.#.......#.#.#.#.#.....#.#.# #.#...#...........#.#.#.#...#.#
#.#.###.#.#.###.#.#.#######.#.# V J Y T C B O #.#####.###.#.###.#.###.###.#.#
#.#.#...#.#...#.....#.#.......# O H P R K R A #.#.....#...#...#.#.#.#.....#.#
#.#.#.#.###.#.#.#.#.#.#.###.#.#####.#####.###########.#######.#####.#####.#######.###############.#.#.#.###.#.#.#.#.###
#.#.#.#.#...#.#.#.#...#...#.#.#.......#.......#...#.....#.....#.......#...#...#.........#.#.#.....#.#.#.#.#.#...#.#.#.#
###.#####.#.#######.###.###.#######.#####.#####.###.#######.###.#######.###.#.#.#.#.###.#.#.###.#####.###.#########.#.#
#.....#.#.#.....#...#...#.#.#...........#.........#.....#...#.#.....#.#.....#.#.#.#.#.....#...#.#.#.........#.........#
#.#####.#.###.#####.#####.#.#.###.###.#.###.#.###.#####.#.#.#.#.#####.###.###.#.#####.#.###.#####.###.###.###.#.#.###.#
#...#...#...#.#.........#...#.#...#.#.#.#.#.#...#.#.....#.#...#.......#.#.#...#.#...#.#.#.....#.#.....#.....#.#.#.#...#
#######.#####.#####.#######.#####.#.#.###.#####.#####.###.###########.#.#####.#.#.#########.###.###.#.###.#######.###.#
#.......#.#.....#...#.........#...#.#.#...#.........#...#.#.#.......#...#.#.#.#...#...#...#.#.....#.#.#.#.#.........#.#
#.#.#.#.#.#.#####.#####.###.#####.#.#.#.#####.#.#.#.###.#.#.#####.#.#.###.#.#.#.###.###.###.###.###.###.###.#.###.#####
#.#.#.#.......#...#...#.#...#.......#.#...#...#.#.#.#.#.#.....#...#.#.....#...#...#.#.#.........#.#...#...#.#.#.......#
#######.###.###.#.#.###############.###.#####.###.###.#.#.#.#.#.#.#.#.###.###.###.#.#.#.###.#.###.###.#.#.#.#####.#.#.#
#...#.#.#.....#.#.#.#.........#.#.........#.....#.#...#.#.#.#.#.#.#.....#.#...#...#...#...#.#.....#.#.#.#.......#.#.#.#
#.###.###.#.#####.#.#########.#.#######.#.###.#####.###.#.#.#####.###.#######.#.###.###.#######.#.#.#####.#.#.#.###.###
#.....#...#...#.#.....#...............#.#.#.....#.......#.#.#.....#.#...#.....#.....#.....#.....#.....#.#.#.#.#.#.....#
#####.#.#.###.#.#.#########.#####.###.#.###.###.#######.#.#####.###.#.#.#####.#.###.#.#.#######.#.#.###.#.#######.#.#.#
#.......#.#.#.#.....#.......#.#...#.#.....#.#...#.#.#...#...#.......#.#.#.....#.#.....#...#...#.#.#.#.......#.#.#.#.#.#
#.###.#.#.#.###.#######.#####.#.#.#####.#.###.###.#.#.#.#.#####.#####.#####.###.#.###.###.#.###.#.###########.#.#.#.#.#
#.#.#.#.#...#...#...#.#.#.#.#.#.#.....#.#...#...#.....#.#...#.#.....#.#.......#.#.#...#.#.....#.#.#.........#...#.#.#.#
#.#.#.#.#.###.#####.#.###.#.#.###.#######.#####.#.###.###.#.#.#.#############.#######.#.#.###.#####.#.###.###.#####.###
#.#.#.#.#...#...#.#.....................#.#.....#...#.#...#...#.#...#.#.......#...#.#...#.#.#.#.....#.#.........#.#...#
#.#.#.#.#.#######.#####.#####.#####.#########.#.#.#########.#.#.###.#.#####.###.###.#.#.###.#####.#########.#####.#####
#.#...#.#.#...#.........#.#.#.#.......#...#.#.#.#.........#.#.#.#.....#...........#...#.#.......#.#.#.#.#...........#.#
#.#######.###.###.#######.#.#####.#####.###.#.#######.#####.###.###.#.###.###.#######.#######.###.#.#.#.###.###.###.#.#
#.....#.#.#.#.#.#.#.#.....#.........#.........#.#...#...#.#...#.....#.#.#...#.#.#.#.#.....#...............#...#.#.....#
#.#####.###.#.#.###.#####.#######.#####.#.###.#.#.#.#.###.#.#########.#.#.###.#.#.#.#.#########.#####.#.#.#######.#.#.#
#.#.#.......................#.#.#.#...#.#.#.....#.#...#.#...#.#.#.......#.#.....#.#...#...#.........#.#.#.......#.#.#.#
#.#.#.###.#####.#########.#.#.#.#.#.###########.#.###.#.#.###.#.###.###.###.#####.###.###.#.#.#.#.###.#####.#.###.#####
#.#...#.#.#.#...#.........#.........#...#.#.....#...#.#.......#...#...#.#.....#...#.........#.#.#...#...#...#.#.#...#.#
#######.###.###.#####.#####.#####.#.#.###.###.###.#######.#.#.#.#####.#######.#.#.#.#####.#####.#.#.#.#####.###.#####.#
#...............#.....#.......#...#.....#.......#.....#...#.#.#.......#.......#.#.......#.....#.#.#.#.....#...........#
#####################################.#####.#######.#######.###.#########.#####.#######################################
O C N X F S W
G K B L Z L W

File diff suppressed because one or more lines are too long

View File

@ -1,100 +0,0 @@
cut 578
deal with increment 25
cut -3085
deal with increment 16
cut -6620
deal with increment 17
cut -1305
deal with increment 71
cut -4578
deal with increment 44
cut 5639
deal with increment 74
deal into new stack
deal with increment 39
cut 7888
deal with increment 17
deal into new stack
cut 6512
deal with increment 46
cut -8989
deal with increment 46
cut -8518
deal with increment 75
cut -870
deal into new stack
deal with increment 53
cut 7377
deal with increment 60
cut -4733
deal with increment 25
cut -6914
deal with increment 23
cut -4379
deal into new stack
cut 582
deal with increment 35
cut 9853
deal with increment 2
cut -142
deal with increment 74
cut 328
deal into new stack
deal with increment 75
deal into new stack
cut -8439
deal into new stack
deal with increment 34
cut 2121
deal with increment 2
cut 8335
deal with increment 65
cut -1254
deal into new stack
cut -122
deal with increment 75
cut -9227
deal into new stack
deal with increment 24
cut 3976
deal into new stack
deal with increment 8
cut -3292
deal with increment 4
deal into new stack
cut -8851
deal with increment 2
deal into new stack
cut 4333
deal with increment 73
deal into new stack
deal with increment 9
cut -7880
deal with increment 49
cut 9770
deal with increment 30
cut 2701
deal with increment 59
cut 4292
deal with increment 37
deal into new stack
cut -184
deal with increment 25
cut 9907
deal with increment 46
deal into new stack
cut 902
deal with increment 46
cut 2622
deal into new stack
cut 637
deal with increment 58
cut 7354
deal with increment 69
deal into new stack
deal with increment 49
deal into new stack
deal with increment 19
cut -8342
deal with increment 68
deal into new stack

View File

@ -1,3 +0,0 @@
deal with increment 7
deal into new stack
deal into new stack

View File

@ -1,3 +0,0 @@
cut 6
deal with increment 7
deal into new stack

View File

@ -1,3 +0,0 @@
deal with increment 7
deal with increment 9
cut -2

View File

@ -1,10 +0,0 @@
deal into new stack
cut -2
deal with increment 7
cut 8
cut -4
deal with increment 7
cut 3
deal with increment 9
deal with increment 3
cut -1

File diff suppressed because one or more lines are too long

View File

@ -1,5 +0,0 @@
.#.##
...#.
....#
.#...
..#..

View File

@ -1,5 +0,0 @@
....#
#..#.
#..##
..#..
#....

View File

@ -1,5 +0,0 @@
.....
.....
.....
#....
.#...

File diff suppressed because one or more lines are too long

View File

@ -54,11 +54,6 @@ var dayMap = []day{
&days.Day18{},
&days.Day19{},
&days.Day20{},
&days.Day21{},
&days.Day22{},
&days.Day23{},
&days.Day24{},
&days.Day25{},
}
func main() {

View File

@ -28,8 +28,6 @@ type IntcodeProgram struct {
program []int64
relativeBase int
haltRequested bool
printASCII bool
feedInput []rune
}
type IntcodeProgramState struct {
@ -142,15 +140,14 @@ func (p *IntcodeProgram) Reset() {
p.relativeBase = 0
}
func (p *IntcodeProgram) Run() int64 {
return p.RunIn(func(int) int64 { return 0 }, func(int64, IntcodeProgramState) {})
func (p *IntcodeProgram) Run() {
p.RunIn(func(int) int64 { return 0 }, func(int64, IntcodeProgramState) {})
}
func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOutputFunc) int64 {
func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOutputFunc) {
p.init()
inputsRequested := 0
lastOutput := int64(0)
for instructionPointer := 0; instructionPointer < len(p.program) && !p.haltRequested; {
instruction := p.GetMemory(instructionPointer)
instructionPointer++
@ -187,28 +184,13 @@ func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOut
case opInput:
inputsRequested++
param1 := p.GetMemory(instructionPointer)
var inputVal int64
if len(p.feedInput) > 0 {
inputVal = int64(p.feedInput[0])
p.feedInput = p.feedInput[1:]
} else {
inputVal = inputFunc(inputsRequested)
}
if p.printASCII && inputVal <= 255 {
fmt.Printf("%c", rune(inputVal))
}
p.setMemory(int(param1), inputVal, paramModes[0])
p.setMemory(int(param1), inputFunc(inputsRequested), paramModes[0])
instructionPointer += 1
case opOutput:
param1 := p.GetMemory(instructionPointer)
param1Val := p.getParamValue(int(param1), paramModes[0])
if p.printASCII && param1Val <= 255 {
fmt.Printf("%c", rune(param1Val))
}
outputFunc(param1Val, p.makeState(instructionPointer))
lastOutput = param1Val
outputFunc(p.getParamValue(int(param1), paramModes[0]), p.makeState(instructionPointer))
instructionPointer += 1
@ -274,19 +256,8 @@ func (p *IntcodeProgram) RunIn(inputFunc ProvideInputFunc, outputFunc ReceiveOut
}
p.haltRequested = false
return lastOutput
}
func (p *IntcodeProgram) Stop() {
p.haltRequested = true
}
func (p *IntcodeProgram) SetDebugASCIIPrint(enable bool) {
p.printASCII = enable
}
func (p *IntcodeProgram) FeedInputString(str string) {
p.feedInput = make([]rune, len(str))
copy(p.feedInput, []rune(str))
}