I thought day 17 looked reasonably easy at first⦠Now my back of the envelope guess for part 2 completion is 2.5 hours
guess that leaves me some time to consider my botched approach β¦ or just be lazy and let it finish before day 18 π
only an hour it turns outβ¦. yay?
While I have no clue what your solution looks like, maybe you can bring that down without rewriting your logic at all by using memoize
(if you have any functions that will often have the same inputs throughout execution)
yeah i was considering going in that direction, but i just scrapped version one and did a big refactor.. now itβs < 1 second for part 1 and about 10 for part 2, good enough for me
Nice!
Day 18 answers thread - Post your answers here
Here is my solution, based on postwalk
as well, but without tricks for part 2
https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_18.clj
I struggled with this one https://github.com/nbardiuk/adventofcode/blob/master/2020/src/day18.clj
https://github.com/RedPenguin101/aoc2020/blob/main/day18.clj no post walk, just good old recursive calls to evaluate. Feels very SICP'y
Lovely question. Defined two context-free grammars and used instaparse: https://github.com/transducer/adventofcode/blob/master/src/adventofcode/2020/day18.clj
(insta/visualize (arithmetic-parser2 "1 + (2 * 3) + (4 * (5 + 6))"))
@erwinrooijakkers at the end of your program, you do a map inside your reduce
you may also do something like
(->> input
(map (comp-> arithmetic-parser (partial insta/transform parse-tree->sexp)))
(reduce +))
(not mine) But I found this solution quite fun https://github.com/elektronaut/advent-of-code/blob/main/day18/day18.clj Don't know if this guy is here or not
I spent too much time on this today π https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2020/day18.clj
I feel you pain, I also manually processed tokens and spend too much time debugging precedence and parenthesis
Yeah... The most frustrating moment was when all tests were passing but total result was wrong. After a while I've found that (9*((1+1))+1)
gave different result than (9*(1+1)+1)
....
Instaparse solution for me https://github.com/benfle/advent-of-code-2020/blob/main/day18.clj
I also went the grammar + instaparse route, anticipating that part 2 might be harder or, finally, tomorrow would build upon today. Made for almost no clojure code, but here are my crappy grammars https://github.com/coyotesqrl/advent2020/blob/master/resources/day18-no-precedence.grammar https://github.com/coyotesqrl/advent2020/blob/master/resources/day18-plus-precedence.grammar
Should have gone with instaparse right away, I also got all the test data working but failed on the file. https://github.com/Dexterminator/advent-of-code-2020/blob/main/src/day18/core.clj
(defn calc
;; outer
([priority form]
(let [f (complement number?)
x (reduce
(fn [form ops]
(if (f form)
(calc priority ops form)
(reduced form)))
form
priority)]
(if (f x) (first x) x)))
;;inner
([priority OP form]
(if (number? form)
form
(loop [todo (rest form)
done [(calc priority (first form))]]
(if (empty? todo)
done
(let [[op x & todo] todo
f (eval op)
a (peek done)
b (if (list? x) (calc priority x) x)]
(if (OP op)
(recur todo (conj (pop done) (f a b)))
(recur todo (conj done op b)))))))))
(calc '[#{+} #{*}] '[(4 * (3 * 2 + 2) * (9 * 7 * 5 * 4 * 9) * (7 * 7 + 7 * 4 + 9)) + 6 * 4 + 8 + ((6 * 5) * 4 * (2 * 8 + 4 + 7 * 9 + 3) * 2 + 6) + 3])
(calc '[#{+} #{-}] '(10 + (6 * 5)))
(defn solve [input priority]
(->> input
(str/split-lines)
(map #(read-string (str "[" % "]")))
(map #(calc priority %))
(reduce +)))
(assert (= 15285807527593 (solve i '[#{+ *}])))
(assert (= 461295257566346 (solve i '[#{+} #{*}])))
https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_18.clj
https://github.com/euccastro/advent-of-code-2020/blob/master/src/advent/day18.clj
nice one @vincent.cantin!
mine is admittedly very hacky π
I am awaiting the solution from @zelark, hope to learn something new again.
mine is tricky π .. tricks are not always available.
I kind of knew postwalk existed but I had never used it so I stayed in string land all along π
That was boring :c
Maybe it means that we improved.
Don't think so. My solution is still pretty ugly, but that is because the problem is not very motivating. At least for me of course, it is a matter of taste.
@vincent.cantin today is your turn to teach us something π
Not fair, I will ask a refund. π
Nice catch to use postwalk
, I even didnβt remember about it.
Actually, I solved it in python, because it was faster for me. Now Iβm going to have breakfast and go to work.
Small note about how to test the type of something that looks like a βlistβ:
;; Only use list? when you are sure what you want to test is a list.
(list? (map identity (list :a :b))) ; false
(list? (cons :a (list :b))) ; false
(list? `(:a :b)) ; false
;; sequential? is more generic.
(sequential? (map identity (list :a :b))) ; true
(sequential? (cons :a (list :b))) ; true
(sequential? `(:a :b)) ; true
;; Note: Strings are seqable, but not sequential?
(sequential? "foo")) ; false
TIL clojure.lang.Symbol
s are also functions! I guess the purpose of it is to look up things inside a map or a set but Iβm not sure how to use this effectively. Here is the source code: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Symbol.java#L127-L133
;; surprise!
('+ 1 2)
;; => 2
('+ {'+ 1})
;; => 1
('+ {'+ +})
;; => #function[clojure.core/+]
('+ {'* *})
;; => nil
('+ {'* *} :not-found)
;; => :not-found
Had to learn this the hard way because my day 18 part 1 kept evaluating to the very last number in any given equation. :picard-facepalm:
('+ ('+ 1 ('* 2 3)) ('* 4 ('+ 5 6)))
;; => 6
I did not know that. Thank you for sharing.