Day 12 - Solutions
https://gitlab.com/maximoburrito/advent2024/-/blob/main/src/day12/main.clj This is definitely ugly. I struggled to name things and payed the price. I also payed the price for not having handy search abstractions built up. Normally I find it fun to write it by hand each time, but this time with a search on top of a search, it was quite awkward. Maybe this will get cleaned up tomorrow with some sleep.
Canβt be worse than mine: https://gist.github.com/RokLenarcic/931023da7afbc13f53b2aa3799027288
Awful part 1 rank on this one and bad for part 2
at first glance, I think we did exactly the same thing for the sides, searching the graph of [perimeter direction] nodes
Which is awful lol
I will replace this with a proper solution
Even part1 I was 4300th place, took me way too long.
I had this stupid idea of representing boundary points as floats.. and then wasted a lot of time there. https://github.com/erdos/advent-of-code/blob/master/2024/day12.clj
My solution works for every test input I can find, but too high on real input on part2 π
@malaingreclement ugh, I hate days like this... I know this might sound awfully obvious, but - as someone else said - it's best to have correct solution on the first try π
hmmm, my part 1 works for all three examples, but too low for the real input
@erdos I represented mine as rationals
wonder if I'm missing something in my perimeter calculation
(defn perimeter [region]
(count
(reduce (fn [s position]
(into s (keep (fn [delta]
(let [neighbor (mapv + position delta)]
(when-not (contains? region neighbor)
(mapv + neighbor (mapv (partial * 1/2) delta)))))
deltas)))
#{}
region)))My idea was to store fence as a pair of fields in->out (this helped me to avoid crossed fence case eventually). https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2024/day12.clj
@felipecortezfi your neighbor is a vector and you call contains? on this vector (not elements of it). Is it right? Maybe you wanted to filter neighbors?
think it's right. region is #{[1 2] [2 2]}, I want to see if e.g. [2 2] + [-1 0] is a position in the region
Ah, ok, got it. It's just a vector adding.
yep!
Is it a safe assumption that every letter is its own unique region? It appears that the input reuses letter for unrelated regions.
@vincenz.chianese no! the X O example shows that
> Plants of the same type can appear in multiple separate regions
think I found my issue. I'm forgetting to detect some regions
Oh ok, it's more of a plant type
"corner counting" for part two https://gist.github.com/DeLaGuardo/b6e073a9551290fe8683fd688d095b38
I used a similar trick to last year's "squeeze through the pipes" problem, e.g. expand the graph so it's easier to count the borders. then it's flood fill + counting for p1, flood fill + following the border for p2. I spent a bunch of time on p2 trying to follow the border without tracking an explicit direction, which got me very close (passed on all examples) but I had to rewrite it. https://github.com/tildedave/advent-of-code/blob/main/src/advent2024/day12.clj I kind of wonder if for p1 perimeter you could just count cells that are NSEW adjacent to something with a different letter. (haven't checked reddit yet)
corner counting is quite clever.
Phew, I finally managed to get it done.
Cleaned up it a bit https://github.com/zelark/AoC/blob/master/src/zelark/aoc_2024/day_12.clj
(defn perimeter [region]
(count
(reduce (fn [s position]
(into s (keep (fn [delta]
(let [neighbor (mapv + position delta)]
(when-not (contains? region neighbor)
(mapv + neighbor (mapv (partial * 1/2) delta)))))
deltas)))
#{}
region)))
duh. completely wrong. (mapv + neighbor (mapv (partial * 1/2) delta) -> (mapv + position (mapv (partial * 1/4) delta)got both parts!
how does one create collapsible code blocks aside from dragging files in again? not very clear from the slack interface
FINALLY
@doppiaelle1999 I don't drag the files. have to copy the contents, go to the bottom left corner and click the plus, text snippet
@doppiaelle1999 shift+ctrl+enter or click on the + on the bottom left and click on "create snippet"
It took me a decade and I had to go sleep in between but I'm finally done ><
@malaingreclement hammock time π
proud of my little clojure.lang.Rational trick today
My solution is... kinda awful? I walk the outeredge and remember the coordinates of the void on the left, to then generate all the neighbors of the current region. Remove the outer edge from that and bam, got the islands.
It's a bit stupid imho, but it works, so it's not stupid.
This is so bad it's almost funny.
It doesn't matter, what matters is you nailed it!
The corner counting never occurred to me due to using graph searches as a golden hammer from the start, so part 2 is (especially) fugly
Hereβs todayβs and I got tree-seq in there:
https://github.com/bhauman/adv2024/blob/main/src/adv2024/day12/sol.clj
Second time I see you using tree-seq. I should learn to use it, it looks fun.
Conrer counting! Well that would have been nice to know. π Now I have to give it a try.
yeah, corner counting would be much faster to implement than mine: https://github.com/vollcheck/aoc/blob/master/src/y24/day12.clj I'm grouping boundaries by the direction they look to and then by x or y axis + checking if they are contiguous
Actually, after trying it, I donβt know that counting corners is significantly easier in terms of code, it might be conceptually easier????
corner counting since first solution hit both OOM and garbage collector walls :) not pretty. "Elapsed time: 111.823166 msecs" total
Okay I agree, maybe corner counting isnβt that easy
I counted corners. busy with work today, I think I can tighten this up.
Excited to see the simpler ways everyone solved part 2, mine really got out of hand π
https://github.com/alexlapp/aoc_clojure/blob/main/src/advent_of_code/2024/day12.clj#L62
I found regions in part 1 by creating sets of [x y] coordinates where they shared edges. I found sides by looking at each cell and counting the which of the 4 sides did not touch other cells in the region.
For part 2, I take the set of coordinates that represents a region, split it into rows, split each row into blocks (for cases where the shape "touches" a column in multiple sections), and then map those blocks into values of either :exposed or :covered if there is a block above them, then partition-by those values, filter out the covered sections, and count what's left. Doing the partition-by organizes these into sets of shared sides. Then I do the same for the row looking at exposed or covered for below, then split the region into columns and do the same for each column looking to the left and right.
I finally did my writeup for today. β’ Blog: https://github.com/abyala/advent-2024-clojure/blob/main/docs/day12.md β’ Code: https://github.com/abyala/advent-2024-clojure/blob/main/src/advent_2024_clojure/day12.clj
alright so they decide in regards to A the highlighted part has 4 sides instead of 2. what a bummer for me.
Yeah.
Also don't forget : if one of those B were a C, the calculation for A would stay the same (the total would change, ofc, but it doesn't change the number of sides from A 's point of view).
thought i found an elegant way to solve it until only 4/5 pass
for part1 perimeter: the regions of garden plots are determined first. within each region, i map each garden plot [y x] to 4 edges in this form [y x y+1 x] [y x y x+1] [y+1 x y+1 x+1] [y x+1 y+1 x+1] then do a freq on the collections of all edges, and keep only those with count equals 1 then it's the perimeter
for part2 i try to build on top of part1 based on the 4 tuple form edges and unfortunately it fails for that particular case. looks like i need to walk the border garden plot. π
Godammit, the problem warned me about inside fencing and I still forgot -_-
This one really got me too. I'm still stuck π
So I don't see any, but maybe I'm wrong. Can someone spoil this for me: is there deeper nesting than one level in the real input ?
can't see any in mine tbh
Found my bug. Didn't account for co-linear nested inputs. Like
AAAA
ABCA
AAAAwe're back at the top of the hour!