Fork me on GitHub

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

Vincent Cantin05:12:00

Day 18 answers thread - Post your answers here

Vincent Cantin05:12:00

Day 18 answers thread - Post your answers here


nice one @U8MJBRSR5!


mine is admittedly very hacky πŸ™‚

Vincent Cantin05:12:08

I am awaiting the solution from @U067R559Q, hope to learn something new again.

Vincent Cantin05:12:32

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 πŸ™‚


@U8MJBRSR5 today is your turn to teach us something πŸ™‚

☝️ 2
Vincent Cantin06:12:05

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.

waving 2

Here is my solution, based on postwalk as well, but without tricks for part 2

πŸ‘ 3
Joe11:12:24 no post walk, just good old recursive calls to evaluate. Feels very SICP'y

πŸ‘ 5

Lovely question. Defined two context-free grammars and used instaparse:

πŸ‘ 3
😍 1
πŸ‘ 1

(insta/visualize (arithmetic-parser2 "1 + (2 * 3) + (4 * (5 + 6))"))

Vincent Cantin16:12:49

@U2PGHFU5U at the end of your program, you do a map inside your reduce

Vincent Cantin16:12:01

you may also do something like

(->> input
  (map (comp-> arithmetic-parser (partial insta/transform parse-tree->sexp)))
  (reduce +))

πŸ‘ 1

(not mine) But I found this solution quite fun Don't know if this guy is here or not

πŸ‘ 3

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

R.A. Porter03:12:52

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

πŸŽ‰ 1

Should have gone with instaparse right away, I also got all the test data working but failed on the file.

πŸ‘ 1

(defn calc
  ;; outer
  ([priority form]
   (let [f (complement number?)
         x (reduce
             (fn [form ops]
               (if (f form)
                 (calc priority ops form)
                 (reduced form)))
     (if (f x) (first x) x)))

  ([priority OP form]
   (if (number? form)
     (loop [todo  (rest form)
            done  [(calc priority (first form))]]
       (if (empty? todo)
         (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
    (map #(read-string (str "[" % "]")))
    (map #(calc priority %))
    (reduce +)))

(assert (= 15285807527593  (solve i '[#{+ *}])))
(assert (= 461295257566346 (solve i '[#{+} #{*}])))

πŸ‘ 1

That was boring :c

Vincent Cantin06:12:41

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 Cantin06:12:42

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

thanks2 2
πŸ™ 2
Daw-Ran Liou11:12:58

TIL clojure.lang.Symbols 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:

;; surprise!
('+ 1 2)
;; => 2

('+ {'+ 1})
;; => 1
('+ {'+ +})
;; => #function[clojure.core/+]
('+ {'* *})
;; => nil
('+ {'* *} :not-found)
;; => :not-found

πŸ‘ 3
Daw-Ran Liou12:12:41

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

πŸ˜… 2
Vincent Cantin13:12:24

I did not know that. Thank you for sharing.