Fork me on GitHub
#adventofcode
<
2020-12-12
>
fingertoe03:12:44

Did anyone have flashbacks of the “Ants demo”?

markw03:12:29

more like game of life, these automata problems show up every year

Stuart03:12:22

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.

pez08:12:10

Sounds like it could pretty easily be transformed into the right solution, though.

Stuart03:12:51

I have no idea why

markw03:12:57

I did the same thing the first time.. actually I counted all empty seats in any direction

markw03:12:07

well any of the 8

Stuart03:12:29

yeah, i've done the same. Go off on all the 8 directions and count empty seats until i hit an occupied one

Stuart03:12:52

Well, its 3:40 am. Fix it tomorow I guess. Dammit

markw03:12:01

My reading comprehension falls off a cliff at 11 P.M. CST apparently

markw03:12:17

3:40? there goes my excuse

alekszelark04:12:38

Day 12 answers thread - Post your answers here

Vincent Cantin05:12:55

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

☺️ 6
rjray06:12:04

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

👍 9
mchampine06:12:10

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

👍 6
alekszelark07:12:30

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.

alekszelark07:12:41

Even worse, I solved my first part getting the final calculation wrong. And it gave me the first star.

Dos07:12:03

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

👍 9
Vincent Cantin08:12:15

I forgot about Math/abs. Thx Dosbol

joppe08:12:19

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

👍 6
Vincent Cantin08:12:06

Nice golf skills

😂 6
Vincent Cantin08:12:28

@UAWTW2REE You may save yourself some time by using case

joppe08:12:25

That also makes a lot of sense, thank you! I saw cond used somewhere and forgot all about case 😄

pez10:12:57

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

Vincent Cantin10:12:58

Arity excretion ? XD

pez10:12:58

Dunno what autocorrect is thinking about today. 😎

erwinrooijakkers10:12:51

You combined part 1 and 2 by having a “shift” as a concept, how big the steps are when moving forward

erwinrooijakkers10:12:18

How you exactly do rotation so concisely is unclear to me I hope to figure it out

erwinrooijakkers10:12:35

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

nbardiuk10:12:36

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

👍 6
thanks2 3
pez11:12:12

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

alekszelark11:12:24

Not only you, check out the other solutions 🙂

pez11:12:00

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

pez11:12:18

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

pez11:12:49

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 

pez11:12:24

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

pez11:12:09

It was the gnomes and kittens murder with my rotate that hit me. All good now.

🎉 9
benoit13:12:00

I used a shortcut for Part 1 so I redid it so it can be used as well for Part 2.

😃 3
pez14:12:42

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

👍 3
pez14:12:58

Well, the rotation around the ship was. The rest was pretty straight forward and I was mainly fighting my own sloppyness.

mchampine15:12:59

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

👍 3
plexus15:12:56

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

👍 3
plexus15:12:21

Pretty fast too, 0.3ms for part 2

pez15:12:15

0.3! Mine runs in 1.7ms. I thought that was fast.

pez15:12:41

Now I must run yours on my machine. Haha.

pez16:12:54

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 ms

pez16:12:19

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

Stuart23:12:16

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.

alekszelark05:12:09

Morning folks ^_^

Vincent Cantin06:12:06

troll mode: my code runs under 1 second ! 😉

gotta_go_fast 6
😆 6
Vincent Cantin06:12:48

I solved the puzzle using clojure.core.protocols/nav (kidding)

misha11:12:36

I wish all the discussion did not happen inside a single overpopulated thread

💯 9
thinking-face 3
pez12:12:16

Step 2 movements done. Now to rotate. Big hmmm! Feels like it is my brain rotating and not the waypoint…

🙈 3
upside_down_parrot 9
parrot 6
😂 3
plexus15:12:49

Feels like they are saving the easier ones for the weekends

👍 3
pez15:12:31

This Manhattan Distance things brings back Robocode memories for me.

plexus15:12:40

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

👍 3
pez15:12:37

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.

Stuart17:12:54

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.

pez17:12:58

The example data lacks left turns, so maybe start looking there?

pez18:12:36

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

plexus18:12:50

@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

plexus18:12:50

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

❤️ 6
plexus18:12:48

printing out the position and waypoint after each step allowed me to manually go through the steps and mentally compute what the expected output should be, then I noticed that my west was actually going east

❤️ 3