12
votes
Day 12: Rain Risk
Today's problem description: https://adventofcode.com/2020/day/12
Join the Tildes private leaderboard! You can do that on this page, by entering join code 730956-de85ce0c
.
Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace python
with any of the "short names" listed in this page of supported languages):
<details>
<summary>Part 1</summary>
```python
Your code here.
```
</details>
Got distracted by Cyberpunk again. Oops. This way pretty fun though. I got to reuse some of the techniques I used on earlier days
And once again EUROBEAT MAKES YOU GOOD AT CODE
Day 12 Part A – Python
For this one I handled direction by making an array that I would push and pop from to rotate. Sort of like the buffer on day 9. Then, if I ran into a forward command, I would just use the value at
the front of the buffer.
Day 12 Part B – Python
This wasn't too bad either. I just had to make some minor modifications to track the waypoint separate from the ship. The trickiest part was just figuring out how to rotate the waypoint, but I wrote down the coordinates and was able to figure out how to move in each direction.
Tips and Commentary
I assumed 90 degree turns and that worked, it might help to simplify it. It also helps if you make it so that you can handle multiple magnitudes of turn in one smooth motion
Grabbing a pen and paper (or an excel spreadsheet) and drawing out how turning changes things may help. Especially for part B
You don't actually need a whole-ass grid, you can just track the relative positions and facing
Sheets! link to sheet
This was awful at first, but once the structure was there, it all came together.
C#
Part 1
Part 2
Commentary
I liked the twist for part 2 on this one. I was expecting a twist of non-90-degree rotations and not looking forward to it. If that were the case, I probably would have actually gone to actual rotation matrices, but the 90-degree rotations are easy enough to do with coordinate swap-and-inversion.Ruby
This one is another pretty straightforward one, the only thing I got hung up on a few times was forgetting to account for the parameter to the L/R instructions.
Part 1
Part 2
Ooh chucking the directions into an array and rotating by moving between elements is a good idea. I manually wrote down the
(x, y) -> (-y, x)
transformations for 90 degrees left, 90 degrees right, etc.Haha, yeah I've used that trick before in other situations, saves some repetition and makes it easier to extend if you have to include the corners as well (NE/NW/SE/SW).
It also helps that the input only deals in rotations that are whole multiples of 90 degrees. I saw a few other solutions using complex numbers for "real" rotation math, which would make it a lot easier to handle a trickier input.
I think that would've made my part 2 "rotate around origin" cleaner too.
Python
Repo Link
In short, I think I overcomplicated this relatively simple problem. I ended up using a dictionary to mark the ship/waypoint coordinates. I realized it would have been easier to just use cartesian coordinates but I decided to go this route anyway.
Part 1
I used a `pointing` variable to keep track of which direction the ship was facing. For moving the ship, I would add the value to the appropriate direction and subtract the value from the opposite. In the end, I was only interested in the absolute `E` and `N` values (which would be analogous to the `x` and `y` in a normal approach.Part 2
I used a similar approach as part 1. As for rotating the waypoint, I just rotated the values of my dictionary manually.Elixir
I'm not sure whether to be proud or ashamed of my solution. I have a bad habit of trying to generalize my part 1 solution to work with both part 1 and part 2 rather than just addressing each one independently when that makes sense to do, so I think I really overdid the abstraction for this one.
I'm also bad at math so my point rotation logic is probably not as concise as it could be.
I also decided to not parse the input beyond splitting the lines into a list, which made for some fun practice with binary pattern matching. Plus, I dipped my toes into macro-land to generate multiple function clauses that handle all of the direction/rotation actions. Another solution with zero
if
/case
expressions! (except for all of the implicit ones in the function clauses)Part 1 runs in 245 μs; part 2 in 258 μs. 🏎
Edit: I offloaded the macro stuff concerned with translating 'NESW', 'LR' to the appropriate unit vector/rotation direction sign to the
Point
module. This made things a lot cleaner and better follows separation of concerns, I think.Point data structure / functions
Parts 1 and 2
This was a pretty simple one, though I did forget that turns could be more than 90 degrees at first. Actually ended up using trig functions in part 2 because I think that ended up being the least work. Had to look up how that rotation works though because this year has made it feel like an eternity since I thought about trig!
Part 1
Part 2 diff
Python
Repo Link
Part 1
This took some time in terms of thinking about to handle the orientations, but I think I figured a nice way without having to hardcode too much.
Part 2
For this one, I had to sit down with a piece of paper and draw out the rotations. Once I did that, I could see that I just needed to swap the waypoints x and y and negate either the x or y coordinate (depending on the direction). After that, it was pretty much the same as Part 1.
Rust
My first time doing this type of problem with rotations was in AoC 2018 which I did in Fortran. Fortran's
MATMUL
made it easy to apply a rotation matrix via matrix multiplication. For this case using Rust, I wrote my ownrotation_matmul
function to multiply a 2x2 matrix by a 2x1 matrix.Rust
Python
It worries me a little that I had the same problem as yesterday at first: Test input passed, actual solution failed (for part 2). Only retyping it from scratch helped, as I didn't actually find the mistake. That's why part 1 and 2 use different ways of dealing with rotation. I initially just always stored the direction in degrees and flipped based on that value. For part 2, I now "actually" rotate the waypoint's coordinates in 90° increments.
Part 1+2
I didn't quite enjoy this one as much as the cellular automation of day 11, but this was still pretty entertaining to code overall. Like some others, I too got hung up on the L-R rotations in Part 2. I was definitely expecting them to go the complex-degrees-math route so it was nice to see that everything stayed in even increments of 90.
e: Oh! And I almost forgot, this one led me to run into another annoying "gotcha" of Javascript that betrays my assumptions built on previous experience with other languages... At least this was relatively easy to track down, since it just meant my direction turning was totally off.
Part 1
Part 2