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
2020-12-16T02:28:25.302400Z

In this aspect, it's like for vs map

st3fan 2020-12-16T02:36:18.303100Z

I got Day 15 Part 2 down to 450ms

st3fan 2020-12-16T02:36:54.303300Z

Rewrote it in C πŸ˜‰

st3fan 2020-12-16T02:37:08.303600Z

Will do a similar solution in Clojure though

fingertoe 2020-12-16T03:27:23.303700Z

I got you beat at 33 seconds. πŸ˜‰. My original solution was going to take a couple days, I think.. repeatedly (count seq) and (drop last) are horrible. I improved it to terrible, but functional..

2020-12-16T06:29:06.307800Z

Day 16 answers thread - Post your answers here

2020-12-16T08:08:45.312500Z

Not long, but a bit dirty solution. Will try to refact it after work. https://github.com/zelark/AoC-2020/blob/master/src/zelark/aoc_2020/day_16.clj

πŸ‘ 2
nbardiuk 2020-12-16T09:29:33.313300Z

I am glad that today's problem does not require some fancy dynamic programming algorithm https://github.com/nbardiuk/adventofcode/blob/master/2020/src/day16.clj

πŸ‘ 2
genmeblog 2020-12-16T11:33:24.315700Z

True, but was much complicated than I thought at the beginning... https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2020/day16.clj

πŸ‘ 2
benoit 2020-12-16T14:04:40.316800Z

Nothing very exciting to see here πŸ™‚ https://github.com/benfle/advent-of-code-2020/blob/main/day16.clj

πŸ‘ 2
benoit 2020-12-16T14:05:37.317200Z

Maybe the only interesting bit is to sort the candidates for part2 so you can solve the problem in one pass in a reduce.

πŸ‘ 2
Joe 2020-12-16T14:46:08.322700Z

https://github.com/RedPenguin101/aoc2020/blob/main/day16.clj- I'm pretty happy with my implementation for once. Short, fast(ish) and a comprehensible api. I especially like the narrow-down function here, I thought that was going to much more difficult than it turned out to be.

πŸ‘ 2
Joe 2020-12-16T14:47:26.323200Z

Really fun puzzle too, I like this sort of thing much more than implementing efficient algorithms or fiddling with bits πŸ˜‘

misha 2020-12-16T15:02:00.324800Z

@me1740 how is sorting = one pass? :kappa:

erwinrooijakkers 2020-12-16T16:21:29.325200Z

I overlooked Now that you've identified which tickets contain invalid values, _discard those tickets entirely_

erwinrooijakkers 2020-12-16T16:22:10.325400Z

And it was bit more difficult than I thought (could not discard the non β€œdeparture” entries)

erwinrooijakkers 2020-12-16T16:22:47.326300Z

Anyway, https://github.com/transducer/adventofcode/blob/master/src/adventofcode/2020/day16.clj

πŸ‘ 1
benoit 2020-12-16T17:04:09.327200Z

@misha sort by the number of candidates for each position. The first position will only have one candidate. The second will have two candidates, the one already picked in (1) + a new one which is the solution...

2020-12-16T17:46:33.327500Z

Hi, here is my solution, it runs in 30 msecs on my old computer. https://github.com/green-coder/advent-of-code-2020/blob/master/src/aoc/day_16.clj

πŸš€ 3
euccastro 2020-12-16T18:06:33.328Z

@benoit is that guaranteed, or did it just happen to be true for the challenge input?

euccastro 2020-12-16T18:07:08.328200Z

I imagine you could have several positions with the same number of candidates, and not the first one would resolve first?

βž• 1
euccastro 2020-12-16T18:08:31.328500Z

my solution just does brute force since it works ~instantly anyway. I didn't clean it up, sorry:

(ns advent.day16
  (:require [clojure.string :as str]
            [<http://clojure.java.io|clojure.java.io> :as io]))


(def demo-input "class: 1-3 or 5-7
row: 6-11 or 33-44
seat: 13-40 or 45-50

your ticket:
7,1,14

nearby tickets:
7,3,47
40,4,50
55,2,20
38,6,12")


(defn parse-long [x]
  (Long/parseLong x))


(defn extents [input]
  (for [[_ &amp; extents]
        (re-seq #"(\d+)-(\d+)" input)]
    (mapv parse-long extents)))


(defn nearby-tickets [input]
  (-&gt; input
      (str/split #"nearby tickets:\n")
      second
      (str/split #"\R")
      (-&gt;&gt; (map #(str/split % #","))
           (map #(mapv parse-long %)))))


(defn nearby-ticket-numbers [input]
  (flatten (nearby-tickets input)))


(defn valid-number? [n extents]
  (first (for [[begin end] extents
               :when (&lt;= begin n end)]
           n)))


(defn invalid-numbers [input]
  (let [extents (extents input)]
    (remove #(valid-number? % extents) (nearby-ticket-numbers input))))


(defn solution [input]
  (apply + (invalid-numbers input)))


(solution demo-input)
;; =&gt; 71


(def real-input (slurp (io/resource "input16")))


(solution real-input)
;; =&gt; 21978

;; part 2


(defn attr-extents [input]
  (for [[_ attr &amp; extents]
        (re-seq #"(\w+\s*\w*):\s+(\d+)-(\d+)\s+or\s+(\d+)-(\d+)" input)]
    (apply vector attr (map parse-long extents))))

(comment

  (attr-extents demo-input)

  )

(defn valid-ticket? [numbers extents]
  (every? #(valid-number? % extents) numbers))


(defn valid-nearby-tickets [input]
  (let [extents (extents input)]
    (filter #(valid-ticket? % extents) (nearby-tickets input))))


(comment
  (def valid-tickets* (valid-nearby-tickets demo-input (extents demo-input)))
  (def attr-extents* (attr-extents demo-input))
  (def num-positions (count (first valid-tickets*)))
  )


(defn attr-matches-position? [[_ begin1 end1 begin2 end2] position tickets]
  (every?
   #(or (&lt;= begin1 % end1) (&lt;= begin2 % end2))
   (map #(nth % position) tickets)))


(defn initial-state [aexts tickets]
  (vec
   (for [pos (range (count aexts))]
     (set (keep
           (fn [[attr :as attr-ext]]
             (when (attr-matches-position?
                    attr-ext
                    pos
                    tickets)
               attr))
           aexts)))))


(defn resolve-positions [initial-state]
  (let [num-positions (count initial-state)]
    (loop [state initial-state]
      (let [resolved (map
                      first
                      (filter #(= (count %) 1)
                              state))
            resolved-set (set resolved)]
        (if (= (count resolved) num-positions)
          resolved
          (recur
           (map
            (fn [x]
              (if (= (count x) 1)
                x
                (remove resolved-set x)))
            state)))))))


(def resolved
  (resolve-positions
   (initial-state
    (attr-extents real-input)
    (valid-nearby-tickets real-input))))


(defn my-ticket [input]
  (-&gt; input
      (str/split #"ticket")
      second
      (-&gt;&gt; (re-seq #"\d+")
           (map parse-long))))

(def m (zipmap resolved (my-ticket real-input)))


(apply * (vals (select-keys m (filter #(str/starts-with? % "departure") (keys m)))))
;; =&gt; 105368685

πŸ‘ 1
euccastro 2020-12-16T18:08:42.328700Z

names and factoring are very questionable, sorry

euccastro 2020-12-16T18:11:32.329Z

btw this is the first day I actually worked through the problem myself. so far I've just binge-watching @plexus's recorded videos (haven't caught up yet)

pez 2020-12-16T18:15:22.330Z

Step 1 done. Turns out my solution is not as applicable to step 2 as things were yesterday πŸ˜ƒ

(-&gt;&gt; input
       (parse)
       ((fn [notes]
          (let [valid? (reduce (fn [acc rule]
                                 (-&gt;&gt; (:ranges rule)
                                      (map (fn [[start end]]
                                             (into #{} (range start (inc end)))))
                                      (apply (partial clojure.set/union acc))))
                               #{}
                               (:rules notes))]
            (filter (complement valid?) (apply concat (:nearby notes))))))
       (apply +))

😁 5
2020-12-16T18:45:22.331800Z

I am up to date with the puzzles ^_^

πŸŽ‰ 2
markw 2020-12-16T19:57:15.333600Z

Will probably try to do some cleanup, time permitting: https://github.com/Solaxun/aoc2020_clj/blob/main/src/aoc2020_clj/day16.clj

erwinrooijakkers 2020-12-16T20:29:33.333900Z

How do I turn this into valid core.logic?

(run* [q]
  (fresh [i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20]
    (logic/== q [i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20])
    (fd/in i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 (fd/interval 0 21))
    (logic/membero i0 #{1 2 3 5 6 8 10 11 14})
    (logic/membero i1 #{0 1 2 3 4 5 6 8 10 11 14 15})
    (logic/membero i2 #{0 1 2 3 4 5 6 7 8 10 11 14 15 18 19})
    (logic/membero i3 #{1 2 3 4 5 6 8 10 11 14})
    (logic/membero i4 #{0 1 2 3 4 5 6 8 10 11 14})
    (logic/membero i5 #{6 8 10 11})
    (logic/membero i6 #{6 8 11})
    (logic/membero i7 #{1 5 6 8 10 11 14})
    (logic/membero i8 #{6 8 10 11 14})
    (logic/membero i10 #{1 2 5 6 8 10 11 14})
    (logic/membero i11 #{6 8})
    (logic/membero i12 #{1 6 8 10 11 14})
    (logic/membero i13 #{8})
    (logic/membero i14 #{0 1 2 3 4 5 6 7 8 9 10 11 12 14 15 16 17 18 19})
    (logic/membero i15 #{0 1 2 3 4 5 6 7 8 10 11 14 15 17 18 19})
    (logic/membero i16 #{0 1 2 3 4 5 6 7 8 10 11 14 15 16 17 18 19})
    (logic/membero i17 #{0 1 2 3 4 5 6 7 8 10 11 12 14 15 16 17 18 19})
    (logic/membero i18 #{0 1 2 3 4 5 6 8 10 11 14 15 19})
    (logic/membero i19 #{0 1 2 3 4 5 6 8 10 11 14 15 18 19})
    (logic/membero i20 #{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19})))

;=&gt; ()...

erwinrooijakkers 2020-12-16T20:29:55.334100Z

This does not make sense

erwinrooijakkers 2020-12-16T20:31:15.334400Z

I’ll ask in core.logic

peterc 2020-12-16T21:44:47.334700Z

@euccastro @me1740 I also did the sort approach as I did it for speed. 1. Inspect the results after you removed the invalid fields for each position. There are some clues that a relatively "simple" solution can be used. 2. Next, sort the valid fields by count and do a set difference between each element to see that there is indeed a unique solution. Obviously a solution is not guaranteed, but step two is quick to test.

πŸ‘ 2
rjray 2020-12-16T06:57:37.308Z

Long solution. I also plan to try to improve it. Tomorrow. https://github.com/rjray/advent-2020-clojure/blob/master/src/advent_of_code/day16.clj

πŸ‘ 1
πŸŽ‰ 2
misha 2020-12-16T09:21:49.313Z

chief loop officer

πŸ˜ƒ 2
misha 2020-12-16T09:26:09.313100Z

(let [[rules mine other] (parse i)
      valid?     (-&gt;&gt; rules vals (reduce into #{}))
      valid      (-&gt;&gt; other
                   (remove #(seq (remove valid? %)))
                   (map vec))
      transposed (apply map vector valid)
      candidates (fn [pred]
                   (-&gt;&gt; transposed
                     (map-indexed
                       (fn [idx col]
                         (when (every? pred col)
                           idx)))
                     (remove nil?)))
      labels     (loop [done {}
                        todo (-&gt;&gt; rules
                               (map-vals candidates)
                               (sort-by #(-&gt; % val count) &lt;)
                               (into PersistentQueue/EMPTY))]
                   (if (empty? todo)
                     done
                     (let [[label cols] (peek todo)
                           todo (pop todo)
                           cols (remove done cols)]
                       (if (-&gt; cols count (= 1))
                         (recur (assoc done (first cols) label) todo)
                         (recur done (conj todo [label cols]))))))]
  (-&gt;&gt; labels
    (filter #(-&gt; % val (str/starts-with? "departure")))
    (map key)
    (map mine)
    (reduce *)))

πŸ‘ 1
misha 2020-12-16T09:38:11.314500Z

ofc it would loop forever, if at some point every unmapped label had more than 1 candidate idx. that'd be job for core.logic

βž• 2
mdallastella 2020-12-16T14:25:46.319300Z

Namaste. I have a "philosophical" question about the first problem of day 1. I saw solutions like this around the internet:

(for [x input y input :when (= 2020 (+ x y))]
  (* x y))

mdallastella 2020-12-16T14:27:08.320600Z

but what if my input list is (1010 <tel:17212991465|1721 299 1465>)? Isn't going to stop on the first element?

2020-12-16T14:27:51.320700Z

That's probably true

2020-12-16T14:28:04.320900Z

Another check to make sure the numbers are not the same is enough

2020-12-16T14:29:08.321100Z

But apparently it wasn't necessary given the input data

mdallastella 2020-12-16T14:30:17.321300Z

I agree, but given the statement: > Specifically, they need you toΒ find the two entries that sum toΒ `2020`Β and then multiply those two numbers together.

mdallastella 2020-12-16T14:30:35.321500Z

They won't be two entries, but one

mdallastella 2020-12-16T14:31:21.321700Z

Anyway checking that are different can be enough

mdallastella 2020-12-16T14:32:25.321900Z

but if I have, let's say (1010 <tel:17212991010|1721 299 1010>) the elements are two

mdallastella 2020-12-16T14:33:25.322100Z

Maybe I'm a little pedantic...

2020-12-16T14:46:50.323Z

hehe well I think noone cares about the perfect solution as long as it works and it's fast enough πŸ˜„

πŸ‘ 1
πŸ˜… 1
misha 2020-12-16T14:52:52.323400Z

you can compare indexes instead of actual numbers in case you want to be pedantic

(let [input [1010 1721 299 1465]]
  (for [[a x] (map-indexed vector input)
        [b y] (map-indexed vector input)
        :when (= 2020 (+ x y))
        :when (not= a b)]
    (* x y)))
=&gt; (514579 514579)

1
misha 2020-12-16T15:00:53.324400Z

but then :when (&lt; a b) is even better

erwinrooijakkers 2020-12-16T18:14:22.329200Z

ah indeed

erwinrooijakkers 2020-12-16T18:14:24.329400Z

smart

erwinrooijakkers 2020-12-16T18:14:31.329600Z

did not think about core.logic but this is core.logic

2020-12-16T18:39:24.331500Z

Day 17 answers thread - Post your answers here

peterc 2020-12-17T08:08:17.345200Z

Ooops my mistake, I meant @@zelark :X

πŸ˜… 1
nbardiuk 2020-12-17T08:58:37.346700Z

@zelark I love the frequences approach, it improved my slow implementation from 5s to 450ms

misha 2020-12-17T09:31:09.348Z

9 seconds, and I don't care :d:

3
nbardiuk 2020-12-17T10:01:22.348300Z

@misha sometimes it is harder to "let it go"

misha 2020-12-17T10:08:15.348500Z

not after ~day15 usually

benoit 2020-12-17T13:35:46.353Z

Representing the pocket dimensions as a set of active cubes. Looks similar to others here. https://github.com/benfle/advent-of-code-2020/blob/main/day17.clj

πŸ‘ 3
benoit 2020-12-17T13:36:43.353400Z

Of course I had to rewrite the function that compute the neighbor coordinates for part2 to support an arbitrary number of dimensions πŸ™‚

2020-12-17T13:40:19.353700Z

https://github.com/benfle/advent-of-code-2020/blob/main/day17.clj#L55-L60 could also be written like (-&gt;&gt; (all-neighbor-coordinates state) (filter (partial next-cube-active? state)) set)

2020-12-17T13:47:05.354400Z

There is also the transducer way which should run faster: (into #{} (filter (partial next-cube-active? state)) (all-neighbor-coordinates state))

benoit 2020-12-17T13:47:55.354600Z

Thanks, done.

benoit 2020-12-17T13:49:46.354800Z

That would be cool if my IDE could detect this kind of semantic-preserving transformations and automatically propose them :)

βž• 1
2020-12-17T13:50:34.355Z

Which IDE are you using? Is it open source?

benoit 2020-12-17T14:07:32.355400Z

emacs, I believe it is open source lol

2020-12-17T14:09:58.355600Z

It could eventually be in https://github.com/borkdude/clj-kondo/blob/master/doc/editor-integration.md#emacs

2020-12-17T14:13:28.356200Z

near the goal ... https://github.com/borkdude/clj-kondo/issues/323

benoit 2020-12-17T14:19:48.356600Z

Yeah I would certainly leverage things in clj-kondo πŸ™‚ But I'm not a fan of the overall approach of linters. This should be a la carte and an assistant to help you navigate the design space. Not a collection of rules that you must respect or be warned about.

Joe 2020-12-17T16:03:52.366500Z

https://github.com/RedPenguin101/aoc2020/blob/main/day17.clj - Fun! About 500ms for Part 2

πŸ‘ 3
euccastro 2020-12-18T03:13:06.384500Z

nice! nit: (apply concat (map neighbors coords)) could be just (mapcat neighbors coords)

markw 2020-12-18T04:26:37.386Z

better late than never: https://github.com/Solaxun/aoc2020_clj/blob/main/src/aoc2020_clj/day17.clj

πŸ‘ 1
2020-12-16T18:49:20.333Z

@vincent.cantin I see you’re back in the game, that’s great!

2
βž• 3