Fork me on GitHub
#adventofcode
<
2022-12-01
>
norman05:12:09

Day 1 - have fun!

😴 2
5
🥴 1
tree-shake 3
🤓 1
alekszelark08:12:30

"\R\R"
❤️

Stuart10:12:32

Day 1 easy as expected.

(defn parse-input []
  (->> (slurp "puzzle-inputs/day1")
       (str/split-lines)
       (map parse-long)
       (partition-by nil?)
       (remove #(= '(nil) %))
       (map #(apply + %))))

;; part 1
(->> (parse-input)
     (apply max))

;; part 2
(->> (parse-input)
     (sort >)
     (take 3)
     (reduce +))

tschady11:12:22

time to update my helpers with parse-long

Martin Půda12:12:07

(ns aoc2022.day01
  (:require [clojure.string :as s])
  (:gen-class))

(defn block->calories [block]
  (transduce (map parse-long) + (s/split-lines block)))

(def data
  (->> (s/split (slurp "resources/input01.txt") #"\n\n")
       (map block->calories)))

(defn part1 [data]
  (reduce max data))

(defn part2 [data]
  (->> data
       (sort >)
       (take 3)
       (reduce +)))

👍 4
Stuart12:12:37

That's neat, splitting on "\n\n" to get rid of havintg to partition by nil or "", then remove them

mkvlr12:12:59

oh I see I missed part 2

nooga12:12:44

This is let-go, not Clojure nor CLJS:

(ns day1)

(defn parse [ls]
   (loop [[l & r] ls sum 0 out []]
     (cond
       (nil? l) out
       (empty? l) (recur r 0 (conj out sum))
       :else (recur r (+ sum (parse-int l)) out))))

(def data (->> "day1.txt" slurp lines parse (sort >)))
(println "1:" (first data))
(println "2:" (->> data (take 3) (apply +))) 

Stuart12:12:53

whats let-go ?

mkvlr12:12:58

@U04V15CAJ thanks TIL about take-nth and sort-by - is prettier than reverse

borkdude12:12:03

@UJEK1RGJ0 if I change parse-int to parse-long and lines to clojure.string/split-lines the code worked in bb too :)

🎉 1
nooga12:12:03

@U04V15CAJ I just literally plopped lines and parse-int into my stdlib so I could solve the AoC 😄 will clean that up some day when it's time to get my APIs closer to the real deal

borkdude12:12:16

@UJEK1RGJ0 maybe you can support reader conditionals, would be fun to compare solutions in different clojure dialects

1
nooga12:12:14

cool idea, I'll look into this over the weekend :D

Stuart13:12:34

Has filterv always been in clojure, or is a recent thing ?

borkdude13:12:18

user=> (:added (meta #'filterv))
"1.4"

Stuart13:12:35

TIL 🙂 Had no idea there as a v version

borkdude13:12:48

There will also be a partitionv in 1.12 :)

1
💯 1
Stuart13:12:05

Is that going to make each bucket a vector too, or more like [(1 2) (3 4)] ?

borkdude13:12:20

@U013YN3T4DA You can try with:

clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.12.0-alpha1"}}}'
and read here: https://clojure.org/news/2022/06/30/clojure1-12-alpha1

👍 1
💯 1
delaguardo16:12:08

(ns aoc2022.day-1
  (:require [aoc2022.misc :as misc]))

(defprotocol Top
  (-push [this] [this x]))

(defrecord TopOne [x]
  Top
  (-push [_] x)
  (-push [this y]
    (if (> y x)
      (new TopOne y)
      this)))

(defrecord TopThree [x y z]
  Top
  (-push [_] (+ x y z))
  (-push [this a]
    (cond
      (> a x)
      (new TopThree a x y)

      (> a y)
      (new TopThree x a y)

      (> a z)
      (new TopThree x y a)

      :else
      this)))

(defn solve-1 []
  (binding [misc/*day* 1]
    (misc/read-lines
     (fn [xs]
       (transduce
        (comp (map parse-long)
              (partition-by nil?)
              (map #(reduce (fnil + 0 0) 0 %)))
        -push
        (new TopOne 0)
        xs)))))

(defn solve-2 []
  (binding [misc/*day* 1]
    (misc/read-lines
     (fn [xs]
       (transduce
        (comp (map parse-long)
              (partition-by nil?)
              (map #(reduce (fnil + 0 0) 0 %)))
        -push
        (new TopThree 0 0 0)
        xs)))))

(comment

  (time
   (dotimes [_ 10000]
     (solve-1)))

  (time
   (dotimes [_ 10000]
     (solve-2)))

  )
day one without using sort 🙂

👏 4
1
😱 1
nooga18:12:20

need to wrap my head around implementing transducers, it would be fun to have them at the bottom, gosh I think I really need a let-go channel

peterh01:12:00

I use the “Advent of Clerk” template and really enjoy trying to figure out a nice experimental, notebook-oriented workflow. I try learning from other solutions posted here and document my insights in “TIL” comments. 🙂 https://github.com/formsandlines/aoc2022-clojure/blob/main/src/advent_of_clerk/day_01.cljc

peterh01:12:58

Btw, since I wanted to run tests from Babashka, I needed to exclude the Clerk import via a reader conditional, because otherwise I cannot run the test command due to an error.

Chase02:12:29

Excited for a new AOC and to learn from all your cool solutions! https://github.com/Chase-Lambert/aoc-clojure/blob/main/src/aoc/2022/day_01.clj

jaihindhreddy04:12:58

Sorting is a lot of unnecessary work considering that we only need top 3, especially for large datasets. Here's something that doesn't do a full-sort, much like @U04V4KLKC did (although his method is even more bespoke):

(defn day1 [fpath]
  (let [xs (str/split (slurp fpath) #"\R\R")
        q (java.util.PriorityQueue. (count xs) (comparator >))
        _ (run! #(->> (re-seq #"\d+" %)
                   (transduce (map parse-long) +)
                   (.add q))
            xs)
        x (.poll q), y (.poll q), z (.poll q)]
    [x (+ x y z)]))
I'd appreciate any feedback 😄.

robertfw07:12:51

after some refactoring I ended up with this as an attempt to do the task in one lazy pass

(ns adventofcode2022.day1
  (:require
   [ :as io]))

(comment
  (with-open [rdr (-> "adventofcode2022/day1.txt" io/resource io/reader)]
    (let [calorie-sums
          (sequence (comp (partition-by #{""})
                          (remove #{'("")})
                          (map #(map parse-long %))
                          (map #(reduce + %)))
                    (line-seq rdr))

          top-three
          (reduce (fn [acc x]
                    (if (< (first acc) x)
                      (sort (conj (rest acc) x))
                      acc))
                  '(0 0 0)
                  calorie-sums)]
      {:part1 (last top-three)
       :part2 (reduce + top-three)}))
  ;; => {:part1 69310, :part2 206104}
  )

dogenpunk20:12:32

Just realized people are posting these every day. Here’s my day 1: https://github.com/dogenpunk/advent-of-code/blob/main/src/aoc22/day01.cljc

😄 1
mbjarland18:12:06

(ns day-01
  (:require [clojure.string :as str]))

(defn input []
  (for [elf (str/split (slurp "../day_01.data") #"\n\n")]
   (reduce + (map parse-long (re-seq #"\d+" elf)))))

(defn solution-1 []
  (apply max (input)))

(defn solution-2 []
  (reduce + (take-last 3 (sort (input)))))

mkvlr12:12:16

sorry, didn’t know & move it there

tschady12:12:09

> A group of a thousand elves on an expedition carrying backpacks filled to the brim --v 4 > By MidJourney > https://www.reddit.com/r/adventofcode/comments/z9g0i0/ai_imagine_advent_of_code_2022_day_1/

😄 11
borkdude12:12:22

I created a repository to help with doing Advent of Code in #babashka and #nbb! https://github.com/borkdude/advent-of-babashka-template Spoiler alert: it contains a solution for day 1.

elken12:12:50

I did something similar that also pulls the input file too. All you need is to curl the URL and pass the cookie in a header https://github.com/elken/aoc (contains solutions so spoiler alert)

borkdude12:12:38

oh, we can update this repo to do that

borkdude12:12:59

with bb new-day --token ....

elken12:12:31

Nice, yeah I will when I'm off the train 😁

genmeblog13:12:14

Just a reminder: there exists #CLX41ASCS script made by @tws which produces such nice badges:

🤯 3
borkdude14:12:12

Oh, it would be nice to have a PR with a link to this in the repo I just created...

borkdude14:12:21

or maybe integrate it in that repo

👍 1
tschady15:12:26

now you’re going to force me to clean that up crying-laughing-joy-blood

tschady15:12:42

I execute with bb badges

{:paths ["resources" "script"]
 :tasks {badges   {:doc  "Updates README badges with latest puzzle completion stats."
                   :task (shell "bb script/update_badges.clj")}

borkdude15:12:31

Cool :) You can also do (load-file "script/...")

genmeblog15:12:43

Don't forget that you have to download session cookie manually to use this script.

tschady15:12:41

and get the favicon locally

borkdude15:12:27

Maybe someone can make this a proper library so it can be used in bb.edn

tschady15:12:19

it’s on my list, along with downloading input: https://github.com/tschady/advent-of-code/blob/main/script/download_input.clj This was just for my use, i didn’t librify it yet.

tschady15:12:35

bb dl 2022 1

borkdude15:12:36

yeah, no obligations of course, just would be nice to have for people :)

Alex Alemi06:12:08

Great script! Eric has requested that we all put a "User-Agent" field into our requests from scripts. I've modified your script to do that here: https://github.com/alexalemi/advent/blob/main/scripts/badges.clj#L32

Alex Alemi06:12:27

where I try to be nice and ensure that I don't make more than one request by checking to ensure that it is the proper time and not requesting the input once I've already gotten it. In this way shortly before midnight I can just run watch bb fetch (I set up a bb task) and it'll only make one request to the page and grab the input while I'm reading the problem

Apple15:12:16

how do you make this nicer

(->> x
             (map #(map parse-long %))
             (map #(reduce + %))
the two maps can you combine them?

Apple15:12:00

(let [x (->> (slurp "src/y2022/input202201")
             (re-seq #"\d+|\n\n")
             (partition-by #{"\n\n"})
             (remove #{["\n\n"]})
             (map #(map parse-long %))
             (map #(reduce + %))
             sort
             reverse
             (take 3))]
  [(first x) (reduce + x)])
my solution for day1

borkdude16:12:21

you can use transducers for to speed things up

borkdude16:12:38

but in this case it's not important, but it is a way to fold those maps

borkdude16:12:57

fwiw, I haven't used it in my solution

elken16:12:46

I've tried to force myself to use transducers more this year as a learning exercise, but I already failed lol Edit: found a way https://github.com/elken/aoc/blob/master/src/solutions/2022/day01.clj

Ben Lieberman16:12:45

I was just about to give clojure.walk/walk a try for this, not sure if it will work. TBD

norman16:12:34

To me, for cries out as the most idiomatic way to express this, and for just two operations I might not bother threading:

(for [group x]
  (reduce + (map parse-long group)))

norman16:12:34

Or with the threading

(for [group x]
  (->> group
       (map parse-long)
       (reduce +)))

alekszelark18:12:16

(defn parse-input [input]
  (map (fn [xs]
         (->> (re-seq #"\d+" xs)
              (transduce (map parse-long) +)))
       (str/split input #"\R\R")))

3
mbjarland18:12:54

yes, what @U067R559Q said, this was mine:

(ns day-01
  (:require [clojure.string :as str]))

(defn input []
  (for [elf (str/split (slurp "../day_01.data") #"\n\n")]
   (reduce + (map #(Integer/parseInt %) (re-seq #"\d+" elf)))))

(defn solution-1 []
  (apply max (input)))

(defn solution-2 []
  (reduce + (take-last 3 (sort (input)))))