This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-12-12
Channels
- # adventofcode (78)
- # announcements (5)
- # babashka (22)
- # beginners (230)
- # calva (18)
- # cider (26)
- # clj-kondo (1)
- # cljs-dev (1)
- # clojure (14)
- # clojure-austin (1)
- # clojure-dev (3)
- # clojure-europe (30)
- # clojure-switzerland (1)
- # clojure-uk (26)
- # clojurescript (33)
- # conjure (2)
- # cursive (2)
- # data-science (1)
- # datomic (9)
- # docker (1)
- # emacs (8)
- # events (4)
- # fulcro (64)
- # lambdaisland (3)
- # luminus (1)
- # off-topic (3)
- # pathom (6)
- # portal (1)
- # programming-beginners (5)
- # shadow-cljs (22)
- # tools-deps (8)
- # xtdb (4)
oh balls, i misread part 2, and have spent faaaar too long calculating how many empty seats i can see in any of the 8 directions until I hit an occupied seat.
I did the same thing the first time.. actually I counted all empty seats in any direction
yeah, i've done the same. Go off on all the 8 directions and count empty seats until i hit an occupied one
Day 12 answers thread - Post your answers here
This time it was relatively relax … having a clean code helped not getting confused, I think. https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_12.clj
Here's my (rough) code. I think it can be shorter and cleaner after I've slept a bit and can revisit it. https://github.com/rjray/advent-2020-clojure/blob/master/src/advent_of_code/day12.clj
Part 1, quick-n-dirty
(def raw-input (str/split-lines (slurp "resources/day12.data")))
(defn proc1 [i]
(let [[c nstr] (split-at 1 i)]
[(first c) (read-string (apply str nstr))]))
(def input (map proc1 raw-input))
(def move {\E [1 0] \W [-1 0] \N [0 1] \S [0 -1] })
(def dir->ang {\E 0 \N 90 \W 180 \S 270})
(def ang->dir {0 \E 90 \N 180 \W 270 \S})
(defn turn [currdir turndeg op]
(let [currang (dir->ang currdir)
newang (mod (op currang turndeg) 360)]
(ang->dir newang)))
(defn go [currpos direc howfar]
(let [[currx curry] currpos
[direcx direcy] (move direc)
newx (+ currx (* direcx howfar))
newy (+ curry (* direcy howfar))]
[newx newy]))
(defn step [state inst]
(let [[i v] inst]
(case i
(\N \S \E \W) (update-in state [:pos] go i v) ;; go direction i v steps
\F (update-in state [:pos] go (:direction state) v) ;; go forward v steps
\R (update-in state [:direction] turn v -) ;; turn right v degrees
\L (update-in state [:direction] turn v +)))) ;; turn left v degrees
(defn solve [i]
(let [abs (fn [v] (if (neg? v) (- v) v))
init-state {:pos [0 0] :direction \E}
finstate (reduce step init-state i)
[px py] (:pos finstate)]
(+ (abs px) (abs py))))
;; example
(def ex1 [[\F 10] [\N 3] [\F 7] [\R 90] [\F 11]])
(solve ex1)
;; => 25
(solve input)
;; => 441
The final question (not the puzzle itself) is a bit confusing to me. That’s why I spent almost half an hour to figure out what is wrong with my second answer.
Even worse, I solved my first part getting the final calculation wrong. And it gave me the first star.
;; day 12
(def data (->> (slurp "input12.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v]
(let [[_ inst n] (re-find #"(\w)(\d+)" v)]
[inst (Long/parseLong n)])))))
(def initial-state {:dir "E"
"S" 0
"N" 0
"E" 0
"W" 0})
(def rotate {"L" {90 {"N" "W"
"W" "S"
"S" "E"
"E" "N"}
180 {"N" "S"
"S" "N"
"W" "E"
"E" "W"}
270 {"N" "E"
"W" "N"
"S" "W"
"E" "S"}}
"R" {90 {"N" "E"
"E" "S"
"S" "W"
"W" "N"}
180 {"N" "S"
"S" "N"
"W" "E"
"E" "W"}
270 {"N" "W"
"W" "S"
"S" "E"
"E" "N"}}})
(def state (reduce
(fn [{dir :dir :as state} [instraction n]]
(case instraction
"F" (update state dir + n)
("L" "R") (assoc state :dir (get-in rotate [instraction n dir]))
("N" "S" "W" "E") (update state instraction + n)))
initial-state
data))
(+ (Math/abs (- (state "N") (state "S")))
(Math/abs (- (state "E") (state "W"))))
;; part 2
;;
(def data (->> (slurp "input12.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v]
(let [[_ inst n] (re-find #"(\w)(\d+)" v)]
[inst (Long/parseLong n)])))))
(defn rotate [{{E "E" W "W" S "S" N "N"} :waypoint :as state}
dir
degree]
(assoc state :waypoint (get-in {"L" {90 {"N" E
"W" N
"S" W
"E" S}
180 {"N" S
"S" N
"W" E
"E" W}
270 {"N" W
"E" N
"S" E
"W" S}}
"R" {90 {"N" W
"E" N
"S" E
"W" S}
180 {"N" S
"S" N
"W" E
"E" W}
270 {"N" E
"W" N
"S" W
"E" S}}}
[dir degree])))
(rotate initial-state "R" 90)
(def initial-state {:waypoint {"E" 10
"N" 1
"W" 0
"S" 0}
"S" 0
"N" 0
"E" 0
"W" 0})
(defn move-forward [{waypoint :waypoint :as from} times]
(reduce (fn [state [dir n]] (update state dir + (* n times)))
from
waypoint))
(move-forward initial-state 10)
(def state (reduce
(fn [state [instruction n]]
(case instruction
"F" (move-forward state n)
("L" "R") (rotate state instruction n)
("N" "S" "W" "E") (update-in state [:waypoint instruction] + n)))
initial-state
data))
(+ (Math/abs (- (state "N") (state "S")))
(Math/abs (- (state "E") (state "W"))))
I forgot about Math/abs
. Thx Dosbol
Looking at all of your solutions I think I have some work to do regarding not leaning too heavily on loop/recur 😅 https://github.com/Yopi/advent-of-code/blob/master/src/adventofcode/2020/day12.clj
@UAWTW2REE You may save yourself some time by using case
That also makes a lot of sense, thank you! I saw cond
used somewhere and forgot all about case
😄
My program (step 1) crashes with an arity excretion at what appears to be just when the final position is reduced. I love everything about Clojure except its error messages and stack traces...
Arity excretion ? XD
Try completing
Inspiring @U076FM90B
You combined part 1 and 2 by having a “shift” as a concept, how big the steps are when moving forward
How you exactly do rotation so concisely is unclear to me I hope to figure it out
I have this monstrosity:
\L (update acc :waypoint-location
(case n
90 (comp rotate-right rotate-right rotate-right)
180 (comp rotate-right rotate-right)
270 rotate-right))
\R (update acc :waypoint-location
(case n
270 (comp rotate-right rotate-right rotate-right)
180 (comp rotate-right rotate-right)
90 rotate-right))
I have 2 vectors: position [x y] and direction [dx dy]. Rotation changes direction vector using rotation matrix that I've grabbed from wikipedia https://en.wikipedia.org/wiki/Rotation_matrix#Common_rotations

Haha, I have this:
(defn rotate [dir degrees]
(case degrees
90 [({[0 1] [1 0]
[1 0] [0 -1]
[0 -1] [-1 0]
[-1 0] [0 1]} dir)]
180 [({[0 1] [0 -1]
[1 0] [-1 0]
[0 -1] [0 1]
[-1 0] [1 0]} dir)]
270 [({[0 1] [-1 0]
[1 0] [0 1]
[0 -1] [1 0]
[-1 0] [ -1]} dir)]
dir))
Not only you, check out the other solutions 🙂
I can’t yet. Have this crash in step 1 to sort out. Then of course step 2 will probably take me a while too. 😃
Not sure how to use completing
for the problem, @U8MJBRSR5. My function for reducing the instructions looks like so:
(defn run [program]
(reduce (fn [ferry [op arg]]
(let [{:keys [dir]} ferry]
(cond
(dirs op) (update ferry :pos #(move % (dirs op) arg))
(= "F" op) (update ferry :pos #(move % dir arg))
(= "R" op) (update ferry :dir #(rotate % arg))
(= "L" op) (update ferry :dir #(rotate % (get {90 270 270 90} arg arg))))))
{:pos [0 0]
:dir [1 0]}
program))
(Edited to fix a confusing update of :dir
.)The function works for the example input of ""F10 N3 F7 R90"
then croaks if the next instruction is an F
instruction. (All other instruction types work…) Also the updated function doesn’t crash with arity problems, but with
class clojure.lang.PersistentVector cannot be cast to class java.lang.Number
I think I have a hint at the problem now. I’ll go back and beg for help here if it doesn’t lead anywhere. 😃
Solution to Day 12: https://github.com/benfle/advent-of-code-2020/blob/main/day12.clj
OMG. My head spins now. This was a tough one for me.
(defn parse [input]
(->> (re-seq #"\w\d+" input)
(map #(re-seq #"(\w)(\d+)" %))
(mapv (fn [[[_ op arg]]] [op (Long/parseLong arg)]))))
(def dirs {"N" [0 1]
"E" [1 0]
"S" [0 -1]
"W" [-1 0]})
(defn move [pos dir dist]
(let [movement (map * dir [dist dist])]
(->> pos
(mapv + movement))))
(defn towards [{:keys [me wp]} n]
(let [[dx' dy'] (map - wp me)
[dx dy] (map * [dx' dy'] [n n])]
{:me (map + me [dx dy])
:wp (map + wp [dx dy])}))
(defn rotate [[x y] degrees]
(case degrees
90 [(- (* x 0) (* y -1)) (+ (* x -1) (* y 0))]
180 [(- (* x -1) (* y 0)) (+ (* x 0) (* y -1))]
270 [(- (* x 0) (* y 1)) (+ (* x 1) (* y 0))] ))
(defn rotate-around [origin degrees pos]
(let [[dx' dy'] (map - pos origin)
[dx dy] (rotate [dx' dy'] degrees)]
(map + origin [dx dy])))
(defn run [program]
(reduce (fn [system [op arg]]
(let [{:keys [me]} system]
(cond
(dirs op) (update system :wp #(move % (dirs op) arg))
(= "F" op) (towards system arg)
(= "R" op) (update system :wp #(rotate-around me arg %))
(= "L" op) (update system :wp #(rotate-around me (get {90 270 270 90} arg arg) %)))))
{:me [0 0]
:wp [10 1]}
program))
(defn abs [n]
(if (neg? n)
(- n)
n))
(comment
(def input (util/fetch-input 12))
(->> #_ "F10 N3 F7 R90 F11" input
(parse)
(run)
:me
(map abs)
(apply +)))
Well, the rotation around the ship was. The rest was pretty straight forward and I was mainly fighting my own sloppyness.
Here's my solution: https://github.com/chrisblom/advent-of-code/blob/master/src/adventofcode/2020/day12.clj
Lots of interesting rotation functions here. I came up with this:
(defn rotate [currdir turndeg op]
(let [currang ({\E 0 \N 90 \W 180 \S 270} currdir)
newang (mod (op currang turndeg) 360)]
({0 \E 90 \N 180 \W 270 \S} newang)))
;; example: rotate 90 degrees to the left (+) from East
(rotate \E 90 +) ;; \N
I feel like my solution is very basic compared to all the clever stuff people are doing. Just a couple nested case statements and vector literals 🙂 https://github.com/lambdaisland/aoc_2020/blob/main/src/lambdaisland/aoc_2020/puzzle12.clj
So, on my machine with your solution and your input, @plexus:
Evaluation count : 5046 in 6 samples of 841 calls.
Execution time mean : 120,907492 µs
Execution time std-deviation : 2,337936 µs
Execution time lower quantile : 118,892646 µs ( 2,5%)
Execution time upper quantile : 124,815435 µs (97,5%)
Overhead used : 6,737515 ns
My machine, my solution, your input: 1,189428 msAlso funny, while sanity checking my rotate
for step 2 I had something extremely like your version in my head. No idea why I didn’t just translate that. Haha.
Using core.matrix
for the rotations in part 2:
https://github.com/Dexterminator/advent-of-code-2020/blob/main/src/day12/core.clj

Nice mess, part 1: https://raw.githubusercontent.com/genmeblog/advent-of-code/master/images/advent_of_code_2020/day12_rules_1.jpg
my solution with rendering code: https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2020/day12.clj
Went with multimethods for day 12 https://github.com/chamaeleon/aoc2020-clj/blob/master/src/aoc2020/day12.clj
Day 12 part 2:
(defn parse-line [line]
(let [[inst v] (rest (re-find #"(\w)(\d+)" line))]
[(keyword inst) (Integer/parseInt v)]))
(defn parse-input [input]
(->> input
(str/split-lines)
(map parse-line)))
(defn rotate-waypoint [[wx wy] inst ang]
(cond (or (and (= inst :R) (= ang 90))
(and (= inst :L) (= ang 270))) [wy (- wx)]
(or (and (= inst :R) (= ang 270))
(and (= inst :L) (= ang 90))) [(- wy) wx]
(= ang 180) [(- wx) (- wy)]
(= ang 360) [wx wy]))
(defn forward [[sx sy] [wx wy] distance]
[(+ sx (* wx distance)) (+ sy (* wy distance))])
(defn move2 [{:keys [ship waypoint] :as acc} [inst d]]
(let [[wx wy] waypoint]
(case inst
:N (assoc acc :waypoint [wx (+ wy d)])
:S (assoc acc :waypoint [wx (- wy d)])
:E (assoc acc :waypoint [(+ wx d) wy])
:W (assoc acc :waypoint [(- wx d) wy])
:L (assoc acc :waypoint (rotate-waypoint waypoint inst d))
:R (assoc acc :waypoint (rotate-waypoint waypoint inst d))
:F (assoc acc :ship (forward ship waypoint d)))))
(->> (reduce move2 {:ship [0 0] :waypoint [10 1]} (parse-input (slurp "resources/2020/day12")))
(:ship)
(map #(Math/abs ^int %))
(reduce +))
Part 2, I just hard coded the rotations.Morning folks ^_^
Good morning
I solved the puzzle using clojure.core.protocols/nav
(kidding)
boring https://github.com/akovantsev/adventofcode/commit/1302d9721e3f385569684cd5ea4b15f48efd57ef
Step 2 movements done. Now to rotate. Big hmmm! Feels like it is my brain rotating and not the waypoint…


I recently worked on a turtle-like API for minecraft, so it definitely reminded me of that 🙂 https://github.com/plexus/witchcraft/blob/main/src/lambdaisland/witchcraft/cursor.clj
I don’t know about your weekends theory, @plexus. Today’s was tough for me. Made me realize I am maybe about to drop out soon. Could not afford to spend this amount of time during work days.
Annoying, my day 11 part 2 works with the test data, finishes with the real data but gives wrong answer. Completely lost to what hte problem is. Printing the grid and inspecting it is out the question.
If someone can add some left turns to the example data and provide it with the correct answer, then you could validate with that. I can't provide this right now. Busy with bbq. 😎
@qmstuart here's some test-input that should hit all discrete cases, plus an overview of what the ship's position and waypoint should be after each step: https://github.com/lambdaisland/aoc_2020/blob/main/src/lambdaisland/aoc_2020/puzzle12.clj#L111-L144
I had the same thing happen to me first as well, I had an error in my implementation for "W", and the demo input does not contain any west instructions, so the demo input ran fine, but the result on real input was wrong