adventofcode

Happy Advent 2020! Please put answers in the pinned threads or create one if it does not exist yet. | https://github.com/adventofcode-clojurians/adventofcode-clojurians | Join the private leaderboard with code 217019-4a55b8eb
2020-12-14T01:22:39.252Z

> 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 πŸ˜‰

πŸ˜ƒ 1
ryan echternacht 2020-12-14T02:55:15.252400Z

I agree @rob156. While it might literally be the Chinese remainder theorem, that's not the part of programming I enjoy/use often

2020-12-14T04:23:04.252800Z

Day 14 answers thread - Post your answers here

2020-12-14T08:03:33.259800Z

I like floating-addresses approach

2020-12-14T08:05:20.260Z

gonna refact my solution after work

βž• 2
genmeblog 2020-12-14T10:23:10.260900Z

https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2020/day14.clj

πŸ‘ 2
❀️ 1
pez 2020-12-14T12:18:24.262Z

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 +)))

πŸ‘ 2
misha 2020-12-14T13:17:13.263900Z

I ChiefStringOfficer'ed this one :d: https://github.com/akovantsev/adventofcode/blob/master/src/adventofcode/y2020/day14.cljc

bnstvn 2020-12-14T13:27:03.264300Z

a long one https://github.com/bnii/advent-of-code-2020/blob/main/src/day14.clj

πŸ‘ 1
benoit 2020-12-14T13:51:31.264800Z

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

benoit 2020-12-14T13:52:17.265200Z

My worst performance of the season (according to my criterias) πŸ™‚

2020-12-14T13:57:31.265400Z

I cleaned up my code a bit: https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_14.clj

πŸ‘ 1
2020-12-14T14:11:56.265900Z

I’m glad someone uses str/escape now πŸ™‚

2020-12-14T14:12:20.266100Z

That’s thanks to @plexus and his videos

2020-12-14T14:12:38.266300Z

He saw it somewhere and it spreads

πŸ‘ 2
2020-12-14T14:12:46.266500Z

was it from you?

2020-12-14T14:13:00.266700Z

Yes πŸ™‚

πŸ‘ 2
🍻 4
😊 1
2020-12-14T14:13:41.267100Z

people still like it https://twitter.com/alekszelark/status/1335185041962504192?s=20

❀️ 1
2020-12-14T14:17:55.267600Z

Also cleaned up my code. Thanks @genmeblog for inspiration https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_14.clj

πŸ’― 1
Joe 2020-12-14T14:29:02.268Z

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!

2020-12-14T16:05:15.269500Z

@genmeblog, btw in the part 2 just bit-or is enough

πŸ‘ 1
genmeblog 2020-12-14T16:09:10.269700Z

Oh, I will revisit it later, thanks! Very clean solution btw (yours)!

2020-12-14T19:03:09.270100Z

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/

2020-12-14T19:03:50.270400Z

I thought about it, but ran for the simplest solution.

pez 2020-12-14T21:49:18.272700Z

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?

pez 2020-12-14T21:51:08.272900Z

(I also tried using for but that got even uglier. πŸ˜ƒ

pez 2020-12-14T22:27:01.273100Z

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 buddy

pez 2020-12-14T22:32:09.273300Z

Next 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.

pez 2020-12-14T23:19:19.273600Z

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:

pez 2020-12-14T23:19:19.273800Z

(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 +)))

πŸŽ‰ 1
2020-12-15T00:28:11.274Z

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

πŸ‘ 3
Ben List 2020-12-15T16:12:39.295100Z

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

2020-12-14T06:10:12.253200Z

Good morning !

😁 4
2020-12-14T07:01:07.256400Z

TIL bit-set and bit-clear πŸ˜„

1
πŸ‘ 3
2020-12-14T07:02:26.256800Z

Dirty, but works https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_14.clj

πŸŽ‰ 4
2020-12-14T07:31:45.257400Z

@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)))

❀️ 1
🦜 1
πŸ™Œ 2
πŸŽ‰ 1
erwinrooijakkers 2020-12-14T07:49:22.258200Z

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

πŸ‘ 1
erwinrooijakkers 2020-12-14T07:55:20.259100Z

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

erwinrooijakkers 2020-12-14T07:57:02.259400Z

Maybe by using similar pattern as for floating-addresses above with concat

Average-user 2020-12-14T13:14:58.263700Z

Just when I decided to use Lua the problem requires 64-bit intgeres :c

1
😎 1