adventofcode

2021-12-03T11:38:52.167200Z

I'm in that horrible situation where my code runs on the test data for day 3, and produces correct answer, and runs on the full data without crashing, but the answer is wrong... gah

Aleks 2021-12-03T11:51:55.167400Z

Maybe you’ve missed this “If `0` and `1` are equally common, keep values with a `1` in the position being considered.” and this “If `0` and `1` are equally common, keep values with a `0` in the position being considered.”

2021-12-03T11:59:08.167700Z

hmmm. That will be it, I assumed since the page doesnt explain what to do in the event of a tie that its set to never occur, thanks!

genmeblog 2021-12-03T12:02:49.167900Z

It explains (for part 2): "If `0` and `1` are equally common, keep values with a `1` in the position being considered."

2021-12-03T12:03:10.168100Z

ah, im on part 1!

genmeblog 2021-12-03T12:07:03.168300Z

ah! do you have a tie in your dataset? (I don't have, it may happen in part 2)

2021-12-03T12:07:35.168500Z

I don't, as even putting that condition I'm getting back same answer

2021-12-03T12:11:44.169600Z

epsilon is always just gamma with the bits flipped right?

2021-12-03T12:13:46.169800Z

omg, i was debugging and had a rogue (take 3) in! argh! That I forgot to take out once I was using the real data. IT works and I have part 1 completed.

🎉 7
nooga 2021-12-03T13:14:26.170800Z

wall of text today 😄

Ben Sless 2021-12-03T13:45:18.170900Z

I didn't do part 2 only due to too long didn't read

😆 4
2021-12-03T14:18:24.171800Z

meme from reddit:

🧵 1
2021-12-03T14:18:33.171900Z

😆 6
2021-12-03T14:21:17.172900Z

At least you wouldn't have the leaderboard filled in 2 minutes!

😂 1
tschady 2021-12-03T16:36:09.177Z

TIL about: https://github.com/clojure/data.int-map seems very useful for AOC

Ben Sless 2021-12-03T16:42:49.177600Z

if your ints are sequential, you can just use a vector

2021-12-03T16:48:51.179200Z

does anyone else find themselves more interested in refactoring part1 so that it can be solved using part2 code, rather than going for sheer speed?

Mario C. 2021-12-03T17:00:04.179600Z

Yes, I am actually focusing on this, this year. I try to write part 1 in such a way that it can be re-used or easily refactored for part2. The less effort required for part 2 means I did a decent job with part 1. Major refactor means I may have made it to specific.

thom 2021-12-03T17:40:43.182700Z

Yeah. I find no joy in just doing the quickest thing, it's far more fun to have unit tests and nice abstractions. Also fun to properly benchmark multiple approaches etc.

AC 2021-12-03T17:41:16.182900Z

This is my first year tracking my progress on a private leaderboard, so I hacked up a pretty gross solution to part 1. After I read part 2, it didn't feel right to do the same. I did refactor part 1 and then came back and finished part 2 this morning. I'm pretty sure I'll end up refactoring it a couple more times.

Benjamin 2021-12-03T17:51:18.183400Z

Rich always solves part 2 while hammoking on part 1

2021-12-03T17:55:27.183600Z

awesome. sounds like I am in good company, then 😁

thom 2021-12-03T18:02:13.186600Z

I mean, I can't be the only person with GitHub Actions running my tests and generating Marginalia docs, right? Right?

😮 1
fingertoe 2021-12-03T18:42:12.187800Z

All in all, I think speed is rather useless.. Instead, I want to do it badly first, so I can build buckets to put the “how to do it right” knowledge into..

Antonio Bibiano 2021-12-03T19:10:28.188300Z

I like to get to a solution as fast as i can and then spend the rest of the day thinking about better ways, that allows me to learn a lot from other people solution throughout the day with no guilt :D

👏 4
2021-12-03T22:12:09.190200Z

+1 to get solution as quickly as you can and then if you find it interesting enough optimise it 😄

nbardiuk 2021-12-03T18:00:28.185200Z

Stats show a dip today on part2, almost half of people decided to skip it https://adventofcode.com/2021/stats

kpav 2021-12-03T18:06:09.186800Z

I can only assume it was the big wall of text. I know I couldnt process that while I was half asleep last night.

➕ 3
nbardiuk 2021-12-03T18:11:05.187Z

Yeah, I waisted time debugging code while the problem was in my reading skils

2021-12-03T18:27:20.187200Z

I managed to get part 1 done during a meeting today at work, just haven't had time yet today to even look at part 2

2021-12-03T18:27:37.187400Z

And I'm going out tonight, so will have to do part 2 tomorrow before I do day 4

nbardiuk 2021-12-03T18:30:17.187600Z

That a good point, tomorrow is a weekend, people will have plenty of time to catch up

sebastian 2021-12-03T20:39:22.189600Z

for me at least, part 2 was a considerable step up in difficulty from part 1

2021-12-04T01:47:14.196600Z

just finished day3, it's 1:46 am here and I'm pretty drunk. Very not proud of my code

Cora (she/her) 2021-12-03T04:30:22.154600Z

I'm super boring about my solutions. here's days 1 and 2 https://gist.github.com/corasaurus-hex/ee69c4bdee71b55a1ebbcf588d82c527

Benjamin 2021-12-03T17:22:54.180Z

sick. I learned about the args to partition from this

🎉 1
mchampine 2021-12-03T05:49:15.156900Z

Done with day3 but it’s too ugly to post before some cleanup. :)

