Fork me on GitHub

If you all haven’t seen this, it’s really worth looking at. It demonstrates the interaction with chatGPT to solve advent problems. via @cfleming

😬 2
metal 2
Mario Trost07:12:06

Thanks for sharing! The day 4 prompt is revelatory: > Write instructions for the following challenge in such a way that a large language model like yourself can take those instructions and produce a program that creates the right output when run. The program needs to read from a file called input.txt Reminds me of starting to code straight from a business request vs. doing a planning session first and getting requirements straight.


Day 6 - Solutions


;; 202206
(let [d (slurp "resources/202206")
      f #(->> (partition % 1 d)
              (keep-indexed (fn [i x]
                              (if (= % (count (set x)))
                                (+ % i))))
  (map f [4 14]))
;; (1850 2823)

👏 4
🙌 4

;; Part 1
(defn sop [n s]
  (let [cs (partition-all n 1 s)
        mk (apply str (first (filter #(= % (distinct %)) cs)))]
    (+ n (str/index-of s mk))))

(sop 4 input) ;; 1343

;; Part 2
(sop 14 input) ;; 2193


Keeping with the advent-of-transducers theme

Ben Lieberman07:12:46

this regrettably only got me the first part but gonna keep working with it

(def input (-> "public/puzzle_inputs/day_six.txt" io/resource slurp))

(defn process-data [n s]
  (let [packets (map #(apply str %) (partition n 1 s))
        unique-packets (map (comp #(apply str %) distinct) packets)
        nums (filter some? (map #(if (= %1 %2) %3 nil)
                   packets unique-packets (range)))]
    (first (drop n nums))))


I think changing your last line to (+ (first nums) n) should do it

👀 1

(defn solve [input nb]
  (reduce (fn [acc item]
            (if (= (count item) nb)
              (reduced (+ acc nb))
              (inc acc)))
          (map set (partition nb 1 input))))

(defn part1 [input]
  (solve input 4))

(defn part2 [input]
  (solve input 14))

👏 3

(defn marker-id
  [data marker-length]
  (->> (partition marker-length 1 data)
       (map (comp count set))
       (map-indexed vector)
       (sort-by second >)
       (reduce +)))

Piotr Kaznowski09:12:10

(defn solve [it len]
  (let [f (fn [ii] ((juxt #(take len %) #(drop 1 %)) ii))]
    (loop [[a b] (f it), pos len]
      (if (= len (count (set a))) pos
          (recur (f b) (inc pos))))))

(defn -main [day]
  (let [input (file->str day)
        result (partial solve input)]
    (zipmap [:part1 :part2] (map result [4 14]))))

Valentin Mouret09:12:57

It’s so nice to learn about all these functions from your examples (`distinct?`, take-while, keep-indexed…). In, I used reduce and reduced and I don’t think I have seen it so far.

👍 1

Variations on above. This was the first day I used my bb submit to send in the answers. Next up, submit direct from emacs cider

👏 2

I am happy that today my solution is almost the same as @U1Z392WMQ

🤪 1

Maybe I missed something, but why in Clojure there's no queue function to create a queue?


Mine: > (defn day-06 [input n] > (loop [seen (apply conj (clojure.lang.PersistentQueue/EMPTY) (take n input)) i n] > (if (= (count (set seen)) n) > i > (recur (conj (pop seen) (get input i)) (inc i))))) > > (defn day-06-1 [input] > (day-06 input 4)) > > (defn day-06-2 [input] > (day-06 input 14))


You have PersistentQueue


but I guess you can mimic simple queues with vectors


I couldn't resist not using juxt 😂:

(defn day6 [fs]
  ((juxt #(% 4) #(% 14))
   (fn [k]
     (->> (partition k 1 fs)
         #(when (apply distinct? %2)
            (+ % k)))

😁 1

I've been using AoC as an opportunity to finally learn how to use transducers. For example my solution for day 6.

👍 1
Alexis Schad13:12:47

(->> (slurp "day6.txt")
     (partition 14 1)
     (map (comp count set))
     (#(.indexOf % 14))
     (+ 14))

👍 4

(ns day6)

(def data (slurp "input/day6.txt"))

(defn solve [n]
  (->> data (partition n 1) (map (comp #{n} count set)) (take-while not) count (+ n)))

(println "1:" (solve 4))
(println "2:" (solve 14))
helped me to fix my comp implementation 🙂

CarnunMP14:12:55, eh? the essence of it:

(defn find-marker [n input]
  (->> (partition n 1 input)
       (keep-indexed #(when (apply distinct? %2) %1))
       (+ n)))


I think this just means tomorrow will be brutal :)

😯 2

indeed... has felt like the calm before the storm for a while now


first week is always kinda like this and then it turns into a full time job

😄 4
😆 1

What I spent 5 minutes debugging last night... Zipmap maps aren't ordered.

day06.main> (for [[n] (zipmap (range) "abcdedghijklmn")] n)
(0 7 1 4 13 6 3 12 2 11 9 5 10 8)
day06.main> (for [[n] (map-indexed vector "abcdefghijklmn")] n)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13)
keep-indexed wasn't really in my vocabulary, but now that I see those solutions, I will definitely start using it ore


@UJEK1RGJ0 yeah the perf of let-go is going to definitely get tested for sure


bring it on I say

😂 1

Danggit! I always forget partition can take a size argument…

Luis Santos18:12:11

(defn sliding-window [seq length]
  (loop [result ()
         remaining seq]
    (let [chunk (take length remaining)]
      (if (< (count chunk) length)
        (reverse result)
        (recur (cons chunk result) (rest remaining))))))

(->> (sliding-window (slurp "input/day-6-input.txt") 14)
     (reduce (fn [acc n]
               (if (= (count (set n)) 14)
                 (reduced (+ acc (count n)))
                 (inc acc )))
I wont forget that partition trick. 😄

Michael Ducharm18:12:30

I was looking for an equivalent of rust's windows function, and learned that partition could do that. Very handy!


I went with a queue for this one but loving the succinct partition answer!

(defn find-marker [stream marker-len]
  (reduce-kv (fn [acc k v]
                 (< (count acc) marker-len) (conj acc v)
                 (= marker-len (count (into #{} acc))) (reduced k)
                 :else (conj (pop acc) v)))
             (into [] stream)))


(defn partition-till-detected [n s]
  (take-while (complement (partial apply distinct?))
              (partition n 1 s)))

(defn count-to-marker [n s]
  (+ n (count (partition-till-detected n s))))

(count-to-marker 4 input)  ;; part 1
(count-to-marker 14 input) ;; part 2


(ns aoc2022.day6
  (:require [ :refer [resource]]
            [clojure.string :as str]
            [clojure.set :refer [intersection]]))

(defn data []
  (->> (resource "inputs/day6.txt")

(defn solution [s len]
  (let [start-3 (into [] (take len s))
        except-start-3 (into [] (drop len s))]
    (+ len
       (reduce (fn [[l idx] e]
                 (tap> [l idx])
                 (if (apply distinct? (conj l e))
                   (reduced idx)
                   [(conj (subvec l 1) e) (inc idx)]))
               [(into [] start-3) 1]

(def part1 #(solution % 3))
(def part2 #(solution % 13))


If someone would like the horrible experience of using JavaScript instead of Clojure... 😃 At least it supports reloading of JavaScripts code. Any ideas of how to integrate ChatGPT in a cool way would be awesome. Please 🧵 . I asked ChatGPT about integrating with its API and it seems pretty straight forward, especially since it gave me the code for it.

Petrus Theron10:12:33

Sup Clojurians. Here are my 2022 Advent of Code solutions in Clojure:

👋 1
clojure-spin 2

PSA for those new to some of the core functions people use in these solutions: Study the . e.g. Have a sequence, and want to get some things from the front? go to “Seq In, Seq Out” -> “Head Items” and checkout the list: take take-while butlast drop-last for.

❤️ 2
👍 2
☝️ 1

I totally forgot about distinct? and really miss basic factory function for queue (sth like (def queue [coll]... (clojure.lang.PersistentQueue ...)


me too! distinct? and keep-indexed this time (`re-seq` yesterday)


every day something new 🙂

👍 1

Kind of a meta-point: over time I've come up with a bit of to tackle each day's puzzle, and I like it so much that this year I wrote a little to generate each day's new one. It's not much boilerplate, but it takes care of the little bit of file I/O fiddliness and my experience becomes, I just hop into the REPL and start hacking first using the puzzle's hardcoded sample data, and then more often than not it works on the first try with my personalized input (which I have to copy into the resource file). So for example day 5 looks like this at the start:

(ns aoc-2022.day5
   [ :as io]))

(defn runner
  "runner docstring"


  (runner ["    [D]"    
           "[N] [C]"    
           "[Z] [M] [P]"
           " 1   2   3" 
           "move 1 from 2 to 1"
           "move 3 from 1 to 3"
           "move 2 from 2 to 1"
           "move 1 from 1 to 2"])

  (with-open [r (io/reader (io/resource "aoc-2022/day5.txt"))]
    (runner (line-seq r)))


👀 1
🙏 1

I have a bb script to create a new day from a template with all my clerk boilerplate

winning 1

Neat! I started building something that parses the html to markdown and pastes that into clerk, but I might just steal your idea of using hickory and using the clerk/html viewer. The downside is that the prose is not visible in the editor, but the upside is that the prose is not visible in the editor. :thinking_face:


Yeah I did it manually at first but it's tedious to do and wastes space. You can have the notebook in an xwidgets browser frame of Emacs is compiled with it (which is how I work)


I'm old-fashioned and still use an external browser for my Portal and Clerk. :) I managed to automate the markdown parsing with this: But it's just a hacky POC at the moment and I'm not aware of what the sharp edges are (OTOH the AOC html is relatively straightforward so shouldn't be too many issues going forward). I will play with both approaches when I find some time in the coming days and report back. Thanks for sharing @U043RSZ25HQ!

😄 1

bb has Selmer built-in, might want to check that out. (ns aoc.{{year}}.d{{day}} is convenient.


I’ve seen someone using clojure.lang.PersistentQueue in todays puzzle, so I wondered if this data structure is something that you use frequently in Clojure and if there are any caveats to be aware of (other than from the general properties of queues). I already explored how it behaves with conj, peek and pop, which is as expected from a queue (first-in-first-out). I also see that seq works on queues and so they can be mapped, filtered, etc. and you can use (into clojure.lang.PersistentQueue/EMPTY …) to get a queue from a seq or vector. They also seem to work with Babashka.


Funny you should mention it: earlier this very day, I was mentioning to someone that, although I've been programming Clojure since 2011, until I very recently read chapter 2 of Clojure Applied I did not even know of the existence of clojure.lang.PersistentQueue. 🤷


<sample-of-one>I looked through my past AoC solutions and I’ve used it about once a year on average. In a full stack production app I’ve been working on, haven’t used it at all.</sample-of-one>


anecdotally (looking through my AoC history), I have used it a couple times for path-finding puzzles but it looks like I switched to at some point. I’m not a clojure expert in any way, so I can’t say whether either was the right way to go. (other than they did do the job asked of them)