> work on a pair of them, see what you can do to make them one I was just making a Buddhist joke, but I am glad it helped π
I agree @rob156. While it might literally be the Chinese remainder theorem, that's not the part of programming I enjoy/use often
Day 14 answers thread - Post your answers here
I like floating-addresses
approach
gonna refact my solution after work
https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2020/day14.clj
My step 1:
(defn parse [input]
(->> (clojure.string/split-lines input)
(map #(->> (clojure.string/split % #" ")
((fn [[op _ arg]] [op arg]))))
(map (fn [[op arg]]
(if (= op "mask")
{:mask arg}
{:addr op :value (Long/parseLong arg)})))))
(comment
(def input (util/fetch-input 14))
; step 1
(def input "mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X
mem[8] = 11
mem[7] = 101
mem[8] = 0")
(->> input
(parse)
(reduce (fn [acc instruction]
(if-let [mask (:mask instruction)]
(merge acc
{:mask mask
:mask-or (->> (clojure.string/replace mask #"X" "0")
(str "2r")
(read-string))
:mask-and (->> (clojure.string/replace mask #"X" "1")
(str "2r")
(read-string))})
(let [{:keys [addr value]} instruction
{:keys [mask-and mask-or]} acc
masked-value (-> value
(bit-or mask-or)
(bit-and mask-and))]
(-> acc
(update-in [:memory addr] #(bit-or mask-or masked-value (or % 0)))
(update-in [:memory addr] #(bit-and mask-and masked-value (or % 0)))))))
{})
:memory
(vals)
(apply +)))
I ChiefStringOfficer'ed this one :d: https://github.com/akovantsev/adventofcode/blob/master/src/adventofcode/y2020/day14.cljc
a long one https://github.com/bnii/advent-of-code-2020/blob/main/src/day14.clj
My solution to Day 14. I couldn't find a nice way to represent the second part. https://github.com/benfle/advent-of-code-2020/blob/main/day14.clj
My worst performance of the season (according to my criterias) π
I cleaned up my code a bit: https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_14.clj
Iβm glad someone uses str/escape
now π
Thatβs thanks to @plexus and his videos
He saw it somewhere and it spreads
was it from you?
Yes π
people still like it https://twitter.com/alekszelark/status/1335185041962504192?s=20
Also cleaned up my code. Thanks @genmeblog for inspiration https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_14.clj
https://github.com/RedPenguin101/aoc2020/blob/main/day14.clj - part 2 is possibly the ugliest code ever written, aside from taking over a second to run. Tidy up time!
@genmeblog, btw in the part 2 just bit-or
is enough
Oh, I will revisit it later, thanks! Very clean solution btw (yours)!
I ran my code with a difficult input from this thread, waited ~4 minutes and then interrupted it. Anyone else wants to test it? https://www.reddit.com/r/adventofcode/comments/kcybyr/2002_day_14_part_2_but_what_if_the_input_is_harder/
I thought about it, but ran for the simplest solution.
I eventually did this differently, but a while I was trying this way:
masked-addr (-> addr
(#(Integer/toBinaryString %))
(->> (format "%36s"))
(clojure.string/escape {\space \0})
(->> (map (fn masker [m a]
(case m
\0 [a]
\1 [\1]
\X [\1 \0]))
mask)))
The relevant part there is how I encoded the masked address. It produces the following for the address 26 assignment in the example input:
"000000000000000000000000000000X1001X"
([\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\0]
[\1 \0]
[\1]
[\1]
[\0]
[\1]
[\1 \0])
I was pleased getting that far and thought the next step would be easy. I think about it as finding all different paths from start to end. But when I try to produce the addresses from them in a horribly nested manner. Like so:
[[[[59 100] [58 100]] [[27 100] [26 100]]] [[[[27 1] [26 1]] [[25 1] [24 1]]] [[[19 1] [18 1]] [[17 1] [16 1]]]]]
And I canβt figure out how to not produce it that way. This is my floater
reducer:
(reduce (fn [acc [masked-addr value]]
(let [floater (fn floater [addr floating]
(if-not (seq? addr)
[(->> floating
(apply (partial str "2r"))
(read-string))
value]
(let [d (first addr)]
(if (= 1 (count d))
(floater (next addr) (conj floating (first d)))
[(floater (next addr) (conj floating (first d)))
(floater (next addr) (conj floating (second d)))]))))]
(conj acc (floater masked-addr []))))
[])
β¦ help?(I also tried using for
but that got even uglier. π
I figured it out now. At least I figured out a way to get this neat structure:
[[(59 58 27 26) 100] [(27 26 25 24 19 18 17 16) 1]]
concat
is my buddyNext question then. This is my working floater:
(fn floater [addr floating]
(if-not (seq? addr)
[(->> floating
(apply (partial str "2r"))
(read-string))]
(let [ds (first addr)]
(if (= 1 (count ds))
(floater (next addr) (conj floating (first ds)))
(mapcat #(floater (next addr) (conj floating %)) ds)))))
It seems to me that this should be a general problem, finding all paths through a structure like this. I think I can generalize my solution, but wonder if there might already be one out there? In core even? My google fu fails me.So, then I am ready to share my solution. It takes half a sec to step 2 compute my input, so clearly there are cpu cycles wasted, but I learnt a lot fiddling with this to and from today. Please feel invited to provide feedback to this Clojure learner:
(defn parse [input]
(->> (clojure.string/split-lines input)
(map #(->> (clojure.string/split % #" ")
((fn [[op _ arg]] [op arg]))))
(map (fn [[op arg]]
(if (= op "mask")
{:mask arg}
{:addr (->> (clojure.string/replace op #"^\D+|\D+$" "")
(Long/parseLong))
:value (Long/parseLong arg)})))))
(comment
(def input (util/fetch-input 14))
(def input "mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X
mem[8] = 11
mem[7] = 101
mem[8] = 0")
; step 1
(->> input
(parse)
(reduce (fn [acc instruction]
(if-let [mask (:mask instruction)]
(merge acc
{:mask mask
:mask-or (->> (clojure.string/replace mask #"X" "0")
(str "2r")
(read-string))
:mask-and (->> (clojure.string/replace mask #"X" "1")
(str "2r")
(read-string))})
(let [{:keys [addr value]} instruction
{:keys [mask-and mask-or]} acc
masked-value (-> value
(bit-or mask-or)
(bit-and mask-and))]
(-> acc
(update-in [:memory addr] #(bit-or mask-or masked-value (or % 0)))
(update-in [:memory addr] #(bit-and mask-and masked-value (or % 0)))))))
{})
:memory
(vals)
(apply +))
; step 2
(def input "mask = 000000000000000000000000000000X1001X
mem[42] = 100
mask = 00000000000000000000000000000000X0XX
mem[26] = 1")
(->> input
(parse)
(reduce (fn [acc instruction]
(def acc acc)
(if-let [mask (:mask instruction)]
(merge acc
{:mask mask})
(let [{:keys [addr value]} instruction
{:keys [mask]} acc
masked-addr (-> addr
(#(Integer/toBinaryString %))
(->> (format "%36s"))
(clojure.string/escape {\space \0})
(->> (map (fn masker [m a]
(case m
\0 [a]
\1 [\1]
\X [\1 \0]))
mask)))]
(update acc :assignments conj [masked-addr value]))))
{:assignments []})
:assignments
(reduce (fn [acc [masked-addr value]]
(let [floater (fn floater [addr floating]
(if-not (seq? addr)
[(->> floating
(apply (partial str "2r"))
(read-string))]
(mapcat #(floater (next addr) (conj floating %)) (first addr))))]
(conj acc [(floater masked-addr []) value])))
[])
(reduce (fn [assignments assignment]
(merge assignments
(let [[addresses value] assignment]
(reduce (fn [acc address]
(assoc acc address value))
{}
addresses))))
{})
(vals)
(apply +)))
Most of the solution is generating a list of operations per bit index, so "1XX0"
would be [0 bit-clear 3 bit-set]
that are then applied to the value with reduce
.
For part 2 I use clojure.math.combinatorics/subsets
to get all the ways of picking the floating indices and assign bit-set and bit-clear based on which indices are in each subset. A little weird but it works π
https://github.com/Dexterminator/advent-of-code-2020/blob/main/src/day14/core.clj
fairly happy with how mine came out, just a bunch of reductions https://github.com/listba/advent-of-code-2020/blob/master/clojure/src/aoc_2020/days/14.clj
Good morning !
https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_14.clj
TIL bit-set
and bit-clear
π
Dirty, but works https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_14.clj
@dawran6 a bit refactored your floating function π
(defn floating-addresses [mask address]
(let [parsed-mask (map vector (iterate dec 35) mask)
inner (fn inner [mask address]
(if-let [[n m] (first mask)]
(case m
\0 (inner (next mask) address)
\1 (inner (next mask) (bit-set address n))
\X (concat (inner (next mask) (bit-clear address n))
(inner (next mask) (bit-set address n))))
[address]))]
(inner parsed-mask address)))
https://github.com/nbardiuk/adventofcode/blob/master/2020/src/day14.clj
Nice @zelark and @nbardiuk. I didnβt know about bit-set and bit-test π. Maybe I will clean mine up this evening. Dirty solution using bit-and and bit-or: https://github.com/transducer/adventofcode/blob/master/src/adventofcode/2020/day14.clj
Also my use of tree recursion and then calling flatten to get the leave values I donβt like, but not sure how to improve
Maybe by using similar pattern as for floating-addresses above with concat
Just when I decided to use Lua
the problem requires 64-bit intgeres :c
https://www.reddit.com/r/adventofcode/comments/kcpdbi/2020_day_11_part_2luaroblox_waiting_room/