10
votes
Day 4: Ceres Search
Today's problem description: https://adventofcode.com/2024/day/4
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>
Advent of Code has a way of making you feel stupid, and, well, today I feel really, really stupid. For how simple the puzzle was, it took an embarrassingly long time to solve (almost 90 minutes).
Musings
I have a
Grid2D
helper class and tried to be fancy with it -- instead of just looping through the grid in eight different directions, I tried to get away with rotating and mirroring the grid, because I have helper methods for that sort of thing. That would have been faster if it had worked, but it didn't (because I had an off-by-one error in the actual counting), so I wasted 15 minutes on that before using the naive approach.Then I got stuck for a very long time on Part 2, because apparently bending the
MAS
around the corner isn't allowed, i.e.is invalid, and the puzzle description did not make that clear. Unfortunately it didn't appear in the test input either (which might have been deliberate), so I was left scratching my head for a good long while.
Part 1 (Rust)
Part 2 (Rust)
Grid problems! I pulled out the helper class I've used for a few years now, makes it a little easier to deal with various approaches to dealing with 2D grids; things like a method for doing something at each index of the grid, or handling out of bounds with a default value, that kind of thing.
Part 1 Ruby
Part 2 Ruby
Helper "Grid" class
I'm very much enjoying having a Point class with simple syntax, but I can't say it's making up for the rest of Pharo's syntax being kind of a pain. It's tough to go from:
for finding a diagonal string, to:
Maybe I'm just not finding the cleanest approaches, but it's frustrating.
I have, however, been enjoying the pressure to heavily decompose tasks and easily add tests. I feel like I'm leaving each day in a state that would be easily refactored or improved.
Pharo Smalltalk Solution
This was one problem where rushing it worked surprisingly to my favor. AWK solutions:
Part 1
My approach here was to locate X's and look for occurrences of "MAS" in all directions. I generally would have used loops for this, but I was in a rush so I just hard-coded everything. Quick and dirty.
Part 2
I was expecting to have to switch to a smarter approach, but this was even easier than part 1 for me. I locate A's and look around diagonally for M/S pairs.
This one was kind of uninteresting to me. I knew how I was going to solve it nearly instantly upon reading the problem text. Maybe it's not a clever solution, but then I don't know that this puzzle really deserves a clever solution. It's just a word search. Part 2 was even easier - I solved it in only a couple minutes.
Solution (Jai)
My initial solution isn't as nice as I'd like it to be, but it works.
I might go back over it tomorrow and add some functions to my utils module to make working with grids easier.
Rhai Solution
Python: Step-by-step explanation | full code
My grid parsing and
neighbors
function came in clutch today. For part 1, I could find everyX
, see if it has a neighboringM
, and calculate the direction we stepped, and step 2 more times to check forA
andS
.For part 2, I tweaked
neighbors
to be able to do diagonals only. It was the same basic approach though: start withA
, find a diagonalM
, and then go the opposite way from theA
to check forS
. If there are exactly 2 of those, we're good to go!Mostly today's writeup covered how my grid system works. I end up using it a ton, so it's nice to have a cogent description of it somewhere.
I do wonder if I should make an actual
NamedTuple
class for myGridPoint
s instead of just a type alias. Is mostly compatible, but will also let me add and subtract via method overrides instead of needing dedicated aadd_points(a: GridPoint, b: GridPoint) -> GridPoint
function. Ah well; that sounds like work for the off season!Part 1 I could've made nicer and I'm sure it could be better, but I think my part 2 is fairly nice
Racket
Python
Ported my handy
Point2D
class from Rust over to Python this year.Part 1
Point2D
Brute force, but it worked well enough. I found complex numbers useful here for storing and shifting coordinates. My Python solutions:
Part 1
Part 2