This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-12-02
Channels
- # adventofcode (97)
- # announcements (11)
- # babashka (18)
- # beginners (34)
- # biff (5)
- # cljfx (5)
- # clojure-europe (4)
- # clojure-uk (2)
- # clojurescript (7)
- # community-development (2)
- # hyperfiddle (8)
- # introduce-yourself (1)
- # music (2)
- # off-topic (2)
- # polylith (3)
- # practicalli (1)
- # releases (1)
- # shadow-cljs (28)
- # squint (1)
One of my usual AOC habits is to explore transducers after I get my quick and dirty answer out there. I'm curious why my regular version is the same speed (if not slightly faster) when benchmarking with criterium than the transducer version. I usually find quite the opposite.
relevant code for Part 1:
(defn part-1 [data]
(->> data
(map #(re-seq #"\d" %))
(map (juxt first last))
(map (comp parse-long (partial apply str)))
(reduce +)))
(defn part-1-transduce [data]
(let [xform (comp
(map #(re-seq #"\d" %))
(map (juxt first last))
(map (comp parse-long (partial apply str))))]
(transduce xform + data)))
https://github.com/wevre/advent-of-code/blob/master/src/advent_of_code/2023/day_02_games.clj
Mine's a little clunky, but gets the job done. https://coyotesqrl.github.io/advent-of-code/2023/src/coyotesqrl/2023/day02/
Happily, my approach for part 1 dovetailed nicely with part 2, didn’t have to re-write anything, and that rarely happens for me with AoC.
https://gist.github.com/jreighley/14ec18793fe5bb9bbdee41493dbe2edd merge-with max came in quite handy.
> merge-with max came in quite handy. this is great, did not know about this! +1
yea, same, i happened to set myself up very nicely for part 2 during part 1. https://github.com/Ramblurr/advent-of-code/blob/main/src/aoc/2023/day02.clj
probably influenced by day 1, but I keep coming back to regex for my solutions: https://github.com/rmrt1n/advent-of-code-2023-clj/blob/main/src/aoc/day02.clj
Had to rewrite parsing logic when part 2 was unveiled, but overall happy how easy today turned out to be https://github.com/skazhy/advent/blob/master/src/advent/2023/day2.clj
Happy with how easy part two was to adapt to :) https://github.com/jantorestolsvik/advent-of-code-2023/blob/main/src/day02.clj
Somehow sorted-map becomes the main data structure so far... https://github.com/caseneuve/aoc2023/blob/master/day02/solution.clj
Bangs head on keyboard, after a non-optimal night of sleep. The test input works for me, but the "production" input gives a too low number
I think I got it, I misinterpreted the puzzle, I summed all the red, green, blue and then compared to the max
I had the same mistake, summed the colors instead of using max
@UTFAPNRPT Love how terse your implementation is! The parsing part certainly took me a while to understand. Also, . Ah, I see that it couldn't, since you keep game id as one of the keys.power
could just be #(apply * (vals %))
I thought I made a mistake earlier by using array indexes as the game id but then I thought: perhaps they use sparse ids, but this wasn't the case in my input
• Sometimes I find spelling out the parser easier to read, though I’m not completely happy with mine it was fast.
• using [r g b]
tuples in a matrix lets you do things like map >=
to check size and makes power just the max of the transpose.
https://github.com/tschady/advent-of-code/blob/main/src/aoc/2023/d02.clj
https://squint-cljs.github.io/squint/?boilerplate=https%3A%2F%2Fgist.githubusercontent.com%2Fborkdude%2Fcf94b492d948f7f418aa81ba54f428ff%2Fraw%2Fa7da6236e9670681a93761b81fd66ad26c119164%2Faoc_ui.cljs&repl=true&src=OzsgSGVscGVyIGZ1bmN0aW9uczoKOzsgKGZldGNoLWlucHV0IHllYXIgZGF5KSAtIGdldCBBT0MgaW5wdXQKOzsgKGFwcGVuZCBzdHIpIC0gYXBwZW5kIHN0ciB0byBET00KOzsgKHNweSB4KSAtIGxvZyB4IHRvIGNvbnNvbGUgYW5kIHJldHVybiB4CgooZGVmIGlucHV0ICgtPiAoanMtYXdhaXQgKGZldGNoLWlucHV0IDIwMjMgMikpCiAgICAgICAgICAgICBzdHIvdHJpbQogICAgICAgICAgICAgc3RyL3NwbGl0LWxpbmVzKSkKCihkZWZuIGdhbWVzIFtzXQogICgtPj4gKC0%2BIHMgKHN0ci9zcGxpdCAjIjoiKSBzZWNvbmQKICAgICAgICAgKHN0ci9yZXBsYWNlICMiKFxkKykgKFx3KykiICJ7XCIkMlwiOiAkMX0iKQogICAgICAgICAoc3RyL3NwbGl0ICMiWyw7XSIpKQogICAgKG1hcCBqcy9KU09OLnBhcnNlKQogICAgKGFwcGx5IG1lcmdlLXdpdGggbWF4KQogICAgKChqdXh0IDpyZWQgOmdyZWVuIDpibHVlKSkpKQoKKGNvbW1lbnQKICAoZ2FtZXMgKGZpcnN0IGlucHV0KSkpCgooZGVmIHAxCiAgKGxldCBbcnVsZXMgKHZhbHMgeyJyZWQiIDEyICJncmVlbiIgMTMgImJsdWUiIDE0fSkKICAgICAgICBwb3NzaWJsZT8gIyhldmVyeT8gdHJ1ZT8gKG1hcCAoZm4gW2EgYl0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8PSBhIGIpKSAlIHJ1bGVzKSldCiAgICAocGFydGlhbCBrZWVwLWluZGV4ZWQKICAgICAgKGZuIFtpZCBnYW1lXSAod2hlbiAocG9zc2libGU%2FIGdhbWUpIChpbmMgaWQpKSkpKSkKCihkZWYgcDIgKHBhcnRpYWwgbWFwICMocmVkdWNlIChmbiBbYSBiXSAoKiBhIGIpKSAlKSkpCgooZGVmbiBzb2x2ZSBbaW5wdXRdCiAgKGxldCBbc29sdmUtd2l0aCAjKC0%2BPiBpbnB1dCAobWFwIGdhbWVzKSAlIChhcHBseSArKSldCiAgICB7OnBhcnQxIChzb2x2ZS13aXRoIHAxKSA6cGFydDIgKHNvbHZlLXdpdGggcDIpfSkpCgooY29tbWVudAogIChzb2x2ZSBpbnB1dCkpCgooY29tbWVudAogIChkZWYgdGVzdC1pbnB1dCAiR2FtZSAxOiAzIGJsdWUsIDQgcmVkOyAxIHJlZCwgMiBncmVlbiwgNiBibHVlOyAyIGdyZWVuCkdhbWUgMjogMSBibHVlLCAyIGdyZWVuOyAzIGdyZWVuLCA0IGJsdWUsIDEgcmVkOyAxIGdyZWVuLCAxIGJsdWUKR2FtZSAzOiA4IGdyZWVuLCA2IGJsdWUsIDIwIHJlZDsgNSBibHVlLCA0IHJlZCwgMTMgZ3JlZW47IDUgZ3JlZW4sIDEgcmVkCkdhbWUgNDogMSBncmVlbiwgMyByZWQsIDYgYmx1ZTsgMyBncmVlbiwgNiByZWQ7IDMgZ3JlZW4sIDE1IGJsdWUsIDE0IHJlZApHYW1lIDU6IDYgcmVkLCAxIGJsdWUsIDMgZ3JlZW47IDIgYmx1ZSwgMSByZWQsIDIgZ3JlZW4iKQogIChkZWYgc29sdmUtd2l0aCAjKC0%2BPiB0ZXN0LWlucHV0CiAgICAgICAgICAgICAgICAgICAgIHN0ci9zcGxpdC1saW5lcwogICAgICAgICAgICAgICAgICAgICAobWFwIGdhbWVzKSAlCiAgICAgICAgICAgICAgICAgICAgIChhcHBseSArKSkpCiAgCiAgKD0gOCAoc29sdmUtd2l0aCBwMSkpCiAgKD0gMjI4NiAoc29sdmUtd2l0aCBwMikpCiAgKQ%3D%3D
The above is @UUAKPEMJ9’s solution. I used JSON/parse
instead of read-string
and there were some issues around *
and <=
not being available as reified functions (https://github.com/squint-cljs/squint/issues/400)
(require '[clojure.string :as str])
(defn parse-count [s]
(let [[cnt color] (str/split s #" ")]
[(keyword color) (parse-long cnt)]))
(defn parse-hand [s]
(->> (str/split s #", ")
(map parse-count)
(into {})))
(defn game-maxes [s]
(let [[game-name-str counts-str] (str/split s #": ")
max-counts (-> counts-str
(str/split #"; ")
(->> (map parse-hand)
(apply merge-with max)))
game-id (-> game-name-str (str/split #" ")
second
parse-long)]
[game-id max-counts]))
(def thresholds {:red 12 :green 13 :blue 14})
(defn game-within-threshold? [[_game-id maxes]]
(->> (merge-with >= thresholds maxes)
vals
(every? true?)))
(defn power-val [[_game-id maxes]]
(->> maxes
vals
(reduce *)))
(def part1-result
(-> (slurp "aoc/input2.txt")
(str/split #"\n")
(->> (map game-maxes)
(filter game-within-threshold?)
(map first)
(reduce +))))
(def part2-result
(-> (slurp "aoc/input2.txt")
(str/split #"\n")
(->> (map game-maxes)
(map power-val)
(reduce +))))
less to get snagged on than with Day 1 🙂
(defn possible? [game]
(let [c->max {"red" 12, "green" 13, "blue" 14}]
;; for every selection in this game...
(every? #(every? (fn [c] ; ... every color <= max (or absent)
(<= (get % c 0) (get c->max c)))
(keys c->max))
(:cubes game))))
;; part 2
(defn min-cubes [game]
;; reduce over all 'cubes' (selections of cubes) in this game...
(reduce (fn [m cube]
(->> m
;; ... to produce a map of min required for each color
(map (fn [[c n]] [c (max n (get cube c 0))]))
(into {})))
{"red" 0
"green" 0
"blue" 0}
(:cubes game)))
(defn solve [input & {:keys [part]}]
(->> (parse input)
(keep (fn [game]
(case part
1 (when (possible? game)
(:id game))
2 (->> (min-cubes game)
(vals)
(apply *)))))
(apply +)))
https://github.com/CarnunMP/Advent-of-Code/blob/master/src/y2023/d2.clj
(if this trend continues...??)@UE7LPTG1L https://squint-cljs.github.io/squint/?boilerplate=https%3A%2F%2Fgist.githubusercontent.com%2Fborkdude%2Fcf94b492d948f7f418aa81ba54f428ff%2Fraw%2Fa7da6236e9670681a93761b81fd66ad26c119164%2Faoc_ui.cljs&repl=true&src=OzsgSGVscGVyIGZ1bmN0aW9uczoKOzsgKGZldGNoLWlucHV0IHllYXIgZGF5KSAtIGdldCBBT0MgaW5wdXQKOzsgKGFwcGVuZCBzdHIpIC0gYXBwZW5kIHN0ciB0byBET00KOzsgKHNweSB4KSAtIGxvZyB4IHRvIGNvbnNvbGUgYW5kIHJldHVybiB4CgoocmVxdWlyZSAnW2Nsb2p1cmUuc3RyaW5nIDphcyBzdHJdKQoKKGRlZm4gcGFyc2UtY291bnQgW3NdCiAgKGxldCBbW2NudCBjb2xvcl0gKHN0ci9zcGxpdCBzICMiICIpXQogICAgWygjPyg6c3F1aW50IGlkZW50aXR5IDpkZWZhdWx0IGtleXdvcmQpIGNvbG9yKSAocGFyc2UtbG9uZyBjbnQpXSkpCgooY29tbWVudAogIChwYXJzZS1jb3VudCAiMSBncmVlbiIpKQoKKGRlZm4gcGFyc2UtaGFuZCBbc10KICAoLT4%2BIChzdHIvc3BsaXQgcyAjIiwgIikKICAgIChtYXAgcGFyc2UtY291bnQpCiAgICAoaW50byB7fSkpKQoKKGNvbW1lbnQKICAocGFyc2UtaGFuZCAiMSBncmVlbiwgMiBibHVlIikpCgooZGVmbiBnYW1lLW1heGVzIFtzXQogIChsZXQgW1tnYW1lLW5hbWUtc3RyIGNvdW50cy1zdHJdIChzdHIvc3BsaXQgcyAjIjogIikKICAgICAgICBtYXgtY291bnRzICgtPiBjb3VudHMtc3RyCiAgICAgICAgICAgICAgICAgICAgIChzdHIvc3BsaXQgIyI7ICIpCiAgICAgICAgICAgICAgICAgICAgICgtPj4gKG1hcCBwYXJzZS1oYW5kKQogICAgICAgICAgICAgICAgICAgICAgIChhcHBseSBtZXJnZS13aXRoIG1heCkpKQogICAgICAgIGdhbWUtaWQgKC0%2BIGdhbWUtbmFtZS1zdHIgKHN0ci9zcGxpdCAjIiAiKQogICAgICAgICAgICAgICAgICBzZWNvbmQKICAgICAgICAgICAgICAgICAgcGFyc2UtbG9uZyldCiAgICBbZ2FtZS1pZCBtYXgtY291bnRzXSkpCgooY29tbWVudAogIChnYW1lLW1heGVzICJHYW1lIDE6IDEgZ3JlZW4sIDIgYmx1ZTsgMiBncmVlbiwgMSByZWQiKSkKCihkZWYgdGhyZXNob2xkcyB7OnJlZCAxMiA6Z3JlZW4gMTMgOmJsdWUgMTR9KQoKKGRlZm4gZ2FtZS13aXRoaW4tdGhyZXNob2xkPyBbW19nYW1lLWlkIG1heGVzXV0KICAoLT4%2BIChtZXJnZS13aXRoICMoPj0gJTEgJTIpIHRocmVzaG9sZHMgbWF4ZXMpCiAgICB2YWxzCiAgICAoZXZlcnk%2FIHRydWU%2FKSkpCgooY29tbWVudAogIChnYW1lLXdpdGhpbi10aHJlc2hvbGQ%2FIChnYW1lLW1heGVzICJHYW1lIDE6IDEgZ3JlZW4sIDIgYmx1ZTsgMiBncmVlbiwgMSByZWQiKSkKICApCgooZGVmbiBwb3dlci12YWwgW1tfZ2FtZS1pZCBtYXhlc11dCiAgKC0%2BPiBtYXhlcwogICAgdmFscwogICAgKHJlZHVjZSAjKCogJTEgJTIpKSkpCgooY29tbWVudAogIChwb3dlci12YWwgKGdhbWUtbWF4ZXMgIkdhbWUgMTogMSBncmVlbiwgMiBibHVlOyAyIGdyZWVuLCAxIHJlZCIpKQogICkKCihkZWYgcGFydDEtcmVzdWx0CiAgKC0%2BIChqcy1hd2FpdCAoZmV0Y2gtaW5wdXQgMjAyMyAyKSkKICAgIHN0ci90cmltCiAgICAoc3RyL3NwbGl0ICMiXG4iKQogICAgKC0%2BPiAobWFwdiBnYW1lLW1heGVzKQogICAgICAoZmlsdGVyIGdhbWUtd2l0aGluLXRocmVzaG9sZD8pCiAgICAgIChtYXAgZmlyc3QpCiAgICAgIChyZWR1Y2UgKykpKSkKCihkZWYgcGFydDItcmVzdWx0CiAgKC0%2BIChqcy1hd2FpdCAoZmV0Y2gtaW5wdXQgMjAyMyAyKSkKICAgIHN0ci90cmltCiAgICAoc3RyL3NwbGl0ICMiXG4iKQogICAgKC0%2BPiAobWFwIGdhbWUtbWF4ZXMpCiAgICAgIChtYXAgcG93ZXItdmFsKQogICAgICAocmVkdWNlICspKSkp
I needed to insert str/trim
to get rid of the newline in the input, I wonder why that wasn't a problem in your case
ah because it's a difference in squint: user=> (str/split "foo\nbar\n" #"\n") ;;=> [ 'foo', 'bar', '' ]
that was relaxing compared to yesterday https://github.com/FelipeCortez/advent-of-code/blob/master/2023/02.clj
@UUAKPEMJ9 good idea using sorted-map
Fixed issues in squint, *
and >=
etc can now be used as higher order functions and str/split
elides empty splitted elements (when limit = nil), like in CLJS
Again @UE7LPTG1L’s https://squint-cljs.github.io/squint/?boilerplate=https%3A%2F%2Fgist.githubusercontent.com%2Fborkdude%2Fcf94b492d948f7f418aa81ba54f428ff%2Fraw%2Fa7da6236e9670681a93761b81fd66ad26c119164%2Faoc_ui.cljs&repl=true&src=OzsgSGVscGVyIGZ1bmN0aW9uczoKOzsgKGZldGNoLWlucHV0IHllYXIgZGF5KSAtIGdldCBBT0MgaW5wdXQKOzsgKGFwcGVuZCBzdHIpIC0gYXBwZW5kIHN0ciB0byBET00KOzsgKHNweSB4KSAtIGxvZyB4IHRvIGNvbnNvbGUgYW5kIHJldHVybiB4CgoocmVxdWlyZSAnW2Nsb2p1cmUuc3RyaW5nIDphcyBzdHJdKQoKKGRlZm4gcGFyc2UtY291bnQgW3NdCiAgKGxldCBbW2NudCBjb2xvcl0gKHN0ci9zcGxpdCBzICMiICIpXQogICAgWygjPyg6c3F1aW50IGlkZW50aXR5IDpkZWZhdWx0IGtleXdvcmQpIGNvbG9yKSAocGFyc2UtbG9uZyBjbnQpXSkpCgooY29tbWVudAogIChwYXJzZS1jb3VudCAiMSBncmVlbiIpKQoKKGRlZm4gcGFyc2UtaGFuZCBbc10KICAoLT4%2BIChzdHIvc3BsaXQgcyAjIiwgIikKICAgIChtYXAgcGFyc2UtY291bnQpCiAgICAoaW50byB7fSkpKQoKKGNvbW1lbnQKICAocGFyc2UtaGFuZCAiMSBncmVlbiwgMiBibHVlIikpCgooZGVmbiBnYW1lLW1heGVzIFtzXQogIChsZXQgW1tnYW1lLW5hbWUtc3RyIGNvdW50cy1zdHJdIChzdHIvc3BsaXQgcyAjIjogIikKICAgICAgICBtYXgtY291bnRzICgtPiBjb3VudHMtc3RyCiAgICAgICAgICAgICAgICAgICAgIChzdHIvc3BsaXQgIyI7ICIpCiAgICAgICAgICAgICAgICAgICAgICgtPj4gKG1hcCBwYXJzZS1oYW5kKQogICAgICAgICAgICAgICAgICAgICAgIChhcHBseSBtZXJnZS13aXRoIG1heCkpKQogICAgICAgIGdhbWUtaWQgKC0%2BIGdhbWUtbmFtZS1zdHIgKHN0ci9zcGxpdCAjIiAiKQogICAgICAgICAgICAgICAgICBzZWNvbmQKICAgICAgICAgICAgICAgICAgcGFyc2UtbG9uZyldCiAgICBbZ2FtZS1pZCBtYXgtY291bnRzXSkpCgooY29tbWVudAogIChnYW1lLW1heGVzICJHYW1lIDE6IDEgZ3JlZW4sIDIgYmx1ZTsgMiBncmVlbiwgMSByZWQiKSkKCihkZWYgdGhyZXNob2xkcyB7OnJlZCAxMiA6Z3JlZW4gMTMgOmJsdWUgMTR9KQoKKGRlZm4gZ2FtZS13aXRoaW4tdGhyZXNob2xkPyBbW19nYW1lLWlkIG1heGVzXV0KICAoLT4%2BIChtZXJnZS13aXRoID49IHRocmVzaG9sZHMgbWF4ZXMpCiAgICB2YWxzCiAgICAoZXZlcnk%2FIHRydWU%2FKSkpCgooY29tbWVudAogIChnYW1lLXdpdGhpbi10aHJlc2hvbGQ%2FIChnYW1lLW1heGVzICJHYW1lIDE6IDEgZ3JlZW4sIDIgYmx1ZTsgMiBncmVlbiwgMSByZWQiKSkKICApCgooZGVmbiBwb3dlci12YWwgW1tfZ2FtZS1pZCBtYXhlc11dCiAgKC0%2BPiBtYXhlcwogICAgdmFscwogICAgKHJlZHVjZSAqKSkpCgooY29tbWVudAogIChwb3dlci12YWwgKGdhbWUtbWF4ZXMgIkdhbWUgMTogMSBncmVlbiwgMiBibHVlOyAyIGdyZWVuLCAxIHJlZCIpKQogICkKCihkZWYgcGFydDEtcmVzdWx0CiAgKC0%2BIChqcy1hd2FpdCAoZmV0Y2gtaW5wdXQgMjAyMyAyKSkKICAgIChzdHIvc3BsaXQgIyJcbiIpCiAgICAoLT4%2BIChtYXB2IGdhbWUtbWF4ZXMpCiAgICAgIChmaWx0ZXIgZ2FtZS13aXRoaW4tdGhyZXNob2xkPykKICAgICAgKG1hcCBmaXJzdCkKICAgICAgKHJlZHVjZSArKSkpKQoKKGRlZiBwYXJ0Mi1yZXN1bHQKICAoLT4gKGpzLWF3YWl0IChmZXRjaC1pbnB1dCAyMDIzIDIpKQogICAgKHN0ci9zcGxpdCAjIlxuIikKICAgICgtPj4gKG1hcCBnYW1lLW1heGVzKQogICAgICAobWFwIHBvd2VyLXZhbCkKICAgICAgKHJlZHVjZSArKSkpKQ%3D%3D but essentially the same now except reading the input of course
Nice to put runnable comments for the intermediary steps like this
lol I'm glad ya'll figured out the summing/maxing thing. I was pretty sure I was misinterpreting, but I wasn't' at all sure how.
Fortunately clojure is amazing. (apply merge-with + coll)
became (apply merge-with max picks)
re having to rewrite parsing: I've found that lossless parsing really pays off in AoC (and in every day programming as well!)
What do you mean, @U07S8JGF7, by lossless parsing?
so, e.g. instead of grabbing the min values from each line, have a parsing phase that grabs all the values
I took a gamble and did not do lossless parsing. I think I picked up that trick from @U067R559Q a couple years ago. It paid off this time. I did not keep track of individual sets within each game (which is more effort because the number of sets per game is not fixed), ignored commas and semicolons and just reduced with max. I guess it was lucky that approach worked for both part 1 and part 2. (I had guessed that part 2 would involve some change to the limits, so when it was revealed it was too easy.)
@UA2U3KW0L yeah, I refactored when the 2nd part was revealed, as it became obvious that only edge cases are important and colors are only needed as "indexes" for unifying data as no further look-ups will follow; then I refactored a bit further, so the solution algorithms accept only vals
, not maps.
It went quite well today : https://github.com/arnaudgeiser/advent-of-code/blob/master/2023/clojure/src/advent_of_code/day2.clj
https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2023/day02.clj
https://github.com/chase-lambert/aoc-clojure/blob/main/src/aoc/2023/day_02.clj Another hacky one for me, I'm excited to check out these more elegant solutions from you folks now
folks seem reluctant to tackle part 2 so far but I didn't find it that much more difficult than part 1. Could just be early though
oh man, some of the solutions are so sweet! I feel like my imposter syndrome needs a disclaimer if you spent a good amount of time refactoring to look so nice before posting or is this just naturally how you code off the bat
I would love and "honour-mode" where you get to submit only one solution without running it and you get the star if it passes first time. No repl cheating
Haha likewise
Day 2 seems to be very easy compare to Day 1 (especially part 2). Did a Live Coding used Hyperfiddle for TDD and its available on https://www.youtube.com/watch?v=aF4OfRGnobk . https://github.com/muthuishere/advent-of-code-clojure-2023/blob/main/src/day2.clj
Do you mind deleting this comment? By all means send your live coding to the main channel but don’t put solutions into the channel
I enjoyed day 2.
Just parsing colour and count in part 1 turned out to be helpful for the second part.
Though reading this thread it would have been nice to know about merge-with
https://github.com/JDurstberger/aoc-2023-clj/tree/main/src/day_2
Here is today's video
https://youtu.be/Whff9f_BrL8
(And could you please delete the link preview as well? It’s an awesome share just don’t want spoilers leaking out) edit: link previews are fine here in the thread, just don’t want code solutions in the main channel for people who are still solving them)
https://github.com/ChrisBlom/advent-of-code/blob/master/src/adventofcode/2023/day02.clj
my day 2 in squint -- didn't use the playground this time due to time constraints (I ended up spending more time working on the playground than doing the actual problems): https://gist.github.com/corasaurus-hex/e800b30d092db6efaaa182aa51d57431
Decided to go for TDD, because parsing input always gets trickier than I think it will. 😃
(ns day02
(:require [ :as io]
[clojure.string :as string]))
(defn parse-subset [subset]
(let [[[_ r]] (re-seq #"(\d+) red" subset)
[[_ g]] (re-seq #"(\d+) green" subset)
[[_ b]] (re-seq #"(\d+) blue" subset)]
[(or (some-> r parse-long) 0)
(or (some-> g parse-long) 0)
(or (some-> b parse-long) 0)]))
(defn parse [line]
(let [[_ subsets] (string/split line #":")]
(->> (string/split subsets #";")
(map parse-subset))))
(defn part01 [lines]
(->> lines
(map parse)
(map-indexed
(fn [idx subsets]
[(+ idx 1)
(->> subsets
(map (fn [[r g b]] (and (<= r 12) (<= g 13) (<= b 14))))
(flatten)
(every? identity))]))
(filter (fn [[_ p]] p))
(map first)
(reduce +)))
(defn part02 [lines]
(->> lines
(map parse)
(map
(fn [subsets]
(->> subsets
(reduce (fn [[ar ag ab] [r g b]]
[(max ar r) (max ag g) (max ab b)])
[0 0 0])
(reduce *))))
(reduce +)))
(comment
(with-open [r (io/reader "day02.txt")]
(part01 (line-seq r)))
(with-open [r (io/reader "day02.txt")]
(part02 (line-seq r))))
Wanted to make a poll asking people about their approach to AoC questions. Is this not possible in slack without a plugin?
I guess not. I often do things like: How do you do X? • 1️⃣ foo • 2️⃣ bar • 3️⃣ baz and get people to use the emoji reactions 1️⃣ , 2️⃣ , or 3️⃣ and discuss in a thread
Ah yeah that works
How do you think about performance in your AoC solutions: 1️⃣ Not at all 2️⃣ It's lower priority than some other style / readability considerations 3️⃣ It's an important aspect of my solution - I optimize it intuitively 4️⃣ It's an important aspect of my solution - I measure it 5️⃣ Something else
As long as it runs in tens of seconds at most, I'm happy 😄 Since I compile my clerk notebooks, the solutions run every time I deploy so I need them fast but I'm not too fussed about shaving milliseconds
I’m № 1 all the time… until you get to that day where it takes 10 million years to solve.
I favour readability over performance for this kind of thing, although I guess readability is a bit subjective
I did AoC in Clojure last year, and I found that it’s quite easy (for a novice at least) to write correct and (I think) idiomatic Clojure code that runs quite slow. Then you have to think about lazy vs. not-lazy sequences, reflection, boxing etc. I was especially surprised that not-lazy code can be quicker that lazy (as laziness is mostly explained as a mean to save resources and not perform calculations until they are really needed).
It depends a little on what you're trying to do. Given that I'm only trying to solve the problems, I only care about perf when it matters, and I care about "readability" not a wit 😄
fwiw I find "readability" to be a grandly misunderstood topic in software, so I'm probably not representative
I do AoC for fun, so I only think of perf when it's fun to or if the solution space my code searches is too large for more naive/fun solutions
this is also probably why I burn out on AoC every year when it hits double digits -- it typically becomes more of a slog at that point and less fun -- I already have a job that challenges me in that way and so my recreation doesn't have to
I do like to go back and check performance after solving it in my normal hacked up way. I get a little sad when I see my also hacked up Rust code solves it 10x faster with the same lack of initial care. I guess it doesn't mean anything but I wish we could just magically have Clojure be super fast lol (clojure is still 10x more fun to write though of course)
@U9J50BY4C I'm curious to see some side-by-sides. People keep saying rust is great, but my initial take is that it's monstrously complex and forces you to deal with computer tedium. I'd be curious if you came up with relatively straightforward solutions.
Yeah, for example my first few days of 2015 were written how I normally would do Clojure and Rust I guess. When benchmarking them I see that huge performance gain with Rust. I should probably switch the apply
to reduce
and whatnot. Caveat: my idiomatic code back in 2015 might just suck in general but that's just when I tried some benchmarking recently
https://github.com/chase-lambert/aoc-clojure/tree/main/src/aoc/2015
https://github.com/chase-lambert/aoc_rust/tree/main/aoc_2015/src
I'm using this aoc tool called cargo-aoc
though because it does the benchmarking for me but it shouldn't make much of a difference I think
Isn't the big trick to making rust easy just doing copy all the time instead of dealing with ownership?
I feel like someone told me that
gah every other language is so clunky after doing clojure for 10 years. I know part of it is just that clojure is near at hand for me, but emotionally it's like watching kids derp around taking 10x the effort for simple tasks.
I mean that in as non-judgemental a way as possible. It's just my emotional (uninformed) reaction.
(Your code is very good btw. Wasn't a comment on that. I can understand it easily. It's the lang, not the writer.)
Rust definitely gets wild. I find it surprisingly straightforward (once you grok the borrow checker) for regular stuff especially considering how performant it is. It has some nice "high level" features. But when you start really getting into harder tasks, things get crazy quick and I run back to sweet, sweet Clojure.
Did some cryptography puzzles from https://cryptopals.com/ in Rust and found it less painful than i was expecting although I'm pretty sure i was cutting corners in a way that would be considered sloppy by proper rusties
Day 2 seems to be very easy compare to Day 1 (especially part 2). Did a Live Coding used Hyperfiddle for TDD and its available on https://www.youtube.com/watch?v=aF4OfRGnobk . https://github.com/muthuishere/advent-of-code-clojure-2023/blob/main/src/day2.clj
is the site down for anyone else?
oh, no, it works now