36 Commits

Author SHA1 Message Date
ce6e63b5b6 Day 15 Part 2
Well...that turned out easier than I 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).
2022-06-13 08:31:43 -05:00
d41aa6cfa5 Day 15 part 1
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 do it all at once.

Part 2 might be able to use the right-hand exploration rule since it has the full map, maybe...possibly a pathfinding/A* type solution, but the problem is finding the "goal" location (furthest point from the oxygen system) itself, so I'm not sure if those will work. My current plan is to either try right-hand wall walking or some sort of breadth-first tree system to plot all distances from the oxygen system, then take the furthest one as the answer.

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 came to a version of it myself.
2022-06-13 00:01:50 -05:00
b5202b28c5 Allow intcode programs to be halted externally
This is simplest to do during an input or output callback, but could potentially also be done to a program running on a goroutine.
2022-06-12 23:49:13 -05:00
0a249b85fc Use varargs for GetPermutations 2022-06-12 23:48:14 -05:00
f03184d4c4 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-12 13:37:38 -05:00
c15d206b8b 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-12 13:37:38 -05:00
43d9a77d62 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-12 13:37:38 -05:00
b903417c06 Day 11 solution 2022-06-12 13:37:37 -05:00
9dd39aa193 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-12 13:37:37 -05:00
3b3c805997 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-12 13:37:37 -05:00
3ca7312e2c 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-12 13:37:37 -05:00
bb00808f99 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-12 13:37:37 -05:00
11b73ba5bc 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-12 13:37:37 -05:00
d7db069031 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-12 13:37:36 -05:00
870abdf579 Day 5 solution
This required an overhaul of the intcode machine to actually be its own type that could operate on its own memory and stuff. So I had to touch day 2 to make it adhere to the new API.

Feeling good about this foundation now. Until I get gobsmacked at some point later, which I expect to happen.
2022-06-12 13:37:36 -05:00
bdd007bb4d Reduce changes needed to the template
I always end up making these changes each time I copy from the template.
2022-06-12 13:37:24 -05:00
6d3627e93b Improve output formatting
Adds some whitespace, a divider, and indents each part's output a bit.
2022-06-10 10:34:44 -05:00
40d5eb59be Add flags to only run a specific part
Now we can specify to only run part1 or part2 of the given day(s). Just in case we need some super focused testing or debugging!
2022-06-10 09:56:37 -05:00
731e991f1f Support piping data in
This allows using someone else's data to compare runtimes, behavior, etc. without having to recompile. Since it's patched into the function that all days use to read, it's incompatible with running all days, which I feel is a reasonable compromise and behavior expectation.

The Mode() check is how the internet says you can test if you should even try to look at stdin, and the Size() check ensures that there's actually data to be read instead of just an open stdin handle (running in VSCode with a debugger seems to keep the stdin handle open, for example, so it passes the Mode() check and then hangs when trying to read since there's nothing to actually read).
2022-06-10 09:42:04 -05:00
c9cfffcc1c Show timing information when running all days 2022-06-10 09:15:08 -05:00
28ea3ff6a1 Handle an empty argument
This makes it slightly easier to adjust VSCode's launch.json to hop around debugging different days. Not much, but a little. And every little bit helps!
2022-06-09 13:17:51 -05:00
bc8ebae440 Day 4 solution
Plenty of room for optimization here, but it's enough for my needs for now.
2022-06-09 08:23:34 -05:00
a53e3467fe Make the linter happy
I mean, it's right, but still...
2022-06-08 18:03:08 -05:00
8ec5aafcc2 Day 3 solution
This is horrendous and slow. But it works. I really don't like grid problems.
2022-06-08 08:23:07 -05:00
2a8384949f I kinda like this Run method on the receiver 2022-06-07 22:54:57 -05:00
092fe15b07 Fix running "all" tests out of order sometimes
Maps are unordered, so this uses an array, which is simpler overall, really.
2022-06-07 22:54:11 -05:00
e8e9eeee02 Remove unnecessary breaks
I forgot that Go doesn't require these.
2022-06-07 20:41:41 -05:00
8cd4994300 More slight streamlining 2022-06-07 10:01:29 -05:00
dd5c072730 Make opcode constants
Just planning for the future...
2022-06-07 09:54:40 -05:00
9b65c91041 Add readme 2022-06-07 09:54:20 -05:00
93c9bc7d6f Day 2 initial solution
There's room to optimize part 2, but I wanted to commit my original brute-force solution first.
2022-06-07 09:26:21 -05:00
d2fbe85a71 Set to automatically run the most recent day 2022-06-07 09:14:24 -05:00
2f5dac4487 Add new day template 2022-06-06 15:33:26 -05:00
85da090c2b Output tweaks, fix day numbering 2022-06-06 15:30:58 -05:00
131fb0f03a Remove sleep added for timing testing 2022-06-06 15:18:26 -05:00
662d76eb7c Bootstrap and day 1 solution 2022-06-06 15:14:31 -05:00