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.
You can pick one from the last year ^_^
I will keep them for January.
Agree! #6 usually starts ramping way up.
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.
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
Many thanks to folks who dropped into the live chats or left comments!
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 :)
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
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
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
@djblue nice ... (str/split input #"*\n\n*") that did not occur to me, I do a (partition-by empty?) ๐
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))
@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...))yeah, I c your point. I can also use minor (-> or (->> lines within the larger thread-block as well. Just gotta pick the right tool for the job ๐
Day 7 Answers Thread - Post your answers here
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)
;; => 179It would be cool to dynamically generate defrules for each line
https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_7.clj
I need to improve my regex capture skills. Let me know if you have a fast way to do the parsing/capturing, I am interested to learn.
not ideal, but I came up with this for parsing
(defn parse-entry [entry]
(let [p (re-find #"\w+ \w+" entry)
cs (->> (re-seq #"(\d+) (\w+ \w+)" entry)
(reduce (fn [m [_ v k]] (assoc m k (Long/parseLong v))) {}))]
[p cs]))
(def bags (into {} (map parse-entry (str/split-lines input))))
I just realized that the algorithm for part2 could be used for part1
My naive solution: https://github.com/oxalorg/aoc/blob/main/src/puzzle7.clj Using some kind of memo could speed up first pass, but this works! ^_^
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
> 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. ยฏ\(ใ)/ยฏ
Day 8 Answers Thread - Post your answers here
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 .
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
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)))))))))
@maksut.cagil has joined the channel
@wilhelmberggren has joined the channel
I've learnt a few neat functions from looking at you guys solution so far this year ๐
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
@lukas.block has joined the channel
I am doing 2015 in parallel ๐
split keyboard? ๐