Good morning !
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?
I am awaiting the difficult problems like a surfer awaiting its wave.
Agree! #6 usually starts ramping way up.
You can pick one from the last year ^_^
why give us a difficult problem on the weekend when you can save it for a weekday…
During the first 1 min 30, I was staring at a blank page, waiting for the page to load.
I will keep them for January.
AoC really starts the first time you add
(set! *unchecked-math* :warn-on-boxed)
(set! *warn-on-reflection* true)
to a namespaceI 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.
This is the first year I'm (seriously) trying to do this. Does it usually get harder day by day?
(Today's puzzle was pretty easy, but if they're going to get difficult I might not have time to see it through.)
Problems have been surprisingly simple so far this year
Last year for me, was by far the most difficult of them all
That’s probably because we’re going to vacation 😃
that or he’s lulling us into complacency just before dropping the hammer tomorrow
oh you got work Monday morning? Hope you remember A* search
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 🙂
I’ve done them since 2015, finished most but not all of them.. Except last year i bailed very early
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
they definitely get difficult and I was spending hours on problems routinely, but i’m not a fast solver
last year by like day 14 you had implemented a VM for a made up language, and then implemented pong using that language
Many thanks to folks who dropped into the live chats or left comments!
Cool.
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.
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)
lots of typing
Let me know if I leave too many comments during the streaming 😅 I have a hard time holding them while excited by the contest.
All good, it's nice to see some activity :)
Day 6 Answers Thread - Post your answers here
(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))))
(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)))
first pass, feels inelegant
i feel the same way, but 🤷
im guessing there’s a frequencies
-based solution
Also checkout pinned thread for day 6 https://clojurians.slack.com/archives/C0GLTDB2T/p1607104763255500?thread_ts=1607104763.255500&cid=C0GLTDB2T
I misread part1 and actually solve part2 first 🙂 https://github.com/benfle/advent-of-code-2020/blob/main/day6.clj
https://github.com/djblue/advent-of-code/blob/master/src/advent_of_code/core_2020.clj#L196
https://github.com/st3fan/aoc/blob/master/2020/advent-of-code/src/advent_of_code/day6.clj
Day 7 Answers Thread - Post your answers here
My solution https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_07.clj
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 🙂
I forgot about tree-seq … that’s a good idea.
🙂 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
(into (set found-bags) (mapcat #(find-outer-bags bags %) found-bags))
nice @zelark
I used this one as an https://github.com/ocisly/advent2020/blob/a96bd7be5e961d737bf33bc552724542e9e65d02/day-7.clj#L19-L41 to learn core.logic
... 😬
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
@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)))))
don't have good intuition for graphs, always struggle https://github.com/nbardiuk/adventofcode/blob/master/2020/src/day07.clj
(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))))
(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]))))
https://github.com/lambdaisland/aoc_2020/blob/main/src/lambdaisland/aoc_2020/puzzle07.clj
https://github.com/genmeblog/advent-of-code-2020/blob/master/src/advent_of_code_2020/day07.clj
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 :)
using loom: https://github.com/tschady/advent-of-code/blob/master/src/aoc/2020/d07.clj
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?)*\.
the *
doesn’t repeat the capture group like you think it does
i’d consider re-seq
visualization >_< https://i.redd.it/gx6l9oavzp361.jpg
> 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.
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
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.
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!
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")
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))
(->> (clojure.string/split-lines input)
(map #(clojure.string/split % #"[ ,]"))
(map #(->> %
(partition 2 5)
(map vec)
(map (partial apply str))))
((fn dig [look-for found rules]
(let [directs (reduce (fn [acc [bag & 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))
(->> (clojure.string/split-lines input)
(map #(clojure.string/split (str "1 " %) #"[ ,]"))
(remove #((set %) "no"))
(map #(->> %
(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] & bags]]
(->> (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)))
when I have troubles naming things, I know I don’t know what I am doing, but I pressed on on sheer intuition. ¯\(ツ)/¯
@zelark is my hero. his solution in this thread blows me away.
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)]
=>
(when (seq ?contained-bags)
(insert-all!
(mapv (fn [[kind num]]
(if (= kind "shiny gold")
(map->GoldBag {:parent-type ?type})
(map->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)]
=>
(insert! (map->GoldBag {:parent-type ?type})))
(defquery gold-bags []
[?gold-bags <- (acc/distinct :parent-type) :from [GoldBag]])
(defn run-rules []
(-> (mk-session :cache false)
(insert-all (doall (for [[k vs] (parse input)]
(map->ContainerBag {:type k
:contained-bags vs}))))
(fire-rules)))
;; Part I
(-> (run-rules)
(query gold-bags)
first
:?gold-bags
count)
;; => 179
It would be cool to dynamically generate defrules for each line
Day 8 Answers Thread - Post your answers here
https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_8.clj
Todays challenge was super fun! https://github.com/oxalorg/aoc/blob/main/src/day8.clj
It reminds me my old emulator https://github.com/green-coder/girlfriend-advance
(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)))))))))
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.
My version: https://github.com/lambdaisland/aoc_2020/blob/main/src/lambdaisland/aoc_2020/puzzle08.clj
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
https://github.com/transducer/adventofcode/blob/master/src/adventofcode/2020/day8.clj
https://github.com/akovantsev/adventofcode/blob/master/src/adventofcode/y2020/day08.cljc#L45-L54
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
Part 2 was nice. https://github.com/genmeblog/advent-of-code-2020/blob/master/src/advent_of_code_2020/day08.clj#L29-L36
Looks like most of us have similar approaches. https://github.com/benfle/advent-of-code-2020/blob/main/day8.clj
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
https://github.com/tschady/advent-of-code/blob/master/src/aoc/2020/d08.clj
https://github.com/bradlucas/advent-of-code-2020/blob/master/src/advent/day08.clj
https://redpenguin101.github.io/posts/2020_12_08_aoc2020_day8.html - this one did give me some flashbacks to intcode 😨
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
https://github.com/kfirmanty/advent-of-code-2020/blob/main/src/advent_of_code_2020/day8.clj
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->
the other day.
(defn parse [input]
(->> (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 (< pc length)
(let [[op arg] (nth program pc)]
(if (pcs pc)
(reduced cpu)
(cond-> 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
(->> input
(parse)
(run)
:acc)
; step 2
(->> 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))
I’m officially a day behind now and late to the party https://gist.github.com/KennyMonster/9b9db6daa056e41413112d0fb31a5e47
feels like part 2 could be way nice even brute forcing it… but I dunno how
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?@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
.
@djblue nice ... (str/split input #"*\n\n*")
that did not occur to me, I do a (partition-by empty?)
🙂
I've learnt a few neat functions from looking at you guys solution so far this year 🙂
Noob code coming up - but I am actually quite happy with this code, it reads nicely I think:
(defn count-group [group]
(->> group
(string/split-lines)
(map set)
(apply clojure.set/intersection)
(count)))
(->> (string/split (slurp "adv6.input.txt") #"\n\n")
(map count-group)
(reduce +))
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 😄
Answering my self: I just searched and found as->, a very nice function. This allows me to write e.g.
(as-> "adv6.input.txt" v
(slurp v)
(string/split v #"\n\n")
(map count-group v)
(reduce + v))
I am doing 2015 in parallel 😕
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
@narve YMMV, but I try not to use as->
, 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 (-> path slurp (str/split #"\n\n")]
(->> groups...))