Day 24 - Solutions
Here’s some clojure.core.logic that prints out potential bad outputs given a bit location.
This definitely could be improved especially the linear gate look up. But dang its a concise way to find bad outputs that can be swapped. I’m sure you could write it so that the the logic system itself reports out all the good or bad bits OR even find all the specific swaps that repair the system as well…
I don’t think this is as accessible or as straight forward as the continuations based matcher I made above. But if there is an interest in core.logic this a nice entry point …
Here’s day 24: https://github.com/bhauman/adv2024/blob/main/src/adv2024/day24/sol.clj Part 2 runs in 10ms
I wrote a little continuations based DSL to match the adder logic graph and then report the errors back. It was a fun puzzle for sure.
I almost used core logic and then I thought better of it.
For part 2 I drew my graph and solved it visually by examining the output
Oh, that's a WAY better presentation than mine lmao
You can label nodes like this
"z31" [label="z31\n\nXOR"]
Eh. I managed. And I'll probably forget before next year's aoc ^^;
I gave up trying to code this and just did it by hand lol
I don't think anyone did it "code first", even scrolling other solution threads.
wasted a lot of time lol
Only 2500 people solved it yet
Nah I wrote a validator in the end but I had to look by hand how to change it to make it pass
Yeah. I ranked 659, which is by far my best ranking ever.
> I wrote a validator in the end but I had to look by hand That's exactly what I did. Code the "detect bad", then solve by hand.
I had an idea of a "validate each step" for each bit and detect as soon as a step was wrong, but it's a chore and a half to write and now that I have the answer, I'm not motivated to write it.
Yeah I wrote the validator for each step, but the output was cryptic enough that the benefit isn’t big enough
hm looks like still only 3 solved on clojurians leaderboard
got it, mostly via REPL experiment. wrote a validator to output which bits were bad which zeroed in on the issues, then brute forced fixing the connectors. in some cases I brute forced all possible swaps to see which ones had worked (e.g. if you know bit N is bad when you just add 1<<N + 1<<N you can find all the swaps that fix it).
lots of stuff like this
could have been more efficient at it, had fun futzing :-)
https://github.com/tildedave/advent-of-code/blob/main/src/advent2024/day24.clj mostly REPL notes
Well, finally finished both parts: https://github.com/rjray/advent-2024-clojure/blob/master/src/advent_of_code/day24.clj I was able to solve part 2 without using any graphing tools. I did get mixed up and had to have a look at a Python solution that was taking the same approach I was, at one point. I became confused when the second test-set from part 1 produced many more swap-pairs than I was expecting (spoiler: it doesn't work as test input for part 2). Even after making some adjustments, i realized I had no effective test-data for part 2. But it running it on the puzzle input did result in exactly eight connections, so I took a leap of faith and submitted it. It was correct.
I couldn’t leave it be. Complete clojure.core.logic solution for part 2 https://github.com/bhauman/adv2024/blob/main/src/adv2024/day24/logic.clj
As usual logic programming requires a completely different way of thinking. Very very fun stuff.
This is very impressive. This doesn't feel that far from my solution, but the syntax is very very different. Do you have a recommendation on how to approach core.logic ? I never even looked at the package, but your code makes it look very interesting.
Love the continuations, the elegance of this kind of stuff drew me to functional programming. But I have to say I don’t ever use things like this in my code, because as neat as it is, it is inferior to just representing this thing in data and running code on top of it. Sure, continuations code results in some short code, but continuations are opaque and hard to debug. Representing something like this with data + code that runs over the data is much better for production code: • the data part is easy to inspect • data can be serialized/deserialized • you can write multiple sets of functions that operate on same data, e.g. if you have multiple versions of a server or something • you can sometimes tweak behavior by tweaking data, instead of changing the code I am sad that these neat functional constructs are not better than plain old boring data + data processing functions, but it is what it is.
This is the second time today when I thought I as working on problem N but I was actually working on problem N-1.... Well, at least I'm not ON the current day 🙂
I have part 1 done, but I'm going to sleep on part 2, I think. It seems like I'd have to either reverse-engineer the circuit or iterate over roughly 128795283347445 different combinations...
maybe it'd be faster to build classic adder, label its wires, and diff with puzzle input
or test pairs of bits for faulty paths.
Might be, but not at 10:45PM 🙂.
I have a solution but I’ve got other errands 😞
I got it 😄 Have to clean up the code a bit, but what I did was build a "validate adder" function, then just look for the faulty ones in graph viz
So misha's approach.
Puzzles that can't be done in 100% code annoy me...
I think it can be 100% in code, but you need to reverse engineer the input first.
I'm working on a 100% code approach, it's just much easier to solve it visually first.
Here is mine. It's not complete by any means, the detect-swap might need more entries in its cond for other inputs. But it works for mine.
https://mitpress.mit.edu/9780262535519/the-reasoned-schemer/ is really the best way to start. Or go to http://minikanren.org. There is also a little tutorial on the clojure.core.logic github wiki. It’s basically pattern matching all the way down. My biggest problem when coming back to it, is that my mind always reverts my non-logic programming ways, when in logic programming you kinda just need to state the problem.