A funny fact: now we can apply packet comparator to https://adventofcode.com/2021/day/18. I did and it worked almost fine! Except, their magnitudes don’t keep the order.
([[[0 [5 8]] [[1 7] [9 6]]] [[4 [1 2]] [[1 4] 2]]]
[[2 [[7 7] 7]] [[5 8] [[9 3] [0 2]]]]
[[[5 [2 8]] 4] [5 [[9 9] 0]]]
[[[[5 2] 5] [8 [3 7]]] [[5 [7 5]] [4 4]]]
[[[[5 4] [7 7]] 8] [[8 3] 8]]
[6 [[[6 2] [5 6]] [[7 6] [4 7]]]]
[[6 [[7 3] [3 2]]] [[[3 8] [5 7]] 4]]
[[[6 [0 7]] [0 9]] [4 [9 [9 0]]]]
[[[7 [6 4]] [3 [1 3]]] [[[5 5] 1] 9]]
[[9 3] [[9 9] [6 [4 9]]]])
(1636 1346 1125 1565 1511 1342 1510 870 1317 681)Wow! I am fucking right 😅
Day 13 - Solutions
Okay, refining is done. Off to bed.
Pretty gross comparator.. I basically wrote it while reading the puzzle text top-down. Was pleasently surprised to find that in part-2, I could slot it into clojure.core/sort without any changes.
https://github.com/Ramblurr/advent-of-code/blob/main/src/aoc/2022/day13.clj
https://github.com/callum-oakley/advent-of-code/blob/main/src/aoc/2022/13.clj no surprises today
https://github.com/benjamin-asdf/advent-of-code/blob/master/src/Y2022/day13.clj
(edn/read-string (str "[" input "]"))
doens't this somehow feel like some win condition for lisp?Maybe.. in JavaScript you could so the same with JSON.parse
I don't think I've done anything very differently to anyone else here. Feels like this problem designed to be solved with a lisp.... Wonder if my comparator is a bit verbose... https://github.com/wardle/aoc2022/blob/main/src/day13.clj
Just read @michaeljweaver’s solution and his use of keep-indexed which is much nicer than my map-indexed and then filter contortions! This is great for learning.
https://github.com/FelipeCortez/advent-of-code/blob/master/2022/13.clj
and TIL
> Java comparators are all 3-way, meaning they return a negative, 0, or positive integer depending upon whether the first argument should be considered less than, equal to, or greater than the second argument.
>
> In Clojure, you may also use boolean comparators that return true if the first argument should come before the second argument, or false otherwise (i.e. should come after, or it is equal). The function < is a perfect example, as long as you only need to compare numbers. > works for sorting numbers in decreasing order. Behind the scenes, when such a Clojure function bool-cmp-fn is "called as a comparator", Clojure runs code that works like this to return an int instead:
>
(if (bool-cmp-fn x y)
> -1 ; x < y
> (if (bool-cmp-fn y x) ; note the reversed argument order
> 1 ; x > y
> 0)) ; x = yRecommended reading on clojure comparators: https://clojure.org/guides/comparators
[2,3,4] vs 4 are in the right order
because 2<4 makes a decision before right runs out of elements.
so [2 3 4] [4] is ok
and [2 3 4] [2] is not because 2=2 (no decision), and only after that right runs out of elements
and [2] [2 3 4] is ok, because 2=2 (no decision), and left runs out, and thats ok
and as a result (every? true? (map correct? left right)) is incorrectMuch much easier than yesterday... It was great decision to write comparator for part1. https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2022/day13.clj
https://github.com/bhauman/advent-of-code-2022/blob/main/src/adv2022/day13/sol.clj
The interesting bit
(defn comparer [a b]
(cond
(every? integer? [a b])
(compare a b)
(every? sequential? [a b])
(if-let [res (->> (map comparer a b) (filter #(not (zero? %))) first)]
res
(comparer (count a) (count b)))
:else ;; one is a list and one is an integer
(apply comparer (map #(cond-> % (integer? %) vector) [a b]))))Lists, first, next. https://github.com/tschady/advent-of-code/blob/main/src/aoc/2022/d13.clj
https://github.com/volesen/aoc2022/blob/main/day13/day13.clj
Looking at the source for = led me to next instead of rest, which I always forget about. next especially helps because (compare nil 2 ) (compare 3 nil) (compare nil nil) all do the right thing.
That’s a good thing to remember, @tws.
Impressed by @michaeljweaver’s code of comparator. It’s really concise.
Mine is a bit wordy https://github.com/zelark/AoC-2022/blob/master/src/zelark/aoc_2022/day_13.clj
I thought a lot about it (too much!) and made two attempts to normalize and flatten the packets and do a simple element-wise compare, but I kept running into exceptions. I got as close as having only 3 cases that I couldn’t resolve (with my input). Ah well. It’s like the false promise of alchemy.
made an animation how the packets would look like if normalized to the common shape. Although it is only animation, the compare doesn't work on it
(compare nil ##-Inf) ; => -1 surprise!
what did you put test.check on the case?
Nil is less than everything. And ##-Inf is less than everything else.
not everything trollface
user=> (compare ##-Inf ##NaN)
0https://github.com/alexalemi/advent/blob/main/2022/clojure/p13.clj
not the most elegant comparison function, but I tried for speed today
it was also nice having an input file that was valid clojure
Very crude solution which I will proceed to refine. https://github.com/wevre/advent-of-code/blob/master/src/advent_of_code/2022/day_13_distress_packets.clj
https://gitlab.com/maximoburrito/advent2022/-/blob/main/src/day13/main.clj Some days I feel like I have no reading comprehension skill....
parsing is easy if we wrap everything into a vector and read edn. Comparator is the meat of the task. I've made a detour trying to normalize packets to the same shape in order to use standard compare, but figured that writing comparator is easier. https://github.com/nbardiuk/adventofcode/blob/master/2022/src/day13.clj
I got mine to work, also using edn/read-string, and I've done my usual write-up.
• https://github.com/abyala/advent-2022-clojure/blob/main/docs/day13.md
• https://github.com/abyala/advent-2022-clojure/blob/main/src/advent_2022_clojure/day13.clj
nil is less than everything, ##-Inf is less than everything else, and ##NaN is less than nothing.
nil is endless void ^_^
Day 13 part 1: I get the right answer for the sample, but it’s wrong for my input. Any tips?
Came here for the exact same question
(read-string (str "[" input "]"))
(partition 2)
works fine for the example and the real input also seems correct. Am I wrong?should be fine, I found a problem with a logic for comparison
I’m using a zipper in a wrong way
For me I realized my logic is wrong for this case:
[[4, 5], 6]
[[4, 5], 3](cmp [[[] 6 2]] [[[]] [10]]) a good example to check against, should return false
My mistake is I was trying to use zippers.
double checked everything, but can’t see a mistake
compared visually the output for every example, it seems correct
The input has empty vectors in strange places that messed me up when I tried to get too tricky.
I use edn/read-string to parse it, should work fine I guess
Posting out here to see if someone with clojure-core-match skills can answer a specific question on my solution to day 13.
I started on the same approach! I just went with condp in the end which does the same thing in this trivial case
I had the same idea, but when I saw this in the wiki, I gave up on match as more complex.
> Unlike pattern matching found in most functional programming languages core.match does not promote matching on concrete types. Instead core.match matches on abstract interfaces / protocols -`IPersistentVector`, ILookup, Sequential and so on.
I found a way to make it work, but I still think it's messy. Instead of working with actual types, I had to map the types to keywords. Note the mapv under the m/match call. Surely this isn't the intention?
(defn correct-order?
([left right] (correct-order? left right [0]))
([left right address]
(let [[v1 v2 :as values] (map #(get-in % address) [left right])]
(m/match (mapv #(cond (number? %) :num, (vector? %) :vec, :else nil) values)
[nil nil] (recur left right (-> address move-up move-right))
[nil _] true
[_ nil] false
[:num :num] (case (u/signum (- v1 v2))
-1 true
1 false
(recur left right (move-right address)))
[:vec :vec] (recur left right (move-down address))
[:vec :num] (recur left (vectorize right address) address)
[:num :vec] (recur (vectorize left address) right address)))))why not use guards for types?
@schad.alexis - I did the first time through, but I had to repeat the guards multiple times to get all of the conditions to work. Thought it looked a little ugly, unless you know a better way.
(defn correct-order?
([left right] (correct-order? left right [0]))
([left right address]
(let [[v1 v2] (map #(get-in % address) [left right])]
(m/match [v1 v2]
[nil nil] (recur left right (-> address move-up move-right))
[nil _] true
[_ nil] false
[(_ :guard number?) (_ :guard number?)] (case (u/signum (- v1 v2))
-1 true
1 false
(recur left right (move-right address)))
[(_ :guard vector?) (_ :guard vector?)] (recur left right (move-down address))
[(_ :guard vector?) _] (recur left (vectorize right address) address)
[_ (_ :guard vector?)] (recur (vectorize left address) right address)))))It's not that ugly for me, at least you know what's going on
In the bottom of https://github.com/abyala/advent-2022-clojure/blob/main/docs/day13.md, I mention trying to use match to check the types of the two values at a given level of the vector, checking if they're nil, scalar, or vectors. I was able to work with matching on [(type v)] just fine, but once I brought in two types, with [(type v1) (type v2)], I couldn't get it to work. I had to resort to :guard clauses, which just look messy.
Does anyone know how to get the matcher to work when using the types of 2 or more values in the input vector?