adventofcode

Happy Advent 2020! Please put answers in the pinned threads or create one if it does not exist yet. | https://github.com/adventofcode-clojurians/adventofcode-clojurians | Join the private leaderboard with code 217019-4a55b8eb
pez 2020-12-04T00:52:20.203900Z

I spent a lot of time counting all the trees passed vertically for when the sled goes 1 right, 2 down. I don’t know why I started to think I should do that when I didn’t do it horizontally… Anyway, if someone ever needs a sequence of x-deltas for a instructions like “x right, y down, forever”, here goes:

(defn dxs [dx' dy']
  (map (fn [line dx dy] 
         (* (+ line dy) dx)) 
       (range) 
       (repeat dx') 
       (cycle (range dy'))))
¯\(ツ)

mchampine 2020-12-04T01:20:09.204Z

(def raw-input (str/split-lines (slurp "resources/day03.data")))

(defn trees [inp [x y]]
  (let [expinp (map #(apply str (repeat 80 %)) inp)
        lines (rest (take-nth y expinp))]
    (count (filter #{\#} (map #(nth % %2) lines (range x 2300 x))))))

(trees raw-input [3 1]) ;; part 1
(apply * (map (partial trees raw-input) [[1 1] [3 1] [5 1] [7 1] [1 2]])) ;; part 2

pez 2020-12-04T01:57:44.206700Z

I’m a bit stuck on day 3, step 2. I get the right answer for the sample data, but too low for the real input. Not sure how I should go about debugging it. My solution looks like so, so far. (In the reply.)

pez 2020-12-04T08:17:08.227500Z

Replacing drop, first with nth gained me x1.2-ish, but I’ll of course keep that and celebrate the speed gain, since it is WAY clearer.

misha 2020-12-04T08:29:45.229700Z

nth is linear lookup. with cycle, each next line does longer and longer linear lookups

misha 2020-12-04T08:30:23.229900Z

e.g.:

...
.....
.......
.........
...........
.............

misha 2020-12-04T08:31:25.230100Z

if you mod your Xs, your lookups will be:

...
.....
.......
...
.....
.......

misha 2020-12-04T08:34:17.230600Z

(time (nth (cycle "abcd") 100000))
"Elapsed time: 7.717277 msecs"
=> \a

(time (nth "abcd" (mod 100000 (count "abcd"))))
"Elapsed time: 0.093352 msecs"
=> \a

pez 2020-12-04T08:47:52.231400Z

Gotcha. Down to 2.5 msec now. That’s x200 in total!

misha 2020-12-04T08:52:22.231800Z

:tatatananana:

pez 2020-12-04T08:53:30.232300Z

This is super helpful to me. I often reach for mod quickly. This time it was much easier for me to visualize it if I actually repeated the pattern indefinitely. But I should of course have remembered/realized to translate it to mod once it worked.

pez 2020-12-04T01:57:53.206800Z

(defn landing [dx line]
  (->> line
       (seq)
       (repeat)
       (flatten)
       (drop dx)
       (first)))

(defn count-trees [[dx dy] woods]
  (->> woods
       (take-nth dy)
       (map landing (map #(* % dx) (range))) ; is (take-nth dx (range)) better?
       (filter #{\#})
       (count)))

(comment
  (def input (util/fetch-input 3))
  (as-> input $
    (s/split-lines $)
    (map #(count-trees % $) [[1 2] [3 1] [5 1] [7 1] [1 2]])
    (apply * $)))

pez 2020-12-04T02:15:21.207Z

Found it! I fed it [1 2] instead of [1 1] for the first slope….

pez 2020-12-04T02:18:13.208100Z

I updated my input-fetcher to read the cookie from a file instead, like @plexus does in his bash script: https://gist.github.com/PEZ/bcd23b9bc099b8b21a41c8c9de78a0f4

pez 2020-12-04T02:24:17.208200Z

It takes about half a sec on my pretty fast MacBook.

rutledgepaulv 2020-12-04T05:15:22.208900Z

that second part was a lot of minutiae haha

☝️ 1
misha 2020-12-04T05:37:56.209Z

1. replace

(repeat)
       (flatten)
with (cycle) for probably x2 speedup 2. replace (cycle) with (mod dx line-len) for next x5-x10 speedup

misha 2020-12-04T05:40:51.209200Z

3. replace drop, first with nth for 3rd speedup

misha 2020-12-04T05:41:45.209400Z

(let [s (str/join (range 1000))]
  (time (nth s 2000))
  (time (first (drop 2000 s))))
"Elapsed time: 0.01144 msecs"
"Elapsed time: 0.264392 msecs"

plexus 2020-12-04T05:50:06.210Z

Live stream for day 4 starting soon https://youtu.be/K3f10iwxtOw

2020-12-04T09:03:29.232800Z

https://github.com/lambdaisland/aoc_2020/blob/main/src/lambdaisland/aoc_2020/puzzle04.clj#L35-L44 the fields are not used anywhere, so they could be removed ^_^

plexus 2020-12-04T09:03:59.233100Z

yes, I know

Joe 2020-12-04T12:08:44.237700Z

What does #"\R\R" match on? From context it looks like a double carriage return, but is it different from #"\r\r" ? https://regexr.com/ says \R is just an escaped R, which it clearly isn't in this case.

plexus 2020-12-04T12:15:08.238Z

it matches "\r" "\n" "\r\n" or a number of unicode newline characters. It does not backtrack between "\r\n", so #"\R\R" will match "\r\r" but not "\r\n" (it will match "\r\n\r\n")

plexus 2020-12-04T12:15:26.238200Z

basically it matches everything that conceptually is a newline

Joe 2020-12-04T12:15:48.238400Z

Ah nice, thanks

2020-12-04T05:50:44.210700Z

I woke up too late today, bye bye leaderboard 😢

rutledgepaulv 2020-12-04T05:52:48.211400Z

yeah i went to bed early and didn't do yesterday's problem until right before tonight's so also dropped 😞

plexus 2020-12-04T06:27:22.211900Z

meh... the leaderboards are really the last of my concerns 🙂

rjray 2020-12-04T06:30:36.212400Z

Argh. Tonight's took much longer than it should. I'm much more rusty than I thought.

djblue 2020-12-04T06:33:47.213400Z

Parsing and validation feels too much like real work 😆

😆 4
plexus 2020-12-04T06:35:03.214400Z

yeah can't say day 4 was particularly interesting... just tediously converting rules into code

plexus 2020-12-04T06:45:10.215500Z

so far the puzzles have been surprisingly easy though... was it like this in the past? it's been two years since I participated so maybe I remember it wrong, I guess it'll get harder in a few days.

erwinrooijakkers 2020-12-04T08:06:22.224300Z

Last year became really challenging for me, but first four days were similar to this year. It was interesting last year with puzzle inputs being programs in a fictional language called intcode you fed in various ways to your own interpreter(s) that you build up over the days with various stories around it (having a robot that runs on a computer that has to perform certain tasks by feeding it input and the coordinates it spit out in return will display a word which is your answer, stuff like that). Also a puzzle that could best be solved using trigonemetry and one with fast fourier transforms. Was magical and instructive.

djblue 2020-12-04T06:49:48.215600Z

Last year, for some of the puzzles, we built up a little byte code VM and our inputs were programs, it was pretty cool

djblue 2020-12-04T06:50:15.215800Z

We even got to chain the programs together via input/output ports

❤️ 2
2020-12-04T06:50:54.216100Z

Yeah, I loved it.

2020-12-04T06:51:55.216300Z

Last year, the first a bit challenging puzzle for me was on day 10, then day 12.

2020-12-04T06:54:00.216500Z

Day 22, part 2 was pretty hard for the most of the participants.

2020-12-04T06:54:50.216700Z

so true, and so boring

plexus 2020-12-04T07:03:16.216900Z

And the recording: https://youtu.be/XaXB0kbpvjw Code: https://github.com/lambdaisland/aoc_2020/

👍 1
plexus 2020-12-04T07:04:06.217100Z

I was just thinking "if this doesn't work from the first try it's going to suck to debug", but luckily it did

🙂 1
kenj 2020-12-04T07:09:14.217300Z

80% of my part 1 solution is parsing 😞

pez 2020-12-04T07:39:37.217500Z

Sweet! I got a x10 when replacing (seq) (repeat) (flatten) with (cycle).

spfeiffer 2020-12-04T07:40:40.217700Z

Yes, it gets harder, and perhaps this year they toned it down a little bit, because i remember last year the were some frustrated participants.

2020-12-04T08:26:04.229Z

@plexus I used Regal 🙂

plexus 2020-12-04T08:26:30.229200Z

I'm glad someone did :rolling_on_the_floor_laughing:

2020-12-04T08:28:51.229400Z

I am happy I spent time to get familiar with it, it might be useful one day.

pez 2020-12-04T07:44:17.218900Z

> 2. replace (cycle) with (mod dx line-len) for next x5-x10 speedup Not following here.

2020-12-04T07:46:28.219100Z

oh … I feel stupid, I did not think about that (str/split real-input #"\R\R")

fingertoe 2020-12-04T07:49:27.220900Z

That was way harder than it needed to be.. 😉. I really need to learn my destructuring better..

nbardiuk 2020-12-04T07:49:53.221200Z

Today is a bit boring, but I've spend some creativity on refactoring parsing rules

fingertoe 2020-12-04T07:50:45.221600Z

It seems to me the past years I have done it, it gets steeper pretty fast after the first 3 or 4 days. It also tends to go back an re-factor off of your old solutions, so it’s hard to jump right in if you get behind.

nbardiuk 2020-12-04T07:53:46.222800Z

last year day 3 was already challenging. If you look at stats https://adventofcode.com/2019/stats you can find where people have dropped off. Like days 3, 7, 18

Ben List 2020-12-04T07:59:18.224Z

Not super happy with what I came up with today. But I'm still new to clojure https://github.com/listba/advent-of-code-2020/blob/master/clojure/src/aoc_2020/days/04.clj

😍 2
1
plexus 2020-12-04T08:31:59.230400Z

interesting that you reach to core.match for this!

erwinrooijakkers 2020-12-04T08:46:15.230900Z

indeed very nic

erwinrooijakkers 2020-12-04T08:46:16.231100Z

e

motform 2020-12-04T13:37:03.240600Z

always fun to see core.match! Also, if you want to destructure map keys into vars with the same name, you can use the handy :keys syntax (defn validate-passport-fields [{:keys [ecl pid eyr hcl byr iyr hgt]} ,,,)

💯 1
Ben List 2020-12-04T14:48:14.247700Z

I'm a scala dev by trade so pattern matching calls to me, and great tip thanks!

1
erwinrooijakkers 2020-12-04T08:10:08.227100Z

Missed my alarm, tedious puzzle luckily everything worked first try

misha 2020-12-04T08:19:51.228900Z

over-engineering, over-engineering everywhere 🤦

nbardiuk 2020-12-04T08:52:00.231600Z

AOC made bad job generating invalid passports 😆 you code proves that • all years fields are actually numbers • height does not have other text than number and unit of measure • documents do not have keys other than explicitly specified

misha 2020-12-04T08:53:13.232100Z

true

misha 2020-12-04T08:59:57.232600Z

(remove #(not-empty (dissoc % "hgt" "byr" "eyr" "iyr" "ecl" "hcl" "cid")))
and
(defn parse-int [s else]
  (try
    (Integer/parseInt s 10)
    (catch Exception e else)))

(parse-int "foo" -1)
=> -1
would fix that

2020-12-04T09:13:29.233900Z

My solution to day 4, but I’m going to refactor it https://github.com/zelark/AoC-2020/blob/72968c3e2baa8fcb2a2a5a0ff84d9a6fb689f644/src/zelark/aoc_2020/day_04.clj#L1

genmeblog 2020-12-04T11:34:36.235600Z

and mine solution (possibly over-engineered 🙂) https://github.com/genmeblog/advent-of-code-2020/blob/master/src/advent_of_code_2020/day04.clj

Joe 2020-12-04T11:54:35.237100Z

https://redpenguin101.github.io/posts/2020_12_04_aoc2020_day4.html - clojure.spec seems tailor-made for this 🙃. No-one else seemed tempted though? Just not worth it for such a simple use case?

👍 4
nbardiuk 2020-12-04T12:05:17.237400Z

I've given up on specs, but when I got a wrong answer regretted it. Spec's explain would be very useful to debug which rule invalidated an entry

benoit 2020-12-04T12:43:18.239Z

My solution to Day 4 with clojure.spec: https://github.com/benfle/advent-of-code-2020/blob/main/day4.clj

👍 1
❤️ 1
3
erwinrooijakkers 2020-12-04T13:35:01.239700Z

I was in a hurry. Would have loved to use Malli or spec

2020-12-04T13:36:11.240100Z

I solve the puzzle using Minimallist, a library inspired by Malli and Spec. https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_4.clj

👀 1
motform 2020-12-04T13:40:56.243100Z

Great to see someone use spec! My solution is very boring, I’m sure parse-passport and valid-hgt? could be more terse, but it was a bit to boring to refactor. https://github.com/motform/advent-of-clojure/blob/master/src/advent-of-clojure/2020/four.clj

motform 2020-12-04T13:41:22.243900Z

Also, general question! Dones anyone have any examples of fancy ways of doing validation? Rule based systems?

2020-12-04T14:28:49.246100Z

My day 4. Not a great solution, but it worked in the end. https://gist.github.com/stuartstein777/7b69f6f39fe44669c77e935ba1249aec

Narve Saetre 2020-12-04T14:36:37.247300Z

I am really glad I used spec for part 1 😄 First practical use of spec for me:

(def text (slurp "adv4.input.txt"))
;(def text "ecl:gry pid:860033327 eyr:2020 hcl:#fffffd\nbyr:1937 iyr:2017 cid:147 hgt:183cm\n\niyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884\nhcl:#cfa07d byr:1929\n\nhcl:#ae17e1 iyr:2013\neyr:2024\necl:brn pid:760753108 byr:1931\nhgt:179cm\n\nhcl:#cfa07d eyr:2025 pid:166559648\niyr:2011 ecl:brn hgt:59in")


(defn parse-line [l]
  (let [
        psa (string/split l #"[\s+]")
        pa (map #(string/split %1 #"\:") psa)
        ma (map (fn [p] {(first p) (second p)}) pa)
        m (apply merge ma)]
    m))

(def entries (map parse-line (string/split text #"\n\n")))

(s/def ::byr (s/and string? #(<= 1920 (bigint %1)) #(>= 2002 (bigint %1))))
(s/def ::iyr (s/and string? #(<= 2010 (bigint %1)) #(>= 2020 (bigint %1))))
(s/def ::eyr (s/and string? #(<= 2020 (bigint %1)) #(>= 2030 (bigint %1))))
(s/def ::hgt (s/and string? (s/or ::in #(re-matches #"\d{2}in" %1) ::cm #(re-matches #"\d{3}cm" %1))))
(s/def ::hcl (s/and string? #(re-matches #"\#[0-9a-f]{6}" %1)))
(s/def ::ecl #{"amb" "blu" "brn" "gry" "grn" "hzl" "oth"})
(s/def ::pid (s/and string? #(re-matches #"[0-9]{9}" %1)))

(s/def ::passport
  (dict {"ecl" ::ecl
         "pid" ::pid
         "eyr" ::eyr
         "hcl" ::hcl
         "byr" ::byr
         "iyr" ::iyr
         "hgt" ::hgt}))

(def v (count (filter #(s/valid? ::passport %1) entries)))

(println "Valid: " v " total " (count entries))

Narve Saetre 2020-12-06T19:39:46.341500Z

Right, sorry i'll use thread replies or links next time.

Narve Saetre 2020-12-06T19:40:12.341700Z

Thanks for the hint, @ben.list89 - I saw that in other submissions. Lots of improvements to make!

2020-12-04T15:08:28.248500Z

@narve As the topic says, please put spoilers in thread replies. Thank you.

➕ 1
2020-12-04T15:08:52.248700Z

links to code are also ok

Ben List 2020-12-04T17:09:20.249Z

fyi you can do (<= min num max) instead of (and (<= min num) (>= max num)

misha 2020-12-04T17:35:49.251200Z

:d:

tws 2020-12-04T17:38:51.251500Z

another spec sol’n. To handle part1 being less specific, I would up with a non s/keys spec for it. Any ideas there? I didn’t want to start undef’ing specs for half the problem. https://github.com/tschady/advent-of-code/blob/master/src/aoc/2020/d04.clj

tws 2020-12-04T17:40:57.252300Z

i have unit tests that verify part-1 and part-2 are still correct as I refactor and optimize, so I need both parts to work at same time.

tws 2020-12-04T17:42:09.252500Z

(like ::hgt needs refactoring)

2020-12-04T17:43:39.252700Z

btw, you could a bit simplify the spec for part 1

2020-12-04T17:43:57.252900Z

(every? (partial contains? %) required-fields) would work

tws 2020-12-04T17:47:40.253200Z

much better, updated, thanks!

2020-12-04T17:54:53.253800Z

are you assuming for day4, part1 that the “values” are always non-empty?

st3fan 2020-12-04T17:56:54.254300Z

Ohh I should have used spec for this one

st3fan 2020-12-04T17:57:36.254600Z

One thing I learned today is (<= 150 height 193) - which is a nice readable short form for (and (…) (…))

1
👀 1
st3fan 2020-12-04T17:58:59.255Z

Day 5 Answers Thread .. Post your answers here

tws 2020-12-05T10:32:06.291800Z

with clojure.set I go for readability with some lets . https://github.com/tschady/advent-of-code/blob/master/src/aoc/2020/d05.clj

Dosbol 2020-12-05T10:32:50.292300Z

(def l->b {\B 1 \F 0 \R 1 \L 0})
(def powers-of-2 (iterate (partial * 2) 1))

(->>  s
      (map l->b)
      reverse
      (map * powers-of-2)
      (apply +))

👍 1
2020-12-05T11:09:21.294100Z

My final decode is

(defn decode [code]
  (-> (str/escape code {\F 0 \L 0 \B 1 \R 1})
      (Long/parseLong 2)))
That’s all you need 🙂

👍 1
🙌 3
Joe 2020-12-05T13:14:57.297400Z

I'm also linking to and trying to summarize and comment on other peoples solutions on that page, hope no-one minds

st3fan 2020-12-05T15:36:51.300600Z

Not super proud of part 2 - I think that could have a simpler solution

st3fan 2020-12-05T15:37:45.300900Z

Hmm subvec

st3fan 2020-12-05T15:38:47.301300Z

Ohh reduce clever I did a recursive loop

st3fan 2020-12-05T15:40:27.301700Z

omg a binary decode

st3fan 2020-12-05T15:41:27.302Z

sigh 🙂

st3fan 2020-12-05T15:41:31.302200Z

Should have recognized that

2020-12-05T16:17:55.302400Z

(ns advent.day5
  (:require [advent.core :as core]
            [clojure.string :as s]))

(defn seat-id [boarding-pass]
  (-> boarding-pass
      (s/replace #"[FL]" "0")
      (s/replace #"[BR]" "1")
      (Integer/parseInt 2)))

(->> (core/input-file "day5.txt")
     (map seat-id)
     (reduce max))
;; => 998

(defn my-seat? [[a b]]
  (= 2 (- b a)))

(->> (core/input-file "day5.txt")
     (map seat-id)
     sort
     (partition 2 1)
     (filter my-seat?)
     first
     first
     inc)
;; => 676
I thought the partition for part 2 was clever, but wondering if theres a better way to do the filter, first, first, inc chain?

2020-12-05T16:19:58.302600Z

@jculp yes, as Arne showed you could use some instead.

2020-12-05T16:20:24.302900Z

(some (fn [[lo hi]] (when (= (+ lo 2) hi) (inc lo))))

2020-12-05T16:31:50.303100Z

clever!

mchampine 2020-12-05T16:57:27.303700Z

;; day 5 super golf
(let [ec #(-> (str/escape % {\F 0 \B 1 \L 0 \R 1}) 
                (Integer/parseInt 2))
      sc (sort (map ec (str/split-lines 
                (slurp "resources/day05.data"))))
      p2 (ffirst (drop-while #(apply = %)
           (partition 2 (interleave (iterate inc (first sc)) sc))))]
  {:part1 (last sc) :part2 p2})

plexus 2020-12-05T17:08:17.304Z

some+when is a useful pattern. I vastly prefer it nowadays over filter+first

👍 3
Ben List 2020-12-05T18:52:02.305Z

my day 5, didnt pick up on the trick until I was nearly done but still fairly happy with the result (I did a scala solution using the trick afterwards) https://github.com/listba/advent-of-code-2020/blob/master/clojure/src/aoc_2020/days/05.clj

Ben List 2020-12-05T18:55:05.305400Z

scala version if anyone cares to see that: https://github.com/listba/advent-of-code-2020/blob/master/scala/src/main/scala/aoc2020/solutions/day-05.scala

Ola Sikström 2020-12-05T23:52:54.308200Z

Interesting to see all different/similar solutions 🙂 Here's my take https://github.com/teppix/advent-of-code-2020/blob/main/src/advent/day05.clj Used bit-shifting instead of the '2r' trick, but same idea.

devn 2020-12-06T01:50:57.308800Z

I am extremely jealous of @mchampine’s solution

🙂 1
st3fan 2020-12-04T17:59:23.255500Z

Day 6 Answers Thread .. Post your answers here

rjray 2020-12-06T05:32:05.310400Z

Mine was basically the same as Adam’s, just more verbose 🙂. https://github.com/rjray/advent-2020-clojure/blob/master/src/advent_of_code/day06.clj

Dosbol 2020-12-06T05:34:53.311Z

(->> (slurp "input6.txt")
     ((fn [v] (str/split v #"\n\n")))
     (map str/split-lines)
     (map (fn [xs] (-> xs str/join (str/split #""))))
     (map frequencies)
     (map keys)
     (map count)
     (apply +))

(->> (slurp "input6.txt")
     ((fn [v] (str/split v #"\n\n")))
     (map str/split-lines)
     (map (fn [xs] [(count xs) (-> xs str/join (str/split #""))]))
     (map (fn [[count xs]] (filter #(= count %) (vals (frequencies xs)))))
     (map count)
     (apply +))

😍 1
fingertoe 2020-12-06T05:42:59.312600Z

https://github.com/jreighley/aoc2020/blob/master/src/day6.clj. I really seem to like sets this year.

mchampine 2020-12-06T06:03:51.316300Z

Mine looks similar to others..

;; part 1
(def input
  (->> (slurp "resources/day06.data")
       str/split-lines
       (partition-by empty?)
       (take-nth 2)))

(apply + (map #(count (set (apply str %))) input))

;; part 2
(defn groupcnt [l]
  (count
   (for [x (set (apply str l))
         :when (every? #(str/includes? % (str x)) l)] x)))

(apply + (map groupcnt input))

2020-12-06T06:20:32.317600Z

I used frequencies for part 2 https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_6.clj

2020-12-06T06:31:14.320300Z

And I used union for the part 1, and intersection for the part 2. Just went with the same data structure for the both parts. https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_06.clj

👍 2
nbardiuk 2020-12-06T06:36:49.324400Z

Turns out both parts differs only whether it is set intersection or union https://github.com/nbardiuk/adventofcode/blob/c30b10fc2320c8f29fb9e84dd9afeaad3b04363b/2020/src/day06.clj#L17-L18

👍 5
2020-12-06T07:25:14.332500Z

I had that intuition as well, but the timer told me to write first and think later 😛

🏃 1
🚤 1
1
⏲️ 2
kenj 2020-12-06T07:41:04.332700Z

I rewrote my part 1 after noticing the same thing about the set operations https://gist.github.com/KennyMonster/ef878c0a789cebe2df3e572a11803f01

Ben List 2020-12-06T07:56:53.332900Z

definitely a pretty easy one with set operations https://github.com/listba/advent-of-code-2020/blob/master/clojure/src/aoc_2020/days/06.clj

pez 2020-12-06T09:13:45.333900Z

I want more of these easy ones.

(comment
  (def input (util/fetch-input 6))

  ; step 1
  (->> (clojure.string/split input #"\R\R")
    (map #(clojure.string/replace % #"\R" ""))
    (map #(clojure.string/split % #""))
    (map set)
    (map count)
    (apply +))

  ; step 2
  (->> (clojure.string/split input #"\R\R")
       (map clojure.string/split-lines)
       (#(for [answers %]
           (->> answers
                (map set)
                (apply clojure.set/intersection))))
       (map count)
       (apply +)))

2020-12-06T16:43:49.340400Z

;; part 1
(defn count-answers [s]
  (->> (mapcat #(str/split % #"") s)
       (into #{})
       (count)))

;; part 2
(defn count-answers-2 [s]
  (let [num-people (count s)
        combined (apply str s)
        answer-frequencies (frequencies combined)]
    (->> (filter (fn [[_ v]] (= num-people v)) answer-frequencies)
         (count))))

;; shared
(as-> (slurp "puzzle-inputs/2020/day6") o
      (str/split o #"\R\R")
      (map #(str/split % #"\n") o)
      (map count-answers-2 o)
      #_(map count-answers o)
      (reduce + o))

neeasade 2020-12-06T22:09:56.343200Z

I did something really silly at first lol -- forgot you could just (set "string") -- https://github.com/neeasade/AdventOfCode/commit/aa941beeb54407bde2b7a00c6678d34345eff80c

st3fan 2020-12-04T18:00:01.256100Z

Check the pinned threads people - no spoilers in the main channel

nbardiuk 2020-12-04T18:00:14.256200Z

yes, if there is a key it has a value

kenj 2020-12-04T18:13:19.258300Z

My solution using spec… probably poorly since I just recently learned it 🙂 https://gist.github.com/KennyMonster/a51c03c53403e76413aa2fe4d61d57a4

pez 2020-12-04T19:32:00.259400Z

If there is a will there is a way.

💯 1
pez 2020-12-04T22:08:08.262500Z

My day-4 solution. I have a feeling I could have used spec for the parsing, but I’m such a newbie with spec so what do I know. https://gist.github.com/PEZ/42375289c032e43ee6dd8cd40b3c1b42

pez 2020-12-04T22:59:51.262800Z

I think it is super nice. I learn a lot by looking at it. One thing makes me wonder “why?” though, and that is your between? function. Is (partial between? 1920 2002) more readable to you than #(<= 1920 % 2020)?

2020-12-04T23:09:06.265100Z

I've been using re-seq with capturing groups pretty heavily in some of these, just in case someone wasn't aware of it! Can be a really nice way of parsing the input sometimes if it follows a simple pattern. Less string splitting and you get a seq of the values you're interested in right away.

neeasade 2020-12-06T22:08:44.343Z

@risinglight thanks!

kenj 2020-12-04T23:14:02.265200Z

this would have simplified parsing on day 4 for me!

➕ 1
pez 2020-12-04T23:20:24.265400Z

I used it for my day 4 parser, which ended up like so:

(defn parse [card]
  (->> (clojure.string/replace card #"\s" " ")
    (re-seq #"(\S+):(\S+)")
    (map rest)
    (reduce
     (fn [m [k v]]
       (assoc m
              (keyword k)
              v))
     {})))

kenj 2020-12-04T23:32:58.266Z

I just refactored mine from a giant nasty looking threading macro doing all sorts of terrible hack n slash

(defn parse-passport-chunk [s]
  "key/val pairs separated by whitespace into a map"
  (into {} (map (fn [[_ key val]] [(keyword key) val])
                (re-seq #"(\w+):(\S+)" s))))

(defn input->passports [s]
  "Raw input -> map of passwords w/ keyword keys"
  (->> (str/split s #"\n\n")
       (map parse-passport-chunk)))

pez 2020-12-04T23:38:22.266200Z

Yeah, ours are pretty similar now. And I can also get rid of that (map rest) and do what you do there:

(defn parse [card]
  (->> (clojure.string/replace card #"\s" " ")
    (re-seq #"(\S+):(\S+)")
    (reduce
     (fn [m [_ k v]]
       (assoc m
              (keyword k)
              v))
     {})))

kenj 2020-12-04T23:49:58.266400Z

given how your regex is defined, I don’t think there’s even a need to do the replace call to normalize the whitespace, since it will be thrown out by re-seq regardless

pez 2020-12-04T23:54:51.266600Z

Yeah, I realized that when I saw your code. 😃