Fork me on GitHub
#adventofcode
<
2022-12-02
>
pyrmont02:12:45

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

pithyless02:12:30

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

pyrmont03:12:09

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 🙂

pithyless03:12:56

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.

pyrmont04:12:32

Yeah, in this particular case, it was two instances where I'd renamed a binding but forgotten to update the references to it.

pyrmont04:12:26

Perhaps the better solution is something that assists in refactorings like this (although that might be overkill for something like an AOC puzzle).

norman05:12:00

Day 2 - looks like we need a solutions thread

R.A. Porter06:12:46

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.

Martin Půda07:12:03

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

nooga08:12:30

(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 +)))

👏 3
Valentin Mouret10:12:21

https://github.com/ValentinMouret/advent-2022/blob/main/src/day_02.clj's longer, but might be more readable. Feedback is welcome. 🙂

sebastian10:12:38

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

👏 3
delaguardo10:12:38

(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 🙂

jaihindhreddy12:12:42

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

Stuart14:12:53

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

👏 1
Stuart14:12:28

I parsed the file into "rock" "paper" "scissors" because "A", "B", "C", "X", "Y", "Z" was confusing me.

pwojnowski14:12:54

Isn't this a link to a private repository?

Benjamin14:12:29

it's 404 for us

Stuart14:12:48

yeah, shit was private. I had no idea. SHould be public now 🙂

👍 2
Luis Santos17:12:44

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

mbjarland08:12:54

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

mbjarland09:12:30

A bit late to the game : / day job intervened, let's see if I can catch up

borkdude10:12:45

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

👀 2
👍 2
arnout20:12:06

Nice idea, this automatic download of the input. I also applied it to my AoC project.

👍 1
genRaiy12:12:10

FYI I am doing the challenges using scittle

🔥 4
metal 2
genRaiy12:12:53

I'm improving the visuals as I go along and ideas are welcome

pez13:12:15

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! joyride https://github.com/PEZ/joyride-aoc-2022

Stuart14:12:23

Why is map-invert in the set namespace ? :thinking_face:

nooga14:12:25

I'll put it in let-go's core I think

Alex Alemi15:12:04

Also, fun fact: (set/map-invert who-beats-who) = (comp who-beats-who who-beats-who)

👀 1
nooga17:12:01

@U02P133R2SZ good one! didn't occur to me

nooga17:12:44

it's basically shifting the table

borkdude14:12:05

@qmstuart because maps can be regarded as sets of key-value pairs? it beats me :)

Ben Lieberman14:12:57

All these beautiful, explicit solutions and I'm just playing code golf 😅

nooga14:12:56

please share 🙂

Ben Lieberman14:12:58

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

genRaiy15:12:08

nice

🙏 1
Apple15:12:07

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

👏 2
Piotr Kaznowski19:12:33

(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)}))

👏 1
Phil Shapiro21:12:45

@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)])

Piotr Kaznowski22:12:07

Of course! Thanks for the hint, @UQL85PT29.

genRaiy15:12:22

modest improvements to the UI

🎉 3
sci 1
🚀 1
1
zamansky21:12:48

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/

❤️ 6
Andrew Meiners14:12:40

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!

zamansky16:12:48

Thanks - wish I had time to make more.

pez21:12:56

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.

👍 1
1
Ben Lieberman21:12:34

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!

nooga22:12:53

man, I like it when I paste a giant fn from clojure.core and it just works