adventofcode 2020-12-12

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

๐Ÿ’ฏ 3
1

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

๐Ÿ˜‚ 1
๐Ÿฆœ 2
๐Ÿ™ˆ 1
3

@fabea87 has joined the channel

Feels like they are saving the easier ones for the weekends

๐Ÿ‘ 1

This Manhattan Distance things brings back Robocode memories for me.

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

๐Ÿ‘ 1

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.

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

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

โค๏ธ 2

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

โค๏ธ 1

Did anyone have flashbacks of the โ€œAnts demoโ€?

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

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.

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

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

well any of the 8

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

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

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

3:40? there goes my excuse

Day 12 answers thread - Post your answers here

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

๐Ÿ‘ 2

Nice golf skills

๐Ÿ˜‚ 2

@brann.jesper 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

Dunno what autocorrect is thinking about today. ๐Ÿ˜Ž

Inspiring @nbardiuk

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

๐Ÿ‘ 2
1

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, @vincent.cantin. 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. ๐Ÿ˜ƒ

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

๐ŸŽ‰ 3

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

๐Ÿ˜ƒ 1

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

๐Ÿ‘ 1

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

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

๐Ÿ‘ 1

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

๐Ÿ‘ 1

Pretty fast too, 0.3ms for part 2

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

Now I must run yours on my machine. Haha.

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

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.

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.

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

โ˜บ๏ธ 2

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

๐Ÿ‘ 3

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

๐Ÿ‘ 2

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

๐Ÿ‘ 3

Morning folks ^_^

๐ŸงŒ mode: my code runs under 1 second ! ๐Ÿ˜‰

2
๐Ÿ˜† 2

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