Advent of Code 2017

I just solved day 5. I didn’t optimise for speed, rather I’m very happy with how elegant it looks. First time I used iterate, and I think my mind exploded a bit https://github.com/greenonion/advent-of-code/blob/master/src/advent_of_code/2017/day_5.clj

1 Like

Sorry about that. thank you :slight_smile:

Nice! your solution could also easily be adapted to use reduce and reduced.

Day6: github:plexus/AdventOfCode2017

I decided to do this one mainly with reduce/reduced, which I thought yielded a very nice solution.

Going from part one to part two was mainly just swapping out the set for a map, I could even keep the call to contains? :slight_smile:

1 Like

My day 6 solution: https://gist.github.com/rauhs/4fe942af60f351e8ecb6c24a35855c44

What does reduced do, exactly? It just terminates the rest of the reduce function early?

The file name says day 5. Is it labeled incorrectly?

For Day7 part 1 I just used frequencies and filtered for whichever only had 1.

Looks like for part 2 I’ll actually have to do some work. :smile:

Yes, exactly. It just wraps a value in a clojure.lang.Reduced, so that Clojure recognizes this as the “final” value and stops looping. Transducers also use this internally to mark termination, e.g. for take or drop-while.

My solution for day 7. Part one was straightforward enough, but part two was a bit of headscratcher. I ended up just looking at the data and figuring out the solution “manually”, REPL style. It’s pretty nice how Clojure lets you do this. see code on github.

Afterwards I did code up a general solution, replicating my earlier reasoning, which looks pretty messy :man_shrugging:

Small highlight: the realization that I could (into #{} cat ,,,) to concatenate a bunch of seqs and get them into a set. Once you get into the transducer mindset you really find all kinds of uses for them.

And an eternal pain point, the lack of a function that does first + filter. I’m never sure if I prefer (first (filter ,,,)) or (some #(and ,,, %) ,,,). There was a proposal to have this built-in but sadly it was rejected, see #CLJ-2056.

Yeah day7 was tough. My solution was also pretty ugly. :confused: Though day8 was fun, I decided to hack it using read-string and resolve: https://gist.github.com/rauhs/4fe942af60f351e8ecb6c24a35855c44 Not that I’d write such code in production :smiley:

Oh interesting that you used reductions to keep the history, I decided to carry around a separate maxval throughout the reduce. See my solution.

I do find all these puzzles very imperative. Maybe that’s just the theme with “being inside the computer”, but it seems very one sided.

And here’s day 9. It’s funny how this is something I get out of bed for on a Saturday now :thinking:

Per @jackrusher’s suggestion I added the assignment in the comments so people who aren’t playing can follow along

I started out writing a recursive parser, and then I was like “how does this work again?”, and decided to use Instaparse instead. It’s such a wonderful library, although not always easy to debug when your grammar doesn’t do what it’s supposed to do.

For the test inputs all was fine, but when running it on the real input it threw an error all the way at the end, it seemed to think the outer { } were unbalanced… Read through the instructions and the grammar a few more times, then decided to try with a partial parse tree. Basically let instaparse get as far as it can before it gives up. That seemed to do the trick since it yielded the right answer.

Part two was really just tweaking what instaparse does or does not ignore in the output.

This was also an excellent opportunity to use clojure.walk/postwalk, a super useful function which perhaps not everyone knows about. It’s kind of like map or reduce, but for mapping over tree structures.

1 Like

This is really neat.

I’m not sure if Shogo Ohta / athos is on clojureverse, but they posted an interesting solution using trampoline and letfn. The trampoline page also leads to an article, Trampolining through Mutual Recursion.

Lots of things learned today.