This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-21
Channels
- # adventofcode (47)
- # aleph (18)
- # announcements (20)
- # babashka (81)
- # beginners (23)
- # biff (6)
- # calva (5)
- # cider (50)
- # clojure (34)
- # clojure-europe (19)
- # clojure-norway (11)
- # clojure-spec (6)
- # clojure-uk (1)
- # clojurescript (2)
- # conjure (2)
- # cursive (14)
- # datomic (1)
- # humbleui (11)
- # hyperfiddle (3)
- # introduce-yourself (5)
- # joyride (1)
- # nbb (7)
- # off-topic (19)
- # podcasts-discuss (1)
- # reagent (3)
- # reitit (19)
- # releases (1)
- # ring-swagger (1)
- # shadow-cljs (29)
- # sql (6)
- # squint (56)
https://gitlab.com/maximoburrito/advent2022/-/blob/main/src/day21/main.clj When part 2 came up, I wrote the code to generate an expression as a string. For the sample input, I was able to give that expression to wolfram alpha to solve, which it did. The full input was too long for wolfram. I was tempted to find something else that would solve it for kicks, but in the end i just wrote the code. The solver wasn't too hard, but it took at least an hour to figure out the cases correctly, which seems quite excessive...
https://github.com/callum-oakley/advent-of-code/blob/main/src/aoc/2022/21.clj
I did the symbolic manipulation... sort of. let human input be h
, then I kept track of the pair [a b]
(represents ah + b
) and then optimistically assumed that we'd never have to deal with an h^2
or h^-1
term... which turned out to be true 😅
I’m not sure my solution works for all datasets 🙈
Instead of replacing the root operator with =
I replaced it with compare
and used it to recursively narrow down to the right number.
I created the expression as a list first and then created a function simplify
that postwalks up the expression and evaluates all lists that contain just an operator and a number.
https://github.com/Oddsor/advent-of-code-clj/blob/master/src/y2022/d21.clj
Macro for part-1 (still working on part-2):
(defn parse [line] (split-line line #":\s|\s"))
(def data (map parse (read-data 2022 21)))
(defmacro build-oparations
[]
`(do ~@(for [[f a op b] data
:let [f (symbol f)]]
(do (println f a op b)
(if-not op
`(def ~f (constantly ~(parse-long a)))
(let [[a op b] (map symbol [a op b])]
`(do (declare ~a) (declare ~b)
(defn ~f [] (~op (~a) (~b))))))))))
(build-oparations)
(root)
;; => 83056452926300
totally changed my approach since someone pointed out that the graph is a tree (should have been obvious given the "root" hint :face_with_rolling_eyes:). since it's a tree the resulting function is guaranteed to be linear in h
, so you can take the value at two points and extrapolate
https://github.com/callum-oakley/advent-of-code/blob/main/src/aoc/2022/21.clj#L20-L24

Updated my part 2 https://github.com/zelark/AoC-2022/blob/master/src/zelark/aoc_2022/day_21.clj#L35-L42
I enjoyed today's puzzle. https://github.com/alexalemi/advent/blob/main/2022/clojure/p21.clj For the first part, I implemented a memoized recursive evaluator because I feared he would be unkind and have us recompute lots of things lots of times, but that turned out to be overkill. For part 2 I looked at the data and saw it was tree-like, so I wrote a solver but it simply 'unwinds' the equality at each stage. i.e. if we are sitting on a = x + b at the top, where a and b are numbers, we know that x = a - b. You can iterate this until you find the number.
Using promises & futures. (I recycled my code with very few changes from 2015 day 7.) These are the only 2 where I keep state, but I like how this reads:
(defn run-prog! [memory prog]
(reset! memory {})
(alloc-registers! memory prog)
(doseq [inst prog]
(exec-inst! memory inst)))
https://github.com/tschady/advent-of-code/blob/main/src/aoc/2022/d21.clj;; p1
(let [parse (fn [line]
(let [[id x op y] (map read-string (str/split line #":?\s"))]
[id (if (number? x) x (list op x y))]))
db (->> input (str/split-lines) (map parse) (into {}))]
(->> 'root db
(clojure.walk/prewalk-replace db)
(eval)
(time)))
"Elapsed time: 30.751088 msecs"
=> 353837700405464

part 1 using promises. let me see if I can do the same for part 2 https://github.com/FelipeCortez/advent-of-code/blob/master/2022/21.clj
Day 21: This was the funnest one for me. I did the symbolic algebra. https://github.com/bhauman/advent-of-code-2022/blob/main/src/adv2022/day21/sol.clj
geez I made the mistake of reading the other solutions… great job! not as much fun as symbolic solver 😉 but I wished I’d thought of the fact that it was a linear function. Would have definitely would have saved some time.
@U1Z392WMQ I thought I was being original with the promises and futures 😞
Showing my symbolic manipulation output:
(- (/ (+ 4 (* 2 (- humn 3))) 4) 150)
(normalize)
[+ -150 [* 1/4 (+ 4 (* 2 [+ -3 humn]))]]
(simplifier)
[+ -301/2 [* 1/2 humn]]
This is where ‘= is replaced with ‘- effectively setting the equation equal to 0.
The normalizing and simplifying code is pretty tidy thanks to core.match
(defn norm [[op exp1 exp2 :as all]]
(condp = op
'- (if (number? exp2)
['+ (* -1 exp2) exp1]
['+ exp1 ['* -1 exp2]])
'/ (if (number? exp2)
['* (/ 1 exp2) exp1]
all)
(if (number? exp2) [op exp2 exp1] all)))
(defn simplify-exp [[op x exp2 :as arg]]
(match [op (if (sequential? exp2) (vec exp2) [])]
['+ ['+ y other]] ['+ (+ x y) other]
['* ['* y other]] ['* (* x y) other]
['* ['+ y other]] ['+ (* x y) ['* x other]]
:else arg))
(def normalize (partial postwalk #(cond-> % (sequential? %) norm)))
(def simplifier (partial postwalk #(cond-> % (sequential? %) simplify-exp)))
My solution for part2:
1. adds to the data set y=x*z
and z=y/x
when x=y/z
is seen.
2. replaces root=x ops y
with x=y+0
and y=x+0
learned the first thing about core.logic https://github.com/benjamin-asdf/advent-of-code/blob/master/src/Y2022/day21_logic.clj it was expecially satisfying that part 2 executed instantly



Oh, I’d forgotten that core logic was a thing. Nice work!
@U064J0EFR I re-read the problem statement but didn’t find anything that said that each value is used only once
did I miss it?
I did my initial p2 solution using z3, because i was worried the equality could be really complex and nonlinear, but ended up making a really simple “reverse application” solution instead
but it assumes that humn
is only referenced in one branch, and only once
right, sure, but i mean the problem statement says nothing about this
properties of the input that aren't stated in the puzzle text have to be considered "part of the puzzle" imo or some previous days are borderline impossible
yeah there is definitely a stage of doing data analysis on the input for a few of these
e.g. 2019 day 16 for a particularly infamous example 😅
This is one of the things that has always frustrated me about aoc - the input isn't input to your problem, it IS the problem to solve. The text along side is not a problem spec, it's just some text to help you understand the puzzle/problem you are given. I've come to peace with it over the years of aoc and don't treat it like I would other kinds of programming challenges. I also, always, look at my input and the question asked before I even read the text.