Fork me on GitHub
#adventofcode
<
2020-12-02
>
kenj00:12:13

Did anyone else use reduce/`reduced`? It feels dirty but I can’t figure out how to get the same efficiency without it. My other solution was to use some but created the whole set of inputs before hand.

(defn find-ints-summing-to-target [coll]
  (reduce (fn [seen-set n]
            (let [diff (- target-sum n)]
              (if (seen-set diff)
                (reduced #{n diff})
                (conj seen-set n))))
          #{}
          coll))

potetm02:12:53

reduced is totally fine and normal. You use it in exactly this sort of situation: You want to short-circuit evaluation because you’re done.

👍 2
Mario C.16:12:16

Hey are you going to be doing a video series this year for AoC? @U07S8JGF7

potetm18:12:24

ugh I made the mistake of trying it in rust this year

potetm18:12:37

no one wants to see that 😄

Mario C.19:12:55

I liked how you broke down the problem in the videos regardless of language used. If you do decide to make them, I would take a look

kenj00:12:35

it also returns the whole set if a pair isn’t found which is a terrible result in the negative find case

kenj00:12:21

ah looks like skykanin did something similar above in a cleaner fashion

drowsy00:12:28

Today I just threw core.logic with finite domain at it, which worked out quite nice: https://github.com/IamDrowsy/aoc-2020/blob/master/clojure/src/advent_of_code/d01.clj

👍 7
mchampine06:12:23

Day 2, not bad, most of the work was processing the input into usable form. E.g.

{:lb 1, :ub 3, :ch \a, :pw "abcde"}
..which took as many loc as my solutions. Here are my pw test functions. Filter input with them and count the results:
(defn pwgood? [{:keys [lb ub ch pw]}]
  (<= lb (get (frequencies pw) ch 0) ub))

(defn pwgood2? [{:keys [lb ub ch pw]}]
  (= 1 (count (filter #(= ch %)
     [(nth pw (dec lb)) (nth pw (dec ub))]))))

pez09:12:05

That is beautiful!

pez09:12:27

Mine:

(defn checks? [{:keys [p1 p2 ch pwd]}]
  (as-> pwd $
    (filter #(= ch %) $)
    (count $)
    (<= p1 $ p2)))

(defn checks2? [{:keys [p1 p2 ch pwd]}]
  (let [p1 (dec p1)
        p2 (dec p2)]
    (as-> pwd $
      (seq $)
      (vec $)
      (not= (= ($ p1) ch) (= ($ p2) ch)))))
(I didn’t bother to update the parser between the two 😃 )

👍 1
pez09:12:18

Neither did you, I now realize. Haha.

nbardiuk07:12:51

I am curious what did you you use to parse data for Day 2. Have you used regexp or some nice parser combinator library?

mchampine15:12:09

A small regex. I simply split each line with #(str/split % #“[- :]“) and then converted the strings to numbers and chars as appropriate.

👍 1
pez06:12:07

I also used a regex, but with groups. I should have splitted instead, had I thought about it. 😀

plexus08:12:09

My solution for day 2 https://youtu.be/rghUu4z5MdM

👍 3
nbardiuk08:12:21

always forget about slurp and barf, I like how some edits are more fluent with them

1
Vincent Cantin05:12:28

I mapped my forward/backward slurp/barf in a positional way on my keyboard, to forget their names and remember what they do.

pez06:12:57

Watched it now. Super nice. You are so fluent in both how you talk and how you code, making it a pleasant experience.

plexus06:12:24

Thank you 😊

Stuart14:12:50

My day 2 part 1 was pretty similar to yours

(defn parse-line [s]
  (let [splits (rest (re-find #"(\d+)-(\d+)\s(.):\s(.+)" s))]
      {:range [(Integer/parseInt (first splits)) (Integer/parseInt (second splits))]
       :char (first (nth splits 2))
       :password (last splits)}))

;; check valid for part 1
(defn valid-password? [{:keys [range char password]}]
  (let [[min max] range
        freq       (frequencies password)
        char-count (freq char 0)]
    (<= min char-count max)))

;; check valid for part 1
(defn valid-password? [{:keys [range char password]}]
  (let [p1 (nth password (dec (first range)) \_)
        p2 (nth password (dec (second range)) \_)]
    (or (and (= char p1) (not= char p2))
        (and (not= char p1) (= char p2)))))

(->> (slurp "input.txt")
     (str/split-lines)
     (map parse-line)
     (filter valid-password?)
     (count))

Stuart14:12:31

I like your solution for part2!

erwinrooijakkers14:12:56

🙂 i did same as yours initially but then realized clojure had no xor

pez09:12:53

Has someone figured out a way to slurp the input data directly from the site? I’m lazy, so if someone has this solved in a nice module, I’d love to have it. 😃 I’m also not lazy, so if this is not done by someone, I might try to do it, if someone here does not tell me it is probably very hard. And I’m the sharing type. Haha.

erwinrooijakkers09:12:55

There is some Python program somewhere

erwinrooijakkers09:12:45

aocd > input.txt  # saves today's data
aocd 13 2018 > day13.txt  # save some other day's data

pez09:12:50

If I end up rolling this, I’ll have use for that to see what is involved.

zackteo09:12:02

Was attempting to do so yesterday, then I realised authentication is required

plexus10:12:16

lazy way I think would be doing it first from the browser, "copy as cURL" so that it has your cookie headers in there, then you can adjust that curl line to download the other ones as long as your session remains valid

erwinrooijakkers10:12:50

In the Python aocd tool you can add the value of the session cookie in the AOC_SESSION env var or ~/.config/aocd/token file

nam.hyunwoo10:12:37

Wow as always it’s fascinating to watch Clojurians solution in this channel. This year I’m using ReasonML(family of OCaml) since my company has chosen it. https://github.com/namenu/advent-of-reason/blob/master/src/Year2020/Year2020_Day01.res Yes, it’s typed, I miss Clojure so badly.

👍 1
erwinrooijakkers10:12:50

I remember a talk from Clojure Vienna 2016 on ReasonML’s Unikernels and also transforming Clojure to ReasonML: https://youtu.be/tB705w4w6H0

clj 1
nam.hyunwoo10:12:13

Wow thats... cursed

erwinrooijakkers10:12:01

Was pretty interesting stuff. Booting up a unikernel faster than the time it takes to do a TCP handshake

erwinrooijakkers10:12:16

Not sure what the status is of it now

erwinrooijakkers15:12:26

aah I see it’s still Reason 🙂

erwinrooijakkers15:12:49

looks pretty clean

nam.hyunwoo01:12:25

oh yes I merged the ReasonML repo with Clojure's to contrast them

nam.hyunwoo01:12:37

I found ML language interesting in a way that more lengthy code makes a program safer, because compiler is very very smart. In my experience, this wasn't true in Clojure. I always prefer brevity in my code, because more code means more bugs!

nam.hyunwoo01:12:20

I use ReasonML and Clojure both for living, and they are both great in very different ways

erwinrooijakkers10:12:00

Maybe a program can login via the GitHub SSH key so that you don’t need the session

❤️ 1
erwinrooijakkers10:12:08

If you use GitHub to login

erwinrooijakkers10:12:53

Not sure if that’s possible

plexus11:12:49

just need to find the session id with devtools and put a export AOC_SESSION=... in your shell profile

drowsy11:12:44

And in the same way, it's also pretty easy to get the input via clojure (I just store the session in a file) https://github.com/IamDrowsy/aoc-2020/blob/581097350d2dc7865304ffc9eddaf6a479406ca1/clojure/src/advent_of_code/util.clj#L9:L13

pez17:12:35

Neat! Found this a bit late, but I did exactly that. 😃

pez17:12:39

Decided to go the easy path that @plexus pointed out. Copy as cURL from the problem page when I start reading it-> Grab the session cookie there -> (set-fetch-cookie! "<cookie>") -> Hack away until I need the input -> (util/fetch-input <day>)

(ns pez.aoc2020.util
  (:require [clj-http.client :as client]))

(def ^:dynamic *fetch-cookie* "")

(defn set-fetch-cookie! [cookie]
  (alter-var-root #'*fetch-cookie* (constantly cookie)))

(defn fetch-input [day]
  (if (seq *fetch-cookie*)
    (try
      (:body (client/get
              (str "" day "/input")
              {:cookies {"session" {:value *fetch-cookie*}}}))
      (catch Exception e
        (println "Ho, ho, ho! Did you forget to `set-fetch-cookie!`?")
        (throw e)))
    (throw (Exception. "Ho, ho, ho! You forgot to `set-fetch-cookie!` first."))))
Like so:
(comment
  (def input
    "1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc")
  (util/set-fetch-cookie! "retracted")
  (def input (util/fetch-input 2))
  (->> input
       (parse)
       (filter checks2?)
       (map :pwd)
       (count)))
Not sure how long the cookie lives, but it should live long enough even for my slow solution pace. And if not, accept that I suck and grab a new session cookie. I’ll see in 11 hours and 47 minutes how much I like this workflow. 😃

drowsy17:12:28

Last year the session never changed.

nbardiuk17:12:39

I've just checked that cookie expiration is set for 10 years 😁

pez17:12:42

Even I should be able to solve the puzzles in that time!

spfeiffer17:12:38

I am stuck in 2016 somewhere, not sure 10 years will cut it for me 😉

kenj18:12:17

my also not fancy day 2… I like how declarative it came out looking https://gist.github.com/KennyMonster/eb6ea22eaba1a1a1201820ef1bddc1cf

👍 2
Jeff Evans20:12:12

this is probably more a #beginners question, but figured I’d ask here since it’s related to the Advent of Code stuff I’m trying why isn’t this working? I copied problem 1's input file to a file called input in resources (in a Leinengen app template project)

(slurp (io/resource "input"))
when run via lein exec my_script.clj, I get java.lang.IllegalArgumentException: Cannot open <nil> as a Reader. however, doing the exact same thing in lein repl works fine

nbardiuk20:12:58

I don't use the exec plugin, but looks like it has -p flag that runs the script in project CLASSPATH, wich is required to resolve the resources

nbardiuk20:12:37

https://github.com/kumarshantanu/lein-exec

-p  indicates the script should be evaluated in project (with classpath)

Jeff Evans20:12:41

thank you! that was it

kpav20:12:14

ha, funny seeing you here @U0183EZCD0D

😀 1
Jeff Evans20:12:40

trying to get my day1 and day2 solutions finished and pushed

kpav20:12:44

I am learning clojure too, trying to do AOC with it

Jeff Evans20:12:58

sweet! let’s keep each other accountable

🙌 1
kpav20:12:46

Ive got my solutions here, finished day 1 and 2! https://github.com/kwpav/advent-of-code-2020

Jeff Evans22:12:14

nice! I’m a bit behind, only got day 1 done so far: https://github.com/jeff303/advent-of-code-2020

Jeff Evans22:12:21

gonna try to finish day 2 before I look at yours

kpav22:12:36

day 2 was fun

Jeff Evans22:12:04

yeah, almost seems easier, especially with Clojure. though I’m sure part 2 will throw some kind of wrench into it