Fork me on GitHub
#adventofcode
<
2022-12-09
>
Joe Dumont05:12:47

I'm learning so much from all your solutions! Thanks for posting everyone. A quick question from a day8 function I saw:

(defn visible?
  [[tree & other-trees]]
  (every? #(< % tree) other-trees))
This captures edges too without needing a single arity version, e.g. (visible? [3]) ;;=> true but it's unclear to me what is happening with every? and the comparison when there's no other value to compare with. It's clearly not equivalent to (< (rest [3]) 3) .

pez07:12:22

other-trees will be nil when there are no args to destruct there. A way to investigate things like this is to use ”inline def”.

(defn visible?
  [[tree & other-trees]]
  (def tree tree)
  (def other-trees other-trees)
  (every? #(< % tree) other-trees))
Then call the function:
(visible? [3])
Then evaluate other-trees in the REPL.

Joe Dumont08:12:49

Thanks for the response. I understand other-trees will be nil, but I don't understand how it doesn't reduce to the comparison (< nil 3) and a NullPointerException, and what every? does with it.

pez08:12:23

Check out https://clojuredocs.org/clojure.core/every_q. In fact, I added a think about nil there just a few days ago, because it surprised me too.

Joe Dumont08:12:13

Aha! "vacuous truth"

pez08:12:35

Yeah, ChatGPT warns about it too 😃

🙃 1
pez08:12:09

ChatGPT's mix of things that makes sense and pure bullshit is interesting!

pez06:12:53

The hypocrisy of i using eval by other names, such as read-string, is going on to this day, though.

😆 8
jumar07:12:50

Quite good except the slow performance of Java land

nooga10:12:06

hehe, I don't even have eval in my implementation

nooga10:12:28

not because it's hard to make, it's actually trivial, I just don't want to include it

pez10:12:12

No free will in your kingdom, @UJEK1RGJ0? 😃

😆 1
nooga10:12:00

it's an edn

😂 2
pez11:12:39

Didn't see that one coming!

😁 1
nooga14:12:39

> toiling in obscurity is what you do in Java land apparently 😂

Andrew Byala07:12:55

Day 9 - Solutions

Andrew Byala07:12:44

Am I the only fool staying up late to code this and document it? Oh well, so be it! Fun puzzle today. 🙂https://github.com/abyala/advent-2022-clojure/blob/main/docs/day09.mdhttps://github.com/abyala/advent-2022-clojure/blob/main/src/advent_2022_clojure/day09.clj

👍 1
Callum Oakley07:12:08

https://github.com/callum-oakley/advent-of-code/blob/main/src/aoc/2022/09.clj early rather than late for me! agreed this was a fun one. getting more interesting now

norman07:12:33

https://gitlab.com/maximoburrito/advent2022/-/blob/main/src/day09/main.clj No - I stayed up too. I completely misunderstood the tail following head algorithm, but what I did worked for all sample inputs and the full input on part1 but not on part 2. After re-reading for the 47th time I finally figured out what I was doing wrong. uggghh.... I applies zero cleanup here, so it's a total mess

Eugene Huang10:12:02

👋 new clojurian here. after a rough day 8, am decently pleased with my solution today. happy for any notes! https://github.com/elh/advent-2022/blob/main/src/advent_2022/day_09.clj

👍 2
tschady10:12:37

I reused my grid/moves->path function which takes the input and returns all coords visited, made this trivial. Each subsequent knot treats the earlier knot like the head, so iterate works nicely. Refactored with core.matrix, thanks @U02CV2P4J6S https://github.com/tschady/advent-of-code/blob/main/src/aoc/2022/d09.clj

chef_kiss 4
Casey11:12:00

More verbose than I would like.. but I'm not golfing after all. https://github.com/Ramblurr/advent-of-code-2022/blob/main/src/aoc/day09.clj

tschady11:12:45

@U02CV2P4J6S nice idea, I’m going to replace some of my vector helpers with core.matrix/{+,-} now.

1
Felipe12:12:12

had a total brain freeze for some 10 minutes trying to come up with the generalized step fn reduction https://github.com/FelipeCortez/advent-of-code/blob/master/2022/09.clj

Callum Oakley12:12:23

@UA2U3KW0L good catch, thanks! cuts the time almost in half 😁 (from 200ms to 100ms)

Felipe12:12:06

ooo, nice!

Andrew Byala15:12:28

I like your move-rope implementation, @U076FM90B, since I was reducing over the indexes of my knot vector and calling update for the values in place. I think your reduce with conj of a new vector is a much cleaner solution. Once I update my blog, I think I'll be following suit!

👍 1
1
Alex Alemi15:12:20

I took a shortcut for part 1 that slowed me down for part 2. In part one since the head only moves up down left or right, the tail, if it moves always takes the old head position. This doesn't work for part two though as intermediate knots might move diagonally.

alekszelark16:12:23

@U076FM90B as usual like your solution especially when it comes to moving something ^_^ btw, just checked that clojure.math has signum.

nbardiuk16:12:58

@U067R559Q cool! I've never seen it TIL. Will try to integrate into next solutions

Mark Wardle18:12:01

Yikes. Wasn't sure I liked this today. Bizarrely, my solution to the second part is simpler and more general purpose (configurable numbers of knots) than my solution to the second part! One of those times knowing the second part would have helped! https://github.com/wardle/aoc2022/blob/main/src/day09.clj

Mark Wardle18:12:28

Think I need to learn 'iterate' given the posted solutions above!

Piotr Kaznowski18:12:47

Didn't know the clojure.core.matrix so had to reinvent some wheels, it's not super readable though:

(defn -mapf [fc ac] (mapv #(%1 %2) fc ac))

(defn follow [H T]
  (let [diff (map - H T)]
    (if (> (apply max (map abs diff)) 1)
      (let [fx (map #(cond (> % 0) inc (< % 0) dec :else *) diff)] (-mapf fx T))
      T)))

(defn solve [input len]
  (-> (reduce
       (fn [{p :pos :as g} [m s]]
         (let [go (partial -mapf ((zipmap ["R" "L" "U" "D"] [[inc *] [dec *] [* inc] [* dec]]) m))]
           (loop [p p, n (parse-long s), g g]
             (if (zero? n) (assoc g :pos p)
                 (let [np (reduce #(conj %1 (follow (last %1) %2)) [(go (first p))] (rest p))]
                   (recur np (dec n) (update g :vis #(conj % (last np)))))))))
       {:pos (repeat len [0 0]), :vis #{[0 0]}} input)
      :vis count))

(defn -main [day]
  (let [solution (->> (file->str day) (re-seq #"\w+") (partition 2) (partial solve))]
    {:part1 (solution 2) :part2 (solution 10)}))

nooga18:12:06

whew, slightly ugly but here it goes:

(ns day9)

(def dirs {"U" [0 -1] "D" [0 1] "R" [1 0] "L" [-1 0]})
(def data (->> "input/day9.txt" slurp lines
               (mapcat #(let [[d n] (split % " ")] (repeat (parse-long n) (dirs d))))
               (reductions #(mapv + %1 %2) [0 0])))

(defn next-pos [[tx ty] [hx hy]]
  (let [sign (fn [x] (cond (zero? x) x (< x 0) -1 :else 1))]
    (if (or (-> tx (- hx) abs (> 1)) (-> ty (- hy) abs (> 1))) 
      [(+ tx (sign (- hx tx))) (+ ty (sign (- hy ty)))]
      [tx ty])))

(let [paths (iterate (partial reductions next-pos) data)]
  (println "1:" (->> paths second (map str) set count))
  (println "2:" (->> (nth paths 9) (map str) set count)))
nailing next-pos took me ages cause I've made a dumb assumption

👏 3
Piotr Kaznowski18:12:51

Definitely need to learn how reductions work...

👀 1
Mark Wardle18:12:27

Me too! Great to see other people's solutions for ideas!

nooga18:12:30

also, my sets don't like vectors so I had to (map str) , it wouldn't be needed in Clojure

bhauman18:12:15

reductions is like reduce but it returns each step

bhauman18:12:44

so in the case of the snake of positions you only have to keep the last position in the accumulator

👍 1
Mark Wardle18:12:51

Yes I see - I went through contortions to track each step in my 'reduce' which would have been unnecessary!

Piotr Kaznowski18:12:33

Yup, that would make my solution much simpler

bhauman18:12:37

yeah I get it, it took me a minute to see the mapping to reductions

Mark Wardle18:12:22

I feel I would be cheating now to change it, but will keep in mind for coming days. That said, I am not sure I can look at my day 9 code and not change it... ! 😂

bhauman18:12:36

Hey if it’s in git, everyone can see the history….. so change away. That’s what I do anyway. It’s not that often that you can have this much fun coding, so I say maximize the fun and experimenting.

👍 1
nooga18:12:40

you know what helps? implementing the core functions as you solve

nooga18:12:48

you learn a ton this way

bhauman18:12:00

yeah I bet

😏 1
wevrem18:12:50

I came up with my own solution this morning, but looking over others I like some of the simpler approaches (i.e. reductions instead of loop/recur). Maybe I’ll go back and re-factor, but good enough for now. https://github.com/wevre/advent-of-code/blob/master/src/advent_of_code/2022/day_09_rope_snake.clj

tschady19:12:49

An advantage to iterate/reductions is you have all this step-wise data for the visualizations that you’ll never make

😂 3
Mark Wardle20:12:39

Right... this is very much simpler - TIL reductions is a super power. Updated code, still can be improved but good enough. https://github.com/wardle/aoc2022/blob/main/src/day09.clj

leinfink20:12:27

Haha, I had just discovered reductions today also! https://github.com/leinfink/aoc-2022-clj/blob/main/src/aoc22/day9.clj

👍 1
leinfink20:12:46

Nearly got crazy until I realised it had \d instead of \d+ in my regex so the latter parts of the input failed to parse correctly...

leinfink20:12:40

Reading through here, I wonder why it didn't occur to me to use reductions for the tail itself, and not just for the intermediate knots, as I did? :face_with_raised_eyebrow: Oh well, happy with my result 😇

Apple22:12:28

check if they are touching/overlap/neighbor

neighbor? (fn [xy1 xy2] (every? #{-1, 0, 1} (map - xy1 xy2)))
catch up to previous knot
(->> (map - prev curr)
     (map #({2 1, -2 -1} % 0))
     (map - prev))

👏 8
1
alekszelark07:12:45

@UP82LQR9N what a nice and neat solution

Max14:12:51

I thought this ended up being rather pretty

👍 3
genmeblog18:12:57

Also visualized how to knots travel. First knot and ninth knot (blues are knots from 1-8)

👏 1
genmeblog18:12:12

just for fun, rope with 100 knots 🙂

🙌 1
nbardiuk19:12:20

this visualization reminds me that people come up with part 3: what's the smallest number of knots such that the tail knot doesn't move https://www.reddit.com/r/adventofcode/comments/zgre9m/2022_day_9_bonus_mini_problem_only_try_after_part/

😄 1
genmeblog19:12:52

426 in my case...

❤️ 4
mbjarland10:12:40

very late to the game but finally got around to finishing day 09:

(ns aoc.day-09)

(let [ds    {\L [0 -1] \R [0 1] \U [-1 0] \D [1 0]}
      parse (fn [a [d n]] (concat a (repeat (parse-long n) (ds (first d)))))
      data  (reduce parse [] (partition 2 (re-seq #"\w+" (slurp "data/2022_09"))))
      head  (reductions #(mapv + %1 %2) [0 0] data)
      rope  (fn [[y x :as t] h]
              (let [[dy dx] (map - h t)
                    tx {0 0 2 1 -2 -1}]
                [(+ y (tx dy ({2 dy} (abs dx) 0))) (+ x (tx dx ({2 dx} (abs dy) 0)))]))
      tail  #(reductions rope [0 0] %)]
  (prn {:one (count (distinct (tail head)))
        :two (count (distinct (nth (iterate #(tail %) head) 9)))}))

👍 3
peterh01:12:53

Same here. I also made a visualization, mainly to verify my solution and because I want to get used to writing SVG. However, ran into stack overflow with the actual data, so I guess canvas would have been a better choice here. 🙂 https://github.clerk.garden/formsandlines/aoc2022-clojure/commit/a068cdff5c85be281f7bf550313d5e9a2b05d573/src/advent_of_clerk/day_09.html

👏 2
clojure-spin 1
1
peterh19:12:40

Omg, reductions would have made my life so much easier (it seems like I am not the only one, looking at this thread). Also, I really like the approach of using map for simple vector math that I have seen in some solutions. I also have to remember to make more clever use of default values in collection getters.

Casey14:12:38

Anyone know if there's an easy way to pair clerk and quil for simple web based visualizations?

nbardiuk15:12:47

maybe people in #C035GRLJEP8 can help. I guess there should be a way to assign custom visualiser for data based on its metadata, but I haven't looked into it.

Sam Ritchie22:12:15

I think Quil has been lagging way behind on jvm versions… it only works on jdk8 etc as far as I know

Sam Ritchie22:12:48

but if you are interested in Mathbox I can get you set up with Clerk and mathbox! https://mathbox.mentat.org/

Casey16:12:00

> I think Quil has been lagging way behind on jvm versions… it only works on jdk8 etc as far as I know Oh that's sad.. I haven't used it in quite a few years. But I thought it might be fun to use with this years AOC since there are some cool animated visualizations one can do. And since I've been using Clerk notebooks for AoC I thought it would be cool to pair them. I've also never used Quil in a web browser context, so not sure how that would work

Sam Ritchie17:12:49

Actually!! That might be totally fine since the cljs side uses p5.js which is up to date

genmeblog21:12:08

Is this your code? Now you know the truth...

nooga21:12:00

yes, this is my code from day 2

Apple21:12:35

ChatGPT likes you! I ask it what's the date today and all I get is 'no data', 'trained till 2021'

kenj21:12:47

I wonder if changing "day2" to something else would be enough to throw it off

Marcelo Fernandes21:12:32

I pasted the solution for my day 5 and asked for it to explain in human terms what it was doing. Not only did it figure out that it was an Advent of Code Day 5 solution (good namespace?) but also explained what the code was doing using words such as warehouse that weren't present in the solution. https://github.com/marceloschreiber/advent-of-code-clojure/tree/main/src/aoc/2022/day_05 (kind of hard to read)

nooga23:12:13

all that while it stopped learning in 2021

nooga23:12:26

I fear for my job in 5 years

nooga23:12:48

not now, but 5 years is enough, maybe we should all jump on the AI train 😂

mbjarland14:12:07

I asked chatgpt to opimtize some clojure core functions…came back with some interesting reasoning