adventofcode

Happy Advent 2020! Please put answers in the pinned threads or create one if it does not exist yet. | https://github.com/adventofcode-clojurians/adventofcode-clojurians | Join the private leaderboard with code 217019-4a55b8eb
Christian 2020-12-31T10:38:55.244300Z

I am new to clojure and I make my way through the aoc2020 problems. I'm interested in your opinions about my day12 code. In python I would check the values and update some data, but with clojure I wanted to stay with away from mutables for the time being. There is two things I noticed. part1 and part2 are very similar but I dont know how to make it more compact. (would you prefer a github link to this?)

(ns advent-of-code.day-12
  (:require [clojure.edn :as edn]))

(defn update-position
  "returns the coordinate changes from an instruction"
  [instruction northsouth eastwest facing]
  (let [code (first (re-find #"[NSEWLRF]" instruction))
        number (edn/read-string (re-find #"\d+" instruction))]
    (cond
      (= code \N) [(+ northsouth number) eastwest facing]
      (= code \S) [(- northsouth number) eastwest facing]
      (= code \E) [northsouth (+ eastwest number) facing]
      (= code \W) [northsouth (- eastwest number) facing]
      (= code \L) [northsouth eastwest (mod (+ 360 (- facing number)) 360)]
      (= code \R) [northsouth eastwest (mod (+ 360 (+ facing number)) 360)]
      (= code \F) (cond
                    (= facing 270) [(+ northsouth number) eastwest facing]
                    (= facing 90) [(- northsouth number) eastwest facing]
                    (= facing 0) [northsouth (+ eastwest number) facing]
                    (= facing 180) [northsouth (- eastwest number) facing]))))

(defn part-1
  "Day 12 Part 1"
  [input]
  (loop
   [instructions input
    northsouth 0
    eastwest 0
    facing 0]
    (let [instruction (first instructions)
          otherinstructions (rest instructions)
          [newns, newew, newface] (update-position instruction northsouth eastwest facing)]

      (if (empty? otherinstructions)
        (+ (Math/abs newns) (Math/abs newew))
        (recur otherinstructions newns newew newface)))))

(defn update-position2
  "returns the coordinate changes from an instruction"
  [instruction northsouth eastwest shipNS shipEW]
  (let [code (first (re-find #"[NSEWLRF]" instruction))
        number (edn/read-string (re-find #"\d+" instruction))]
    (cond
      (= code \N) [(+ northsouth number) eastwest shipNS shipEW]
      (= code \S) [(- northsouth number) eastwest shipNS shipEW]
      (= code \E) [northsouth (+ eastwest number) shipNS shipEW]
      (= code \W) [northsouth (- eastwest number) shipNS shipEW]
      (= code \F) [northsouth eastwest (+ shipNS (* number northsouth)) (+ shipEW (* number eastwest))]
      (= code \L) (cond
                    (= number 90) [eastwest (- northsouth) shipNS shipEW] ;; n=a e=b => n=b e=-a) 
                    (= number 270) [(- eastwest) northsouth shipNS shipEW]
                    (= number 180) [(- northsouth) (- eastwest) shipNS shipEW])
      (= code \R) (cond
                    (= number 270) [eastwest (- northsouth) shipNS shipEW] ;; n=a e=b => n=b e=-a) 
                    (= number 90) [(- eastwest) northsouth shipNS shipEW]
                    (= number 180) [(- northsouth) (- eastwest) shipNS shipEW]))))

(defn part-2
  "Day 12 Part 2"
  [input]
  (loop
   [instructions input
    northsouth 1
    eastwest 10
    shipNS 0
    shipEW 0]
    (let [instruction (first instructions)
          otherinstructions (rest instructions)
          [newns, newew, newShipNS, newShipEW] (update-position2 instruction northsouth eastwest shipNS shipEW)]
      
      (if (empty? otherinstructions)
        (+ (Math/abs newShipNS) (Math/abs newShipEW))
        (recur otherinstructions newns newew newShipNS newShipEW)))))

2021-01-02T20:40:53.256700Z

I use the cycle fn to do rotations. Also I find the most enjoyable part is to β€˜clean up’ after part 1 and first modularize part 1 and retest, than add your part 2 tweaks on top of that. A good rule of thumb is to keep each function to 3-10 of no more than 80 columns for easier reading. Cheers!

πŸ‘€ 1
2021-01-02T20:42:06.257900Z

...”3-10 lines whenever possible...”, sorry

misha 2020-12-31T11:40:57.244400Z

It looks ok. Replacing cond with case or condp would save you a bunch of typing though. If it would be the code you had to maintain, it would make sense to replace loop with a step function, and a (->> state (iterate step) (drop-until done?) first calc-score) "pipeline", to decouple done condition from step logic, and make step function testable and replaceable, etc. But in the context of aoc - it is perfectly fine as is.

Christian 2020-12-31T12:40:20.244600Z

I had case first, but it would not evaliate my code

misha 2020-12-31T13:01:17.244800Z

can you show me?

Christian 2020-12-31T14:23:50.245Z

Ah, it was another day. I think I was trying to compare my value to something. Like if x is smaller than 4 and bigger than -14. and that would not work.

2020-12-31T15:00:32.245400Z

Apart from case and cond there's also core.match for when you'd prefer something like

(match [code (/ number 90) (<= 4 x 13)]
  [\N _ true] (do-something)
  [\R d _] (rotate-smth-by d))

πŸ‘€ 1
2020-12-31T18:48:56.247100Z

I'm having trouble understanding the logic for day 17

If a cube is active and exactly 2 or 3 of its neighbors are also active, the cube remains active. Otherwise, the cube becomes inactive.
    If a cube is inactive but exactly 3 of its neighbors are active, the cube becomes active. Otherwise, the cube remains inactive.

z=0
.#.
..#
###

After 1 cycle:

z=-1
#..
..#
.#.
How does top left in z=-1 turn on? It has 1 neighbour that is on (the top middle on z=0)

erwinrooijakkers 2021-01-04T18:52:46.258800Z

holymackerels 2020-12-31T18:52:30.247300Z

the examples for this one are confusing, it's not keeping like [0 0] on the top left, its always centering the display around the visible active ones

2020-12-31T18:53:12.247500Z

aaaaah

2020-12-31T18:53:16.247700Z

thanks!

holymackerels 2020-12-31T18:54:01.247900Z

its mentioned but briefly, I spent way to much time trying to make sense of the examples until someone pointed it out to me: > (and the frame of view follows the active cells in each cycle)

2020-12-31T18:54:25.248100Z

i saw that and didn't understand what it meant 😞