This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-02
Channels
- # adventofcode (63)
- # announcements (21)
- # babashka-sci-dev (1)
- # beginners (24)
- # biff (2)
- # calva (78)
- # cherry (6)
- # clj-commons (3)
- # clj-kondo (7)
- # clojure (91)
- # clojure-austin (2)
- # clojure-bay-area (6)
- # clojure-denmark (1)
- # clojure-europe (45)
- # clojure-nl (1)
- # clojure-norway (16)
- # clojure-portugal (3)
- # clojure-uk (1)
- # clojurescript (20)
- # conjure (11)
- # datalevin (13)
- # datomic (5)
- # emacs (14)
- # etaoin (15)
- # events (7)
- # fulcro (9)
- # funcool (1)
- # honeysql (26)
- # joyride (4)
- # kaocha (3)
- # lambdaisland (2)
- # malli (7)
- # off-topic (22)
- # pathom (29)
- # portal (58)
- # practicalli (8)
- # rdf (25)
- # reagent (14)
- # sci (3)
- # scittle (37)
- # shadow-cljs (10)
- # slack-help (2)
- # spacemacs (7)
- # sql (7)
- # tools-deps (1)
- # xtdb (2)
I'm sure there's a blog explaining this (I've had a look but couldn't find anything quite on point) but is there a 'best way' to reset the environment of an nREPL session? I'm trying Neovim with Conjure to solve AOC problems this year and found that the solution I built up for Day 1 was relying on some bindings that I'd renamed in my source file but which I didn't notice were gone until I later on tried to load the file again. What I have found online is more directed at larger scale systems, I just have two files (the source file for the day's solution and a utilities file with some helper functions).
You can remove a certain binding with https://clojuredocs.org/clojure.core/ns-unmap So, if you want to just remove all the bindings in the current namespace, you could eval something like:
(do-seq [sym (keys (ns-interns *ns*))]
(ns-unmap *ns* sym))
Note: that's usually good enough for re-evaluating a single namespace, but it won't eg. clean up other namespaces that have referred to previous bindings. If you need something that tracks dependencies, etc. you may need to use something more heavy-handed like clojure.tools.namespace.repl
Thanks. Yeah, I kind of want something that will just blow away everything (without requiring the REPL to be restarted) and so maybe clojure.tools.namespace.repl
is the place to look. Thanks for the above code, though. If the utilities
library remains stable, maybe that is all I need 🙂
I think the trick is to learn to eval things often as you make small changes. It should be rare to end up with so much change that you need to blow away everything to get back to a known steady-state.
Yeah, in this particular case, it was two instances where I'd renamed a binding but forgotten to update the references to it.
Perhaps the better solution is something that assists in refactorings like this (although that might be overkill for something like an AOC puzzle).
https://coyotesqrl.github.io/advent-of-code/2022/src/coyotesqrl/2022/day02.html
I suspect I'll be one of the few to take the particular strategy I used. I'm frankly just too tired to have done it more elegantly tonight.
3 lines of code + data: https://github.com/pwojnowski/advent-of-code/blob/master/src/aoc/aoc2022.clj
(ns aoc2022.day02
(:require [clojure.string :as s])
(:gen-class))
(def data
(->> (s/split-lines (slurp "resources/input02.txt"))
(map #(s/split % #" "))))
(defn round-result [s1 s2]
([3 6 0 3 6]
(+ ({"A" 0 "B" 2 "C" 1} s1)
({"X" 0 "Y" 1 "Z" 2} s2))))
(defn points-for-round [[s1 s2]]
(+ ({"X" 1 "Y" 2 "Z" 3} s2)
(round-result s1 s2)))
(defn my-shape-for-situation [s1 s2]
(["X" "Y" "Z" "X" "Y"]
(+ ({"A" 2 "B" 0 "C" 1} s1)
({"X" 0 "Y" 1 "Z" 2} s2))))
(defn part1 [data]
(transduce (map points-for-round) + data))
(defn part2 [data]
(transduce
(map (fn [[s1 s2]]
(->> (my-shape-for-situation s1 s2)
(vector s1)
points-for-round)))
+ data))
(ns day2)
(def syms {"A" 1 "B" 2 "C" 3 "X" 1 "Y" 2 "Z" 3})
(def domi {1 2 2 3 3 1})
(def losi {2 1 3 2 1 3})
(defn parse [l]
(map syms (split l " ")))
(def data (->> "input/day2.txt" slurp lines (map parse)))
(defn score [[a b]]
(+ (cond
(= a (domi b)) 0
(= a b) 3
:else 6)
b))
(defn strat [[a b]]
[a (case b
1 (losi a)
3 (domi a)
a)])
(println "1:" (->> data (map score) (reduce +)))
(println "2:" (->> data (map (comp score strat)) (reduce +)))
https://github.com/ValentinMouret/advent-2022/blob/main/src/day_02.clj's longer, but might be more readable. Feedback is welcome. 🙂
I just condensed the information into two lookup tables:
(def data (str "input-" day ".txt"))
(def get-score-1 {'(:A :X) 4
'(:B :Y) 5
'(:C :Z) 6
'(:A :Y) 8
'(:A :Z) 3
'(:B :X) 1
'(:B :Z) 9
'(:C :X) 7
'(:C :Y) 2})
(def get-score-2 {'(:A :X) 3
'(:A :Y) 4
'(:A :Z) 8
'(:B :X) 1
'(:B :Y) 5
'(:B :Z) 9
'(:C :X) 2
'(:C :Y) 6
'(:C :Z) 7})
(defn parse [lines]
(->> lines
(map #(str/split % #" "))
(map #(map keyword %))))
(parse (utils/read-lines data))
(defn part-1 [input]
(->> input
(map #(get-score-1 %))
(apply +)))
(defn part-2 [input]
(->> input
(map #(get-score-2 %))
(apply +)))
(part-1 (parse (utils/read-lines data)))
;; => 10404
(part-2 (parse (utils/read-lines data)))
;; => 10334
(ns aoc2022.day-2
(:require [aoc2022.misc :as misc]))
(defmulti score identity)
(defmacro score-methods [points]
`(do
~@(for [they ["A" "B" "C"]
I ["X" "Y" "Z"]]
`(defmethod score ~(format "%s %s" they I) [_#]
~(+ (get-in points [I I])
(get-in points [I they]))))))
(defn solve-1 []
(score-methods {"X" {"X" 1
"A" 3
"B" 0
"C" 6}
"Y" {"Y" 2
"A" 6
"B" 3
"C" 0}
"Z" {"Z" 3
"A" 0
"B" 6
"C" 3}})
(binding [misc/*day* 2]
(misc/read-lines
(fn [rounds]
(transduce
(map score)
+ 0
rounds)))))
(defn solve-2 []
(score-methods {"X" {"X" 0
"A" 3
"B" 1
"C" 2}
"Y" {"Y" 3
"A" 1
"B" 2
"C" 3}
"Z" {"Z" 6
"A" 2
"B" 3
"C" 1}})
(binding [misc/*day* 2]
(misc/read-lines
(fn [rounds]
(transduce
(map score)
+ 0
rounds)))))
(time
(dotimes [_ 1000]
(solve-1)))
;; 334ms
(time
(dotimes [_ 1000]
(solve-2)))
;; 291ms
with dynamic multimethods and macro 🙂my code today is very verbose https://github.com/nbardiuk/adventofcode/blob/master/2022/src/day02.clj
Mine looks pretty-ugly:
(let [to-int
(let [A (int \A) X (int \X)]
(fn [a x]
(+ (* 3 (- (int a) A))
(- (int x) X))))
p1 (int-array [4 8 3 1 5 9 7 2 6])
p2 (int-array [3 4 8 1 5 9 2 6 7])]
(defn day2 [^String fs]
(let [n (count fs)]
(loop [i 0 x 0 y 0]
(if (>= i n)
[x y]
(let [z (to-int (.charAt fs i) (.charAt fs (+ i 2)))]
(recur (+ i 4)
(+ x (aget p1 z))
(+ y (aget p2 z)))))))))
Runs decently-quickly:
(let [s (slurp "02.txt")]
(criterium.core/quick-bench (day2 s)))
; Evaluation count : 9996 in 6 samples of 1666 calls.
; Execution time mean : 60.479461 µs
; Execution time std-deviation : 302.265610 ns
; Execution time lower quantile : 60.114543 µs ( 2.5%)
; Execution time upper quantile : 60.909793 µs (97.5%)
Mostly static lookups... https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2022/day02.clj
Dictionary for the lookup of what beats what, invert it to get the hand to play for part 2 https://github.com/stuartstein777/clj-advent-of-code/blob/master/src/stuartstein777/2022/day2.clj
I parsed the file into "rock" "paper" "scissors" because "A", "B", "C", "X", "Y", "Z" was confusing me.
Isn't this a link to a private repository?
https://github.com/v-garcia/aoc_2022/blob/main/day2.clj
with rock paper scissors encoded as 0
1
2
https://github.com/luissantos/aoc/blob/main/src/luissantos/aoc_2022.clj
(defn round-score [round]
(case round
[:rock :paper] (+ 0 1)
[:rock :scissors] (+ 6 1)
[:paper :rock] (+ 6 2)
[:paper :scissors] (+ 0 2)
[:scissors :rock] (+ 0 3)
[:scissors :paper] (+ 6 3)
[:rock :rock] (+ 3 1)
[:paper :paper] (+ 3 2)
[:scissors :scissors] (+ 3 3)))
(defn pick-correct-hand [round]
(case round
[:x :paper] [:rock :paper]
[:x :rock] [:scissors :rock]
[:x :scissors] [:paper :scissors]
[:y :paper] [:paper :paper]
[:y :rock] [:rock :rock]
[:y :scissors] [:scissors :scissors]
[:z :paper] [:scissors :paper]
[:z :rock] [:paper :rock]
[:z :scissors] [:rock :scissors]))
(defn day2-part2 []
(let [hands {\A :rock \B :paper \C :scissors \X :x \Y :y \Z :z}]
(->> (string/split-lines (slurp "input/day-2-input-1.txt"))
(map #(string/replace % " " ""))
(map #(map hands %))
(map reverse)
(map pick-correct-hand)
(map round-score)
(reduce +))))
(ns day-02)
;;A-rock, B-paper, C-scissors, X-rock, Y-paper, Z-scissors
(def score-1 {\A {\X 4 \Y 8 \Z 3}
\B {\X 1 \Y 5 \Z 9}
\C {\X 7 \Y 2 \Z 6}})
;;X-loss, Y-draw, Z-win
(def score-2 {\A {\X 3 \Y 4 \Z 8}
\B {\X 1 \Y 5 \Z 9}
\C {\X 2 \Y 6 \Z 7}})
(defn input [score]
(for [[a _ b] (re-seq #".+" (slurp "../day_02.data"))]
((score a) b)))
(defn solution-1 []
(reduce + (input score-1)))
(defn solution-2 []
(reduce + (input score-2)))
Dear Advent of Coders!
The babashka-advent-of-code-template now lets you download input automatically when you set your AOC_SESSION
environment variable:
https://github.com/borkdude/advent-of-babashka-template#downloading-input
Also you can run the code on Github Codespaces now (if you just want to try it out)!
https://github.com/borkdude/advent-of-babashka-template#github-codespaces
Nice idea, this automatic download of the input. I also applied it to my AoC project.
Why not use Joyride for Advent of Code this year around? A first version of a Use #joyride for Advent of Code repository. It's full of typos and things I haven't thought about. I will improve on it! https://github.com/PEZ/joyride-aoc-2022
Couple of answers follow. https://clojurians.slack.com/archives/C053AK3F9/p1639157027128700
Also, fun fact: (set/map-invert who-beats-who) = (comp who-beats-who who-beats-who)
@U02P133R2SZ good one! didn't occur to me
All these beautiful, explicit solutions and I'm just playing code golf 😅
(def pt-one-points [4 8 3 1 5 9 7 2 6])
(def pt-two-points [3 4 8 1 5 9 2 6 7])
(def outcomes [["A" "X"] ["A" "Y"] ["A" "Z"]
["B" "X"] ["B" "Y"] ["B" "Z"]
["C" "X"] ["C" "Y"] ["C" "Z"]])
(def pt-one-scores (zipmap outcomes pt-one-points))
(def pt-two-scores (zipmap outcomes pt-two-points))
(with-open [rdr (-> "public/puzzle_inputs/day_two.txt"
io/resource
io/reader)]
(->> (line-seq rdr)
(transduce (map (comp #(get pt-one-scores %)
#(string/split % #"\s"))) + 0)))
;; 202202
(let [rule1 {["A" "Z"] (+ 0 3), ["A" "X"] (+ 3 1), ["A" "Y"] (+ 6 2)
["B" "X"] (+ 0 1), ["B" "Y"] (+ 3 2), ["B" "Z"] (+ 6 3)
["C" "Y"] (+ 0 2), ["C" "Z"] (+ 3 3), ["C" "X"] (+ 6 1)}
rule2 {["A" "X"] (+ 0 3), ["A" "Y"] (+ 3 1), ["A" "Z"] (+ 6 2)
["B" "X"] (+ 0 1), ["B" "Y"] (+ 3 2), ["B" "Z"] (+ 6 3)
["C" "X"] (+ 0 2), ["C" "Y"] (+ 3 3), ["C" "Z"] (+ 6 1)}
d (->> (slurp "src/y2022/input202202")
(re-seq #"\w")
(partition 2))]
(map #(->> d (transduce (map %) +)) [rule1 rule2]))
;; (12772 11618)
(Still learning, so probably my solution is not super idiomatic?)
(def rules
[[2 0 1] ;; R = 0 [who-loses who-draws who-wins]
[0 1 2] ;; P = 1
[1 2 0]]) ;; S = 2
(defn parse [line]
(let [[a b] (re-seq #"\w" line)]
[(index-of "ABC" a) (index-of "XYZ" b)]))
(defn result [[a b] part]
(if (= part 1)
(+ (inc b) (* 3 (.indexOf (rules a) b)))
(+ (inc ((rules a) b)) (* 3 b))))
(defn -main [day]
(let [input (map parse (file->lines day))
game (fn [p] (apply + (map #(result % p) input)))]
{:part1 (game 1) :part2 (game 2)}))
@UUAKPEMJ9 that looks good to me. One minor improvement, you can use destructuring to grab the chars from the line and avoid re-seq
:
(defn parse [[a _ b]]
[(index-of "ABC" a) (index-of "XYZ" b)])
Of course! Thanks for the hint, @UQL85PT29.
Hey everybody. I'm a CS teacher by day and Clojure hobbyist off hours. I wrote up a piece on days 1 and 2 wearing my teacher hat. The post isn't clojure specific but the embedded videos is a Clojure walkthrough of both days. No claims of being great solutions but wanted to share. Days 1 and 2 of #AdventOfCode from a teacher's persepctive: https://cestlaz.github.io/post/advent-2022-day01-01/
I actually stumbled on your video on YouTube before I saw this post. Really liked the way you talked through your thought process when finding the solution. Great work!
We recorded a demo of solving day 1 using Joyride at the office today. It’s in post processing. I think it will be pretty nice content when we’re done with it. Extra bonus is that my colleague made an ”answer” using Rust and an application he has written, that can run Rust code. I think I’ll attach that as an appendix. We’ll see.
The rust version as an appendix would be cool! :face_with_cowboy_hat: but I just thinking about AoC and Joyride on my walk so looking forward either way!