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-06T05:17:56.309800Z

Good morning !

😁 4
fingertoe 2020-12-06T05:38:23.312500Z

Hello! Today’s problem was pretty straightforward.. I am tied with the amount of problems I finished last year.. Not close to burning out.. I wonder if it is going easy on us this year?

2020-12-06T05:58:26.314100Z

I am awaiting the difficult problems like a surfer awaiting its wave.

mchampine 2020-12-06T05:58:36.314400Z

Agree! #6 usually starts ramping way up.

2020-12-06T05:59:20.314900Z

You can pick one from the last year ^_^

👍 1
💯 1
kenj 2020-12-06T05:59:25.315200Z

why give us a difficult problem on the weekend when you can save it for a weekday…

😆 2
2020-12-06T06:00:17.315800Z

During the first 1 min 30, I was staring at a blank page, waiting for the page to load.

2020-12-06T06:03:36.316100Z

I will keep them for January.

plexus 2020-12-06T06:13:10.317100Z

AoC really starts the first time you add

(set! *unchecked-math* :warn-on-boxed)
(set! *warn-on-reflection* true)
to a namespace

👟 1
1
😏 3
2020-12-06T06:23:33.319200Z

I like @dos’s solution, which did not separate the input loading from the processing for the solution. It might be faster to type in that way.

james 2020-12-06T06:31:21.320700Z

This is the first year I'm (seriously) trying to do this. Does it usually get harder day by day?

james 2020-12-06T06:34:36.322700Z

(Today's puzzle was pretty easy, but if they're going to get difficult I might not have time to see it through.)

markw 2020-12-06T06:34:57.323Z

Problems have been surprisingly simple so far this year

markw 2020-12-06T06:35:13.323500Z

Last year for me, was by far the most difficult of them all

2020-12-06T06:36:10.324300Z

That’s probably because we’re going to vacation 😃

😄 1
markw 2020-12-06T06:37:36.324900Z

that or he’s lulling us into complacency just before dropping the hammer tomorrow

markw 2020-12-06T06:37:57.325300Z

oh you got work Monday morning? Hope you remember A* search

😁 4
plexus 2020-12-06T06:40:40.326700Z

I skipped AoC last year because the year before I ended up spending sometimes multiple hours on a single solution. If it gets like that again I'm out, but a bit more challenging than today's would be nice too 🙂

markw 2020-12-06T06:41:09.327700Z

I’ve done them since 2015, finished most but not all of them.. Except last year i bailed very early

plexus 2020-12-06T06:41:34.328600Z

Today's video: https://www.youtube.com/watch?v=b0a5siw85N4&feature=youtu.be I also talk a bit about the different ways that people solved yesterday's puzzle

👍 2
markw 2020-12-06T06:41:37.328800Z

they definitely get difficult and I was spending hours on problems routinely, but i’m not a fast solver

markw 2020-12-06T06:42:34.329400Z

last year by like day 14 you had implemented a VM for a made up language, and then implemented pong using that language

plexus 2020-12-06T06:42:34.329500Z

Many thanks to folks who dropped into the live chats or left comments!

james 2020-12-06T06:45:06.329800Z

Cool.

james 2020-12-06T06:45:39.330600Z

I'm not a fast solver either, and also I'm doing them in Clojure, which I don't really know, so I'm extra slow.

markw 2020-12-06T06:46:11.331200Z

i know the feeling… i’m trying to go back and do them in Go after I finish in Clojure, and it is … painful (i don’t know Go)

markw 2020-12-06T06:46:21.331400Z

lots of typing

2020-12-06T07:22:42.332100Z

Let me know if I leave too many comments during the streaming 😅 I have a hard time holding them while excited by the contest.

plexus 2020-12-06T07:56:58.333200Z

All good, it's nice to see some activity :)

devn 2020-12-06T10:34:05.334300Z

Day 6 Answers Thread - Post your answers here

devn 2020-12-06T10:34:57.334400Z

(ns day6
  (:require [clojure.string :as str]
            [clojure.set :as set]))

(def input "...")

(def groups (str/split input #"\n\n"))

;; Part I
(apply + (for [group groups] (count (distinct (str/replace group #"\n" "")))))

;; Part II
(apply + (for [group groups
               :let [people (str/split-lines group)
                     answer-sets (map set people)]]
           (count (apply set/intersection answer-sets))))

tws 2020-12-06T10:53:28.335100Z

(ns aoc.2020.d06
  (:require [aoc.file-util :as file-util]
            [clojure.set :refer [intersection]]
            [clojure.string :as str]))

(def input (map str/split-lines (file-util/read-chunks "2020/d06.txt")))

(defn part-1 [input]
  (reduce + (map (comp count distinct (partial apply str)) input)))

(defn part-2 [input]
  (reduce + (map (comp count (partial apply intersection) (partial map set)) input)))

tws 2020-12-06T10:53:45.335300Z

first pass, feels inelegant

devn 2020-12-06T10:59:02.335800Z

i feel the same way, but 🤷

devn 2020-12-06T11:00:43.336Z

im guessing there’s a frequencies-based solution

nbardiuk 2020-12-06T11:31:26.336200Z

Also checkout pinned thread for day 6 https://clojurians.slack.com/archives/C0GLTDB2T/p1607104763255500?thread_ts=1607104763.255500&cid=C0GLTDB2T

👍 1
benoit 2020-12-06T12:54:58.337400Z

I misread part1 and actually solve part2 first 🙂 https://github.com/benfle/advent-of-code-2020/blob/main/day6.clj

st3fan 2020-12-06T16:06:41.339200Z

Day 7 Answers Thread - Post your answers here

erwinrooijakkers 2020-12-07T08:18:00.352Z

Mine: https://github.com/transducer/adventofcode/blob/master/src/adventofcode/2020/day7.clj I don’t know why exactly I had to call set on the tree-seq entries in part 1 nor why I had to do apply + 1 in part 2, but it works 🙂

❤️ 2
2020-12-07T08:18:25.352400Z

I forgot about tree-seq … that’s a good idea.

erwinrooijakkers 2020-12-07T08:28:26.353Z

🙂 i now see set is because you have to find amount of different colors and + 1 is because you also have to count the containing bag

erwinrooijakkers 2020-12-07T08:30:32.354100Z

(into (set found-bags) (mapcat #(find-outer-bags bags %) found-bags)) nice @zelark

😁 1
➕ 1
2020-12-07T08:46:18.355200Z

I used this one as an https://github.com/ocisly/advent2020/blob/a96bd7be5e961d737bf33bc552724542e9e65d02/day-7.clj#L19-L41 to learn core.logic... 😬

👍 3
👏 1
erwinrooijakkers 2020-12-07T09:05:55.355900Z

Wow nice, I tried to use core.logic last year for a somewhat similar problem (https://adventofcode.com/2019/day/14) but I did not manage

👍 1
2020-12-07T09:30:57.356400Z

@erwinrooijakkers thanks to your solution for part 2, I simplified mine. Now it’s pretty straightforward

(defn count-bags [bags [bag n]]
  (* n (apply + 1 (map #(count-bags bags %) (get bags bag)))))

😊 2
nbardiuk 2020-12-07T09:32:51.356600Z

don't have good intuition for graphs, always struggle https://github.com/nbardiuk/adventofcode/blob/master/2020/src/day07.clj

Dosbol 2020-12-07T09:34:20.357100Z

(loop [bags #{"shiny gold"}
       old-bags #{}]
  (if (= bags old-bags)
    (dec (count bags))
    (let [new-bags (into bags (map first
                                   (filter #(seq (clojure.set/intersection bags (second %))) data)))]
      (recur new-bags bags))))

Dosbol 2020-12-07T09:36:02.357500Z

(defn get-bags-inside [times [color amount]]
  [(mapv (partial get-bags-inside (* times amount)) (data color)) (* times amount)])

(dec (apply + (flatten (get-bags-inside 1 ["shiny gold" 1]))))

benoit 2020-12-07T13:45:42.362500Z

Nothing very exciting in my solution but I will post anyway 🙂 https://github.com/benfle/advent-of-code-2020/blob/main/day7.clj It took me way too long to figure out I was off by one for part 2 because I was counting the top shiny gold bag :)

2020-12-07T15:15:03.363600Z

What am I missing with this regex? Works fine for groups of 1 or two but fails with 3 or more (the second group gets improperly matched)

(\w+ \w+) bags? contain ((\d+) (\w+ \w+).*? bags?)(, (\d+) (\w+ \w+) bags?)*\.

tws 2020-12-07T15:19:57.363800Z

the * doesn’t repeat the capture group like you think it does

tws 2020-12-07T15:26:49.365100Z

i’d consider re-seq

2020-12-07T15:45:57.366600Z

visualization >_< https://i.redd.it/gx6l9oavzp361.jpg

😂 4
2020-12-07T15:56:03.367Z

> What am I missing with this regex? @jculp if you repeat a group, this group will be overwritten by the next match. For such cases you need to split a line, or just write 2 regex. Check my solution above for example.

Ben List 2020-12-07T16:59:20.368700Z

heres mine, O'm definitely interested to see what others came up with today as I'm fairly new to clojure still https://github.com/listba/advent-of-code-2020/blob/master/clojure/src/aoc_2020/days/07.clj

rjray 2020-12-07T20:02:27.370600Z

Here's mine: https://github.com/rjray/advent-2020-clojure/blob/master/src/advent_of_code/day07.clj Writing the parsing took longer than I'd like, but I really got stuck in part 1 due to a small logic-error. Part 2 only took about 10 more minutes.

Joe 2020-12-07T20:55:46.372100Z

https://redpenguin101.github.io/posts/2020_12_07_aoc2020_day7.html. So impressed at how concise some of the answers here are. That was a fun problem though!

➕ 1
mchampine 2020-12-07T23:09:07.376Z

Again, lots of effort spent on processing the raw input into a nice shape. I notice my part 2 recursive function has the same pattern as several others. Took me some grinding to get it working. Still not pretty, oh well.

;; with input processed as:
;;     ["dull aqua" ([4 "dark fuchsia"] [1 "shiny purple"])]
(defn count-nestedbags [inp topbag]
  (letfn [(rcount [bag]
            (let [[_ bt] bag
                  contained (second (first (filter #(= bt (first %)) inp)))]
              (apply + 1
                     (for [[bc bn :as thebag] contained]
                       (if (= bn "no other") bc
                         (* bc (rcount thebag)))))))]
    (dec (rcount [1 topbag]))))

(count-nestedbags input-part2 "shiny gold")

pez 2020-12-07T23:15:07.376500Z

This was so hard for me. It took me a lot of time to realize my first regex approach would not work. Then I had struggles wrapping my head around the recursion I needed. Then I made all sorts of silly mistakes even though the structure was right… And the result aint pretty!

(comment ; step 1
  (def input (util/fetch-input 7))
  (-&gt;&gt; (clojure.string/split-lines input)
       (map #(clojure.string/split % #"[ ,]"))
       (map #(-&gt;&gt; %
                  (partition 2 5)
                  (map vec)
                  (map (partial apply str))))
       ((fn dig [look-for found rules]
          (let [directs (reduce (fn [acc [bag &amp; bags]]
                                  (if (seq (clojure.set/intersection (set bags) look-for))
                                    (conj acc bag)
                                    acc))
                                #{}
                                rules)]
            (if (seq directs)
              (dig directs (conj found directs) rules)
              found)))
        #{"shinygold"} #{})
       (apply clojure.set/union)
       (count)))

(comment ; step 2
  (def input (util/fetch-input 7))
  (-&gt;&gt; (clojure.string/split-lines input)
       (map #(clojure.string/split (str "1 " %) #"[ ,]"))
       (remove #((set %) "no"))
       (map #(-&gt;&gt; %
                  (partition 3 5)
                  (map (fn [[n c1 c2]]
                         [(Integer/parseInt n) (str c1 c2)]))))
       ((fn dig [look-for found rules]
          (let [directs (reduce (fn [acc [[_n bag-color] &amp; bags]]
                                  (-&gt;&gt; (for [color look-for
                                             :when (= color bag-color)]
                                         (map #(repeat (first %) %) bags))
                                       (apply concat)
                                       (apply concat)
                                       (into acc)))
                                []
                                rules)]
            (if (seq directs)
              (dig (map second directs) (into found directs) rules)
              found)))
        ["shinygold"] [])
       (count)))

pez 2020-12-07T23:16:42.376700Z

when I have troubles naming things, I know I don’t know what I am doing, but I pressed on on sheer intuition. ¯\(ツ)

devn 2020-12-08T19:40:36.405400Z

@zelark is my hero. his solution in this thread blows me away.

➕ 2
devn 2020-12-08T19:49:07.405800Z

I didn’t finish Part II in this style yet, but I decided to try and do day7 in a rules engine (#clara). There’s a better way to write this, but this gets the right answer:

(defrecord ContainerBag [type contained-bags])
(defrecord IntermediateBag [parent-type type])
(defrecord GoldBag [parent-type])

(defrule produce-intermediate-bags
  [ContainerBag
   (= ?type type)
   (= ?contained-bags contained-bags)]
  =&gt;
  (when (seq ?contained-bags)
    (insert-all!
     (mapv (fn [[kind num]]
             (if (= kind "shiny gold")
               (map-&gt;GoldBag {:parent-type ?type})
               (map-&gt;IntermediateBag {:parent-type ?type
                                      :type kind})))
           ?contained-bags))))

(defrule indirect-gold-bags
  [ContainerBag
   (= ?type type)]
  [IntermediateBag
   (= ?type parent-type)
   (= ?intermediate-type type)]
  [GoldBag
   (= ?intermediate-type parent-type)]
  =&gt;
  (insert! (map-&gt;GoldBag {:parent-type ?type})))

(defquery gold-bags []
  [?gold-bags &lt;- (acc/distinct :parent-type) :from [GoldBag]])

(defn run-rules []
  (-&gt; (mk-session :cache false)
      (insert-all (doall (for [[k vs] (parse input)]
                           (map-&gt;ContainerBag {:type k
                                               :contained-bags vs}))))
      (fire-rules)))
;; Part I
(-&gt; (run-rules)
    (query gold-bags)
    first
    :?gold-bags
    count)
;; =&gt; 179

devn 2020-12-08T19:52:27.406100Z

It would be cool to dynamically generate defrules for each line

st3fan 2020-12-06T16:06:48.339500Z

Day 8 Answers Thread - Post your answers here

oxalorg (Mitesh) 2020-12-08T06:06:18.380100Z

Todays challenge was super fun! https://github.com/oxalorg/aoc/blob/main/src/day8.clj

2020-12-08T06:34:23.381800Z

It reminds me my old emulator https://github.com/green-coder/girlfriend-advance

🦜 1
🎮 5
2020-12-08T07:14:32.385400Z

(defn run-code [code]
  (let [history (atom #{})]
    (loop [acc 0
           ip  0]
      (let [[op arg] (nth code ip [:hlt 0])]
        (if (contains? @history ip)
          {:inf-loop acc}
          (do (swap! history conj ip)
              (case op
                :hlt {:halt acc}
                :nop (recur acc (inc ip))
                :acc (recur (+ acc arg) (inc ip))
                :jmp (recur acc (+ ip arg)))))))))

2020-12-08T08:06:00.385900Z

And my final solution: https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_08.clj in the Part 2 firstly I used case , but re-implement it with a hash-map as @plexus showed on the live stream.

fingertoe 2020-12-08T08:27:54.388300Z

I always feel filthy when I use atoms…. This one is pretty dirty, but I got it done: https://github.com/jreighley/aoc2020/blob/master/src/day8.clj

motform 2020-12-08T12:07:40.395300Z

definitely a bit engineered, but I’m not getting caught off-guard by a part 2: intcode boogaloo https://github.com/motform/advent-of-clojure/blob/master/src/advent-of-clojure/2020/eight.clj

benoit 2020-12-08T12:36:33.396700Z

Looks like most of us have similar approaches. https://github.com/benfle/advent-of-code-2020/blob/main/day8.clj

Lars Nilsson 2020-12-08T15:23:24.399100Z

Day 8 makes me appreciate immutable data structures and defmulti. I am fairly happy with my code for a change. https://github.com/chamaeleon/aoc2020-clj/blob/master/src/aoc2020/day08.clj

Joe 2020-12-08T18:49:00.404400Z

https://redpenguin101.github.io/posts/2020_12_08_aoc2020_day8.html - this one did give me some flashbacks to intcode 😨

👍 1
Ben List 2020-12-08T19:30:41.405Z

I really liked the intcode ones last year so I hope there's some future days that build this one up Anyways my solution for day 08 https://github.com/listba/advent-of-code-2020/blob/master/clojure/src/aoc_2020/days/08.clj

pez 2020-12-08T22:44:59.419600Z

I tried for so long do step 2 in a tree-ish way. Gave up. The brute force was with me though. Copying the program and modifying each one differently worked. I want my gold stars! Glad I learned about cond-&gt; the other day.

(defn parse [input]
  (-&gt;&gt; (clojure.string/split-lines input)
       (map #(clojure.string/split % #" "))
       (mapv (fn [[op arg]] [op (Integer/parseInt arg)]))))

(defn run [program]
  (let [length (count program)]
    (reduce (fn [cpu _]
              (let [{:keys [pc pcs]} cpu]
                (if (&lt; pc length)
                  (let [[op arg]         (nth program pc)]
                    (if (pcs pc)
                      (reduced cpu)
                      (cond-&gt; cpu
                        (= op "acc")        (update :acc #(+ % arg))
                        (#{"acc" "nop"} op) (update :pc inc)
                        (= op "jmp")        (update :pc #(+ % arg))
                        :always             (update :pcs conj pc))))
                  (reduced cpu))))
            {:acc    0
             :pc     0
             :length (count program)
             :pcs    #{}}
            (range))))

(comment
  (def input (util/fetch-input 8))
  ; step 1
  (-&gt;&gt; input
       (parse)
       (run)
       :acc)

  ; step 2
  (-&gt;&gt; input
       (parse)
       (#(repeat (count %) %))
       (keep-indexed (fn [i program]
                       (let [[op val] (program i)]
                         (assoc program i [(cond
                                             (= "nop" op) "jmp"
                                             (= "jmp" op) "nop"
                                             :else        op)
                                           val]))))
       (map run)
       (filter #(= (:pc %) (:length %)))
       (first)
       :acc))

🎉 1
kenj 2020-12-09T06:30:50.426400Z

I’m officially a day behind now and late to the party https://gist.github.com/KennyMonster/9b9db6daa056e41413112d0fb31a5e47

kenj 2020-12-09T06:31:10.426600Z

feels like part 2 could be way nice even brute forcing it… but I dunno how

pez 2020-12-09T21:38:26.486400Z

A reason part 2 took me so long is that I was looking at it as a tree problem. So I was able to build a structure something like so (simplyfied):

[[nop jmp]
 [acc]
 [acc]
 [jmp nop]
 [acc]]
But then I failed building the programs from this. Which for the example above would be:
[[nop acc acc jmp acc]
 [jmp acc acc jmp acc]
 [nop acc acc nop acc]
 [jmp acc acc nop acc]]
Does anyone have any pointers on how to go about it?

2020-12-10T01:41:50.011700Z

@pez Here is what I would do to optimize this problem: • Collect all the switch-indexes , indexes of the nop and jmp where the original program go before an infinite loop is detected, because the solution is to flip one of those indexes. • Build the reverse-jmp-graph, where edges are from jmp-targets to jmp-sources. • In this graph, collect all land-indexes which are reachable from the end of the program. • Find which change on instructions at switch-indexes let the program go into instructions at land-indexes .

st3fan 2020-12-06T16:08:29.339800Z

@djblue nice ... (str/split input #"*\n\n*") that did not occur to me, I do a (partition-by empty?) 🙂

💯 1
🤘 1
2020-12-06T19:08:27.341300Z

I've learnt a few neat functions from looking at you guys solution so far this year 🙂

💯 1
Narve Saetre 2020-12-06T20:16:19.341900Z

Noob code coming up - but I am actually quite happy with this code, it reads nicely I think:

(defn count-group [group]
  (-&gt;&gt; group
       (string/split-lines)
       (map set)
       (apply clojure.set/intersection)
       (count)))

(-&gt;&gt; (string/split (slurp "adv6.input.txt") #"\n\n")
     (map count-group)
     (reduce +))

Narve Saetre 2020-12-06T20:18:55.342100Z

I love the -> and ->> macros, but sometimes they can't be used because the place to put the previous form is different ... any tips for that particular problem? Is there a -?> which "does the right thing depending on the form 😄

Narve Saetre 2020-12-06T20:28:46.342300Z

Answering my self: I just searched and found as->, a very nice function. This allows me to write e.g.

(as-&gt; "adv6.input.txt" v
      (slurp v)
      (string/split v #"\n\n")
      (map count-group v)
      (reduce + v))

st3fan 2020-12-06T22:46:35.344200Z

I am doing 2015 in parallel 😕

tws 2020-12-06T22:50:58.344700Z

In case you haven’t seen it, I highly recommend being well versed in all these base functions, really helps to know what’s possible. https://clojure.org/api/cheatsheet

👍 1
tws 2020-12-06T22:55:05.345Z

@narve YMMV, but I try not to use as-&gt;, I find it has maintenance problems for me. I like to just pull out the different one as a let, so there’s only 1 threading type. In this case, could do:

(let [groups (-&gt; path slurp (str/split #"\n\n")]
  (-&gt;&gt; groups...))