Fork me on GitHub

🧵Day 13 answers thread: post your answers here


this was a fun one..

(ns aoc21.day13
  (:require [ :as io]
            [clojure.string :as s]))

;; part 1

(defn parse-fold [s]
  (let [[_ var line] (re-matches #"fold along (.)=(\d+)" s)]
    [(keyword var) (Integer/parseInt line)]))

(defn make-grid [dots]
  (reduce (fn [g xy] (assoc g xy \X)) {} dots))

(defn input-data [filename]
  (let [[dots folds] (s/split (slurp (io/resource filename)) #"\n\n")]
    [(make-grid (partition 2 (map #(Integer/parseInt %) (re-seq #"\d+" dots))))
     (map parse-fold (s/split-lines folds))]))

(defn fold-y [grid offset]
  (into {} (map (fn [[[y x] _]] (cond (= x offset) nil
                                      (< x offset) [[y x] \X]
                                      (> x offset) [[y (- offset (- x offset))] \X]))

(defn fold-x [grid offset]
  (into {} (map (fn [[[y x] _]] (cond (= y offset) nil
                                      (< y offset) [[y x] \X]
                                      (> y offset) [[(- offset (- y offset)) x] \X]))

(defn fold [grid [axis offset]]
  (if (= axis :x)
    (fold-x grid offset)
    (fold-y grid offset)))

(defn soln-1 [filename]
  (let [[grid folds] (input-data filename)]
    (count (fold grid (first folds)))))

;; part 2

(defn dump-grid [grid]
  (let [[max-y max-x] (reduce (fn [[my mx] [[y x] _]]
                                [(max my y) (max mx x)])
                              [0 0]
    (doseq [x (range (inc max-x))]
      (doseq [y (range (inc max-y))]
        (print (get grid [y x] \.)))
      (print "\n"))))

(defn soln-2 [filename]
  (let [[grid folds] (input-data filename)
        text (reduce (fn [g move] (fold g move)) grid folds)]
    (dump-grid text)
    (count text)))

Antonio Bibiano09:12:51

I'm happy about my folding 🙂 not as much about my rendering :D


@U076FM90B I also enjoyed your solution, nice trick to avoid any if’s


parsing and drawing could be more concise but I'm fine with the folding in one line of specter

👍 1

Nothing new to offer really, I originally did a map, but copied @U44SHEP4N’s specter since I’m a fan.


Bleh, not super happy with it. But it does work fine. On reflection, I made life difficult for myself by making the calculation for the post-fold coordinates based on the size of the paper, which meant I had to keep track of the size of the paper (since you can't determine it from the coordinates alone, though I didn't realize that at first)


In fact, I just refactored that out, now it's much nicer 🙂 thanks @U1EP3BZ3Q

bananadance 1

@U1Z392WMQ you don't actually need the turn the transform result into a set. As long as the initial input is already a set. specter will keep types.

Sam Adams15:12:54

I liked this one too; printing the letters was very satisfying.

karol19:12:49 day13 solution judging from if you want to avoid if... message identical to others 😄 Just printing the board for part2 and reading it manually felt like kind of cheating but I guess that is what most of the people did 😄


in years past i considered doing an “OCR” on the text by comparing to a fingerprint, but he changes the letter size and font often so it’s not worth it.

Antonio Bibiano20:12:49

Maybe one can generate an image and send it off to an OCR api :D


Pretty easy one today

(ns stuartstein777.2021.day13
  (:require [stuartstein777.file :as f]
            [stuartstein777.utils :as u]
            [clojure.string :as str]
            [clojure.set :as set]))

(defn parse-coord [line]
  (->> (str/split line #",")
       (map #(Integer/parseInt %))))

(defn parse-folds [line]
  (let [[xy n] (u/frest (re-seq #"fold along (x|y)=(\d+)" line))]
    [xy (Integer/parseInt n)]))

(defn folder [xy n [x y]]
  (cond (and (= xy "x") (> x n))
        [(- n (Math/abs (- n x))) y]

        (and (= xy "y") (> y n))
        [x (- n (Math/abs (- n y)))]
        [x y]))

(defn row->str [max-x row]
  (let [xs (set (map first row))]
     (map (fn [n] (if (xs n) "⭐" "⬛")) (range (inc max-x)))))

(defn print [coords]
  (let [max-x (apply max (map first coords))]
    (->> coords
         (group-by #(second %))
         (sort-by key)
         (map (partial row->str max-x))
         (map (partial apply str))
         (str/join "\n")

(defn fold [coords [xy n]]
  (map (partial folder xy n) coords))

(let [input (->> (slurp "puzzle-inputs/2021/day13")
      coords (->> input
                  (take-while #(not= "" %))
                  (map parse-coord))
      folds (->> input
                 (drop (inc (count coords)))
                 (map parse-folds)
                 #_(take 1))] ; uncomment to solve part 1
  (->> (reduce fold coords folds)
       #_count ; uncomment to solve part 1

mario-star 3

Oh, i see from @U1EP3BZ3Q, I don't actually need the ((and (= xy "x") (> x n)) statements inside my cond in folder! Nice

bananadance 1

I just need the (= xy "x") and (= xy "y")

Andrew Byala02:12:02

Great solution, @U89SBUQ4T. I enjoyed both how you parsed your data with partition and especially with re-seq, without splitting the lines. For the fold function, your fold' made the map really clear. Thanks - I learned a lot from your tiny bit of code!

kevinc02:12:10 I was inspired by one of yesterday's posts to compose all the folds into one, though I didn't go as far as using a transducer.


Thanks @U01HHBJ56J1, that’s nice to hear! I only picked the partition idea up myself a few days ago from another solution 🙂. Normally I also approach things top-down.


Took me too long to render my result - spoiler in thread


This is what I started with


The console is rotated 90deg? 😄


and mirrored 😄


fold along day=13:christmas_tree:

⤴️ 2
↩️ 3

if you want to avoid if for folding (day13) you can use below formula (spoiler in thread)

👍 4

(- a (m/abs (- v a))) - v - value, a - axis (edited a little bit)