➕ 1
🙌 1
Aleks 2021-12-03T06:02:15.157100Z

the same

Aleks 2021-12-03T06:03:00.157300Z

and the part two has a pitfall ^_^

peterc 2021-12-03T06:48:14.158800Z

hah did everyone copy and paste their code for part2?

mchampine 2021-12-03T07:28:14.161600Z

@zelark what pitfall did you notice?

Aleks 2021-12-03T07:33:56.161800Z

@mchampine actually it wasn’t a pitfall, I just didn’t read the description carefully.

mchampine 2021-12-03T07:40:07.162300Z

@zelark Yeah, when the problem text is that long and involved, it’s so easy to get some little detail wrong. So to me it had several potential pitfalls there! Not to mention the usual risks of off-by-ones and edge cases. I couldn’t use max-key vs min-key in part 2 because they’re not complements like > and <= are. @peterc I copy/pasted on my first pass, but couldn’t stand to look at it. 🙂

Aleks 2021-12-03T06:04:02.157600Z

🧵 Day 3 answers thread: post your answers here

Antonio Bibiano 2021-12-03T09:08:01.163100Z

this is my solution

; part 1
(defn rate [key-compare input]
    (->> input
         (apply map vector)
         (map frequencies)
         (map #(key (apply key-compare val %)))
         string/join)
  )

(def gamma (rate max-key large))
(def epsilon (rate min-key large))

(* (Integer/parseInt gamma 2) (Integer/parseInt epsilon 2))

; part 2

(defn rate [comparison input]
  (loop [pos 0 
         input input]
    (if (= 1 (count input))
      (first input)
      (let [{zeros \0 ones \1} (group-by #(nth % pos) input)]
        (if (comparison (count zeros) (count ones))
          (recur (inc pos) ones)
          (recur (inc pos) zeros))))))

(def oxygen (rate <= large))

(def co2 (rate > large))

(* (Integer/parseInt oxygen 2) (Integer/parseInt co2 2))

👍 3
Callum Oakley 2021-12-03T12:10:53.169100Z

surprised I don’t see anybody above using bit-test bit-set etc! https://github.com/callum-oakley/advent-of-code/blob/main/src/aoc/2021/03.clj

👍 2
1
genmeblog 2021-12-03T12:11:31.169400Z

I used bit-not and bit-and in part 1

☝️ 2
Joe 2021-12-03T12:34:00.170300Z

https://github.com/RedPenguin101/aoc2021/blob/main/day03.md https://github.com/RedPenguin101/aoc2021/blob/main/clojure/src/aoc2021/day03.clj Haven't read any other solutions yet, but whenever there's one of these binary problems I always feel like I've missed a trick by not actually using any bitwise operators. Like that plane seating problem, I forget which year.

👏 3
R.A. Porter 2021-12-03T14:20:11.172600Z

Even if I remove all the comment blocks, I'm still pretty long today. So a link instead - https://github.com/coyotesqrl/advent-of-code/blob/main/src/coyotesqrl/2021/day3.clj Like @tsulej, I also used bit-and and bit-not in part 1. Both parts today, in fact, have that inverse, mirror symmetry. I used filter/`remove` to get to the O2/CO2 values.

👍 1
borkdude 2021-12-03T15:08:51.173800Z

I have the feeling this could be a one-or-two liner so it's probably more verbose than necessary: https://gist.github.com/borkdude/b5cf0e9d2d8ab7c678d88e27a3357b33#file-aoc21_03-clj But it runs in insignificant time with bb (60ms including startup).

👍 2
2021-12-03T16:03:12.174500Z

Here’s mine. I used core.matrix and didn’t end up using it much. I have the feeling there’s a function I’m missing that would’ve made things easier.

2021-12-03T16:05:53.175100Z

Looking forward to reading others’ solutions later to compare, but gotta do some real work first 🙂

V 2021-12-03T16:17:28.175500Z

I'll paste my solution here. I feel like I made it too complicated. I'm still too reliant on loops - Feedback is very welcome

V 2021-12-03T16:44:24.177800Z

tschady 2021-12-03T16:55:14.179300Z

https://github.com/tschady/advent-of-code/blob/main/src/aoc/2021/d03.clj after a vain search for bitwise brilliance (deeper than bit-test and bit-and-not I just went with strings. I like my part1 (no temporary variables), but p2 still needs work.

Fredrik 2021-12-03T19:04:06.188100Z

My unreadable solution of part 2, making each bitstring a function that pushes a counter up or down and adds itself to a set, the sign of counter then picks next set of bitstrings to inspect.

(defn pick [l test]
  (let [make-fn (fn [idx f]
                  (fn [[n m]] [(f n) (update m f (fnil conj #{}) idx)]))
        to-weird-format (fn [a]
                          (map-indexed #(mapv (partial make-fn %1) (mapv {\1 inc \0 dec} %2)) a))
        pos-or-neg (fn [xs idx]
                     (reduce #(%2 %1) [0 {}] (map #(nth % idx) xs)))
        l2 (to-weird-format l)]
    (loop [candidates l2,  bit-index 0]
      (let [[n m] (pos-or-neg candidates bit-index)
            next-indices (if (test n) (m inc) (m dec))]
        (if (< 1 (count next-indices))
          (recur (reduce #(conj %1 (nth l2 %2)) [] next-indices)
                 (inc bit-index))
          (nth l (first next-indices)))))))

(defn sol [input-string]
  (apply * (map #(Integer/parseInt % 2)
                (map #(pick (str/split-lines input-string) %) [(partial <= 0) (partial > 0)]))))

2021-12-03T19:46:35.188900Z

a little late to the party but I finally found time to do it today! https://github.com/theianjones/aoc_2021/blob/master/src/theianjones/aoc-2021/d03/answer.clj

👏 1
gabo 2021-12-03T22:04:34.189900Z

This one felt like a chore for some reason https://gist.github.com/galuque/2fec8a886e1cb24f17662fda438d7e83

2021-12-03T22:14:48.190500Z

https://github.com/kfirmanty/advent-of-code-2021/blob/main/src/day3.clj - here is mine. somehow managed to reuse most of the extract logic from part 1. But accessing things positionally in Clojure always feels kind of dirty to me 😄

Andrew Byala 2021-12-03T22:45:28.194400Z

I loved the day 3 puzzle. Here’s a link to my blog about my solution and its many refactorings, with a link to the source at the top. I really enjoyed making composable functions, like most-common-bit, least-common-bit, one-pass-bit-check, and multi-pass-bit-check that all built up my gamma, epsilon, O2, and CO2 calculations. Very fun day! https://github.com/abyala/advent-2021-clojure/blob/main/docs/day03.md

👏 1
Chase 2021-12-04T01:00:16.195100Z

Oh man, part 2 ate me alive. I don't know why I struggled so much but that's kind of sad this early in the game. Haven't had a chance to process and clean it up. I just can't figure out how to think in terms of reduce. https://github.com/Chase-Lambert/aoc-clojure/blob/main/src/aoc/2021/day_03.clj

Chase 2021-12-04T01:01:31.195400Z

I'm looking forward to reading these answers and figuring out how to approach this in a more simple manner. Things got ugly quick! lol

euccastro 2021-12-04T01:29:10.195700Z

my solution: https://github.com/euccastro/advent-of-code-2021/blob/main/day3.clj I have the feeling that I left some mathematical insight on the table, but this is much cleaner than the first thing that I got to work

euccastro 2021-12-04T01:35:08.196Z

oh yeah, frequencies would have helped in part one

euccastro 2021-12-04T01:46:56.196400Z

TIL (or was reminded of) %& in function literals

euccastro 2021-12-04T01:51:51.196900Z

@zelark great one! part 1 esp. blew my mind. this is maybe evil, but (sort-by (juxt second first)) could be (sort-by reverse) in this case?

2021-12-04T01:52:47.197200Z

Day 3, part 1 (I'll post part 2 when I'm not utterly ashamed of it 😆)

(defn get-key-with-highest-val [m]
  (if (>= (m \1 0) (m \0 0))
    \1
    \0))

(defn flip-bits [s]
  (map (fn [i] ({\1 \0 \0 \1} i)) s))

(defn binary-str->int [s]
  (Integer/parseInt s 2))

(defn char-seq->str [cs]
  (->> (map str cs)
       (str/join "")))

;; part 1
(let [input (->> (f/read-all-lines-and-parse "puzzle-inputs/2021/day3" parser)
                 (apply map vector)
                 (map frequencies))
      γ-bin (->> input
                 (map get-key-with-highest-val))
      ε     (->> γ-bin
                 (flip-bits)
                 (char-seq->str)
                 (binary-str->int))
      γ     (->> γ-bin
                 (char-seq->str)
                 (binary-str->int))]
  (* ε γ))

2021-12-04T01:58:48.197500Z

OK, I'm still ashamed of it but 🙅‍♂️ it's 2am here...

(defn has-v-at-idx [idx v xs]
  (= v (nth xs idx)))

(defn parser [l]
  (map identity l))


(defn reduce-binary-over-f [input f]
  (loop [input input, idx 0]
    (if (= 1 (count input))
      (-> (first input)
          char-seq->str
          binary-str->int)
      (let [bits-at-idx (nth (apply map vector input) idx)
            most-common (->> (frequencies bits-at-idx)
                             (get-key-with-highest-val)
                             (f))]
        (recur (filter (partial has-v-at-idx idx most-common) input)
               (inc idx))))))

(let [input (f/read-all-lines-and-parse "puzzle-inputs/2021/day3" parser)
      oxygen-generator (reduce-binary-over-f input identity)
      oxygen-scrubber (reduce-binary-over-f input #({\1 \0 \0 \1} %))]
  (* oxygen-generator oxygen-scrubber))

euccastro 2021-12-04T02:05:05.198Z

you don't need to wrap the map in a function literal; it's already a function as is

2021-12-04T02:05:50.198300Z

What do you mean ?

euccastro 2021-12-04T02:06:18.198500Z

#({\1 \0 \0 \1} %) could be just {\1 \0 \0 \1}

euccastro 2021-12-04T02:06:43.198700Z

that part 2 solution looks fine to me, nothing to be ashamed of

➕ 1
2021-12-04T02:06:48.198900Z

ah okay! I see, thank you!

euccastro 2021-12-04T02:07:28.199100Z

kudos on the greek chars for part 1! 😄

2021-12-04T03:41:05.200Z

Basically the same as 3-4 others I saw.

2021-12-04T03:41:21.200200Z

I’m kinda convinced there’s no pretty way to do Part 2.

Sam Adams 2021-12-04T04:07:51.201200Z

a late, long-winded submission: https://samadams.dev/2021/12/03/advent-of-code-day-3.html

Sam Adams 2021-12-04T04:09:11.201500Z

Maybe tomorrow I’ll benchmark a frequencies -based solution too

Sam Adams 2021-12-04T04:42:39.201900Z

@zelark I might be misreading but I think your gamma and epsilon ratings are flip-flopped 🙂

Aleks 2021-12-04T04:53:48.202300Z

@sam.h.adams you’re right, I was polishing the code and mixed them up. But yesterday evening I refactored the code and there is no even names, just one single thread 🤩 https://github.com/zelark/AoC-2021/blob/main/src/zelark/aoc_2021/day_03.clj

👏 1
Aleks 2021-12-04T04:56:50.202600Z

@euccastro revers won’t help here

; Execution error (IllegalArgumentException) at zelark.aoc-2021.day-03/eval9970 (REPL:47).
; Don't know how to create ISeq from: clojure.core$reverse

Benjamin 2021-12-05T12:12:29.259100Z

proud of part 2 https://github.com/benjamin-asdf/advent-of-code-2021/blob/master/src/day3.clj - now I can read your solutions and go aha 7 times 😛

Cora (she/her) 2021-12-06T03:45:03.306200Z

again a very boring solution by me

2021-12-03T06:54:30.160300Z

Ugly code ...

(ns aoc2021.day3
  (:require [ :as io]
            [clojure.string :as str]
            [clojure.edn :as edn]))

(defn parse-binary [s]
  (edn/read-string (str "2r" (str/triml s))))

(def input
  (->> (io/resource "day3.txt")
       io/reader
       line-seq))

;; Part 1
(let [s (for [index (-> input first count range)
              :let [{zeroes \0
                     ones   \1} (->> input
                                     (map (fn [bin] (nth bin index)))
                                     frequencies)]]
          (if (< zeroes ones)
            [\1 \0]
            [\0 \1]))
      gamma (->> s
                 (map first)
                 str/join
                 parse-binary)
      epsilon (->> s
                   (map second)
                   str/join
                   parse-binary)]
  (* gamma epsilon))

;; Part 2
(defn most-common-bit [coll index]
  (let [{zeroes \0
         ones   \1} (->> coll
                         (map (fn [x] (nth x index)))
                         frequencies)]
    (if (<= zeroes ones) \1 \0)))

(defn least-common-bit [coll index]
  (let [{zeroes \0
         ones   \1} (->> coll
                         (map (fn [x] (nth x index)))
                         frequencies)]
    (if (<= zeroes ones) \0 \1)))

(let [[[oxygen] _] (->> [input 0]
                        (iterate (fn [[s index]]
                                   (let [bit (most-common-bit s index)]
                                     [(filter (fn [n]
                                                (= (nth n index) bit))
                                              s)
                                      (inc index)])))
                        (drop-while (comp not #{1} count first))
                        first)
      [[co2] _] (->> [input 0]
                     (iterate (fn [[s index]]
                                (let [bit (least-common-bit s index)]
                                  [(filter (fn [n]
                                             (= (nth n index) bit))
                                           s)
                                   (inc index)])))
                     (drop-while (comp not #{1} count first))
                     first)]
  (* (parse-binary oxygen)
     (parse-binary co2)))

👏 1
peterc 2021-12-03T06:55:18.160500Z

(defn read-data []
  (->> (slurp "data/day3.txt")
       clojure.string/split-lines
       (map (fn [s]
              (->> (seq s)
                   (map #(- (int %) (int \0))))))))

(defn to-decimal [ns]
  (read-string (apply str "2r" ns)))

(defn part1 []
  (let [data   (read-data)
        n      (count data)
        counts (apply map + data)
        v1     (map #(if (< % ( * n 0.5)) 1 0) counts )
        v2     (map #(if (< % ( * n 0.5)) 0 1) counts )]
    (* (to-decimal v1)) (to-decimal v2)))


(defn bit-to-keep-o2 [ones zeroes]
 (cond
   (= ones zeroes) 1
   (> ones zeroes) 1
   :else           0))

(defn bit-to-keep-co2 [ones zeroes]
 (cond
   (= ones zeroes) 0
   (< ones zeroes) 1
   :else           0))

(defn part2-rating [f ratings]
  (loop [rs ratings
         n  0]
    (if (= 1 (count rs))
      (to-decimal (first rs))
      (let [counts   (->> rs
                        (map #(nth % n))
                        (reduce +))
            keep-bit (f counts (- (count rs) counts))]
        (recur (filter #(= (nth  % n) keep-bit ) rs)
               (inc n))))))

(defn part2 []
  (let [data (read-data)]
    (* (part2-rating bit-to-keep-o2 data)
       (part2-rating bit-to-keep-co2 data))))
Any improvements welcome.

mchampine 2021-12-03T07:11:54.161100Z

👍 4
Aleks 2021-12-03T07:39:44.162Z

Maybe I’ll refact it later ^_^ https://github.com/zelark/AoC-2021/blob/main/src/zelark/aoc_2021/day_03.clj

👏 2
mchampine 2021-12-03T07:45:14.162500Z

Btw, I found out that to get nice code coloring, start by clicking the lightning bolt in the lower left of the composition box, then select “create a text snippet”. It supposedly has language auto-detect but I haven’t tried it. It also doesn’t color it right away - takes a minute or so after you post!

💯 1
timo 2021-12-08T20:59:17.442400Z

Why do you @borkdude do this in your Day 3 solution?

(if more-ones? 
  (conj bits 1) (conj bits 0))
I don't understand why you are shifting the bits to the left with another 0 or 1 on it...

borkdude 2021-12-08T21:01:20.442600Z

eh, lemme check

borkdude 2021-12-08T21:03:23.442800Z

honest answer: I don't remember, day 3 is already too long ago ;)

timo 2021-12-08T21:04:44.443Z

alright, never mind. thanks anyway

Fredrik 2021-12-08T22:17:22.445100Z

this is not bit shifting per se, it is gradually building up the answer. for every position, determine if that column has more ones or zeros, and append accordingly either 1 or 0 to the answer

👍 1
borkdude 2021-12-08T22:21:42.445600Z

indeed

euccastro 2021-12-04T11:00:27.207Z

@zelark it seems you have the arguments swapped in your experiment? anyway, you're right it doesn't work, but for a reason that is surprising to me: clojure doesn't know how to compare lists (while it can compare vectors):

(sort '[(3 4) (1 2)])

clojure.lang.PersistentList cannot be cast to java.lang.Comparable

(sort-by (comp vec reverse) {:a 3 :b 1})
;; => ([:b 1] [:a 3])

euccastro 2021-12-04T11:01:09.207200Z

of course once you have to (comp vec reverse) it stops being that much prettier

Aleks 2021-12-04T12:32:30.210200Z

Yes, the actual exception is “clojure.lang.PersistentList cannot be cast to java.lang.Comparable”

👍 1
Joe 2021-12-04T12:59:41.211500Z

> I loved the day 3 puzzle.  Here’s a link to my blog about my solution > and its many refactorings, with a link to the source at the top.  I > really enjoyed making composable functions, like most-common-bit, least-common-bit, one-pass-bit-check, and multi-pass-bit-check that all built up my gamma, epsilon, O2, and CO2 calculations.  Very fun day! @abyala this was a great read and a nice solution, thanks!

Felipe 2021-12-04T13:24:53.211700Z

a bit late to the party, but here's mine! https://github.com/FelipeCortez/advent-of-code/blob/master/2021/03.clj

Felipe 2021-12-04T13:26:53.212Z

oh, I can do str/join instead of apply str. nice!

euccastro 2021-12-04T15:41:55.214600Z

looking into the details of clojure list/vector comparison I realized that I could shorten the following thread-last sequence in my solution:

(group-by #(nth % idx))
                (sort-by key)
                (map second)
                (sort-by count)
(where I felt clever for relying on the stability of sort-by so the order in the first sort would be a tie-breaker in the second one) to just
(group-by #(nth % idx))
                vals
                sort
because vectors will first be compared by length and then lexicographically on ties, which is exactly what I want

👏 1