Fork me on GitHub
#adventofcode
<
2019-12-04
>
fingertoe00:12:56

Wasted a lot of time on silly misplaced parens error on this one. 😉 https://github.com/jreighley/aoc2019/blob/master/src/aoc/aoc3.clj

Average-user00:12:29

Have you tried parinfer or parindent?

fingertoe01:12:36

I use cursive and parinfer. It was my distance function that added the absolute values of the two vectors. Since it was all on the same line, it didn’t help

(+ (abs x)) (abs y)
instead of
(+ (abs x) (abs y))
The function was returning the correct number on the y deltas but 0 on the x deltas…

mpcjanssen02:12:37

@erwinrooijakkers nice tip, using peek instead of last shaved 500ms of the 7s.

norman03:12:16

I'm getting a late start. Are we using the same leaderboard as last year?

norman03:12:49

(or I could just look at channel topic, I suppose)

dpsutton03:12:51

I haven’t seen the same style this year @norman

kenj03:12:48

Only made it through part 1 of day 3 while slacking at work towards the end of the day… no one noticed the Clojure instead of Python on my screen 🤷 https://github.com/KennyMonster/aoc_2019/blob/c2dfdfffdc4447c34aa6a7c90b0a763d10da8713/src/day_3.clj

fellshard03:12:53

There's some days when I've needed a break to do some real programming and get my brain moving again before going back to 'real work'. So long as it hasn't cut into the hours I'm contracted to bill, anyway. 🙂

namenu06:12:07

same here. puzzles are being opened amid of my work time 🤫

mchampine05:12:16

Puzzle 4 was way easier than the last two. I count 8 lines of code for Part 1, with a single line altered to adapt the part 1 solution to part 2.

mchampine06:12:56

Actually, just a single character change for part 2. I have a test for repeated digits that looks like this: (some #(<= 2 (count %)) (partition-by identity (str n)) For part 2, just changing the “<=” to “=” was sufficient.

mpcjanssen06:12:45

i used frequency on the list of digits

yuhan06:12:32

Still find it awesome how lisps allow you to do things like #((case part 1 <= 2 =) 2 (count %))

mchampine06:12:16

@mpcjanssen ?? You mean frequencies? But that doesn’t care about order, so I don’t see how it would detect sequential duplicates differently than non-sequential ones..

mpcjanssen06:12:05

@mchampine you are right. it did give the right answer though

mpcjanssen06:12:43

no because the digits are increasing

mpcjanssen06:12:56

so any same digits are consecutive

mchampine06:12:57

Ahh.. got it.

mpcjanssen06:12:28

rationalisation after the fact 🙂

mpcjanssen06:12:50

did not completely think this through before

lilactown06:12:59

yes the duplicate check can be pretty dumb if you take advantage of that

lilactown06:12:25

I still used dedupe though for part 1

herald09:12:09

#(apply <= (digits %))
Damn, so simple!

yenda11:12:17

why do you divide by 10000 though I don't get it why not something like (<= 100000 x 999999)

yenda11:12:21

or (= 6 (count (str digits)))

lilactown15:12:46

the first one would probably have been better, yeah

lilactown15:12:10

I wanted to avoid converting to a string if possible

mchampine06:12:51

Wow, using spec. Neat. Btw, you can do a quick and dirty digits conversion with (map read-string (map str (str 123456)))

mpcjanssen06:12:55

also nice literal coding with org-babel

mpcjanssen06:12:35

the environments are as interesting as the code itself

👍 4
mchampine07:12:14

Yes, tried org-babel a while back. Pretty great stuff you can do. I was mixing bash, python, clojure, and LaTeX as I recall.

karlis08:12:53

apart from the somewhat vague description for puzzle #2, today was quick & easy: https://github.com/skazhy/advent/blob/master/src/advent/2019/day4.clj

genmeblog10:12:05

Oh, this is so great solution. Clever. I overcomplicated a thing this time.

mpcjanssen11:12:38

Smart regex for increasing

Roman Liutikov12:12:25

regex turned out to be much faster than parsing and comparing digits

misha14:12:47

I did (= (seq s) (sort-by identity compare s))) 10 times slower than regex

Roman Liutikov10:12:18

@karlis indeed, it took me a while to decypher description of the 2nd part

☝️ 4
👍 4
karlis10:12:24

neat use of frequencies! That's a method I only seem to use during advent of code 😄

Charles Fourdrignier11:12:41

Try a first time with "filter wrong values", but my predicates were pretty bad, so my evaluation "never" finishes. I re-write it in a dirty (but successful) way. https://github.com/Charlynux/advent-of-code-2019/blob/master/day04/day04.clj

taylor13:12:09

I think each year there are a few problems like day 4 pt. 2 that seem almost intentionally vague… https://github.com/taylorwood/advent-of-code/blob/master/src/advent_of_code/2019/4.clj

👍 4
tschady16:12:16

bug in num-to-digits for 0.

user=> (num-to-digits 0)
[]

James Adam16:12:40

It doesn't like it when the first digit is 0

jrwdunham15:12:36

@taylor nice digits func to convert an int to a seq of digits without string manipulations. I would have never thought to do it that way

4
taylor18:12:31

the only other place I’ve ever used this is in coding interviews lol

James Adam15:12:59

@jrwdunham my solution initially used string manipulation, I got about 10x speedup when I cut out all of the type conversions 🙂

misha16:12:44

(time
  (let [MIN      382345
        MAX      843167
        int-vec  (fn [n] (->> n str (map str) (mapv #(Integer/parseInt % 10))))
        low      (int-vec MIN)
        high     (int-vec MAX)
        too-low  #(neg? (compare % low))
        in-range #(neg? (compare % high))
        pwds     (for [a (range 0 10)
                       b (range a 10)
                       c (range b 10)
                       d (range c 10)
                       e (range d 10)
                       f (range e 10)
                       :let [n [a b c d e f]]
                       :when (->> n frequencies vals (some #{2}))]
                   n)]
       (->> pwds
         (drop-while too-low)
         (take-while in-range)
         (count))))
"Elapsed time: 13.145288 msecs"
=> 290

😍 4
misha16:12:26

James'es times on my input and laptop are: "Elapsed time: 159.510294 msecs" "Elapsed time: 324.308817 msecs"

misha16:12:07

roman's times: "Elapsed time: 227.731395 msecs" "Elapsed time: 172.91049 msecs"

Mario C.16:12:37

Day 4 part 2 was written very poorly.

☝️ 4
herald16:12:41

very cool. using for like that to avoid the intermediate numbers

Mario C.16:12:51

Not too fond of the 10 mins wait after submitting x number of wrong answers

misha16:12:11

btw, I understood part 2 immediately by looking at examples, don't know why so many were confused. (however, there were few similar requirements in previous years' puzzles, so I might have just recognized it)

taylor18:12:40

I had a solution that worked for all the examples but not for my test input; took me like 6 submissions to get it right

herald16:12:18

same here. although I tend to jam the examples into my tests before I think too much over the problem description

Mario C.16:12:29

I thought I did too until my answers were wrong

Mario C.16:12:54

222222 should or shouldn't be valid?

herald16:12:03

maybe you're unlucky and got input data with an extra edge case

Mario C.16:12:15

repeating 2 and its not apart of a larger group

Mario C.16:12:20

its the only group

herald16:12:41

oh no, now I'm confused. it should be

herald16:12:04

there must exist at least one consecutive group with a length of 2+

herald16:12:54

^ this is part 1. part 2 is exactly 2 instead of 2+

misha16:12:15

also this is why I did not use frequencies initially, because I recalled "2 but not 3+ in a row", and thought of letters, and did not figure out that there can only be 1 streak per digit, and can't be e.g. 11xx1x.

misha16:12:39

I think it should not, because it is more than 2 in a row

misha16:12:21

@regen "at least one 2+" for part1, "at least one exactly 2" for part 2

Mario C.16:12:32

Should 123455 work?

misha16:12:49

yes, for both

misha16:12:10

*unless outside the range

Mario C.16:12:14

But isn't the 55 part a larger group of repeating?

misha16:12:31

group is just same digit several times in a row

Mario C.16:12:37

same reason 123444 didn't count

misha16:12:54

444 is a group of 3: three 4 s in a row

misha16:12:27

consecutively

misha16:12:21

(partition-by identity coll) gives you groups : (partition-by identity "123444") => ((\1) (\2) (\3) (\4 \4 \4))

Mario C.16:12:28

Thats not how I understood it. Which was my complaint since it was left up to interpretation

Mario C.16:12:38

I figured 333444 should work

Mario C.16:12:57

since the 33 or 44 are not part of a larger group

Mario C.16:12:36

but you are making the case that it wont work since they are both groups of 3

misha16:12:06

group of 2 is two of the same digits in a row. larger group is tree or more of the same digit in a row

misha16:12:14

I am, yes. 333444 should be invalid

misha16:12:47

because it has 2 groups of size 3 each,

Mario C.16:12:39

the two adjacent matching digits are not part of a larger group of matching digits.I understood this as: As long the repeating digit is not part of the largest group of all groups then it is valid.

Mario C.16:12:53

So 122333 is valid and so would 222333

Mario C.16:12:11

but not 123444 since the repeating digit is part of the larger group

misha16:12:23

yes. here, 33____ and 33__ are two adjacent matching digits but both are part of a larger group of matching digits 333___

misha16:12:37

same for 44_ and _44 in 444

genmeblog16:12:44

122333 is valid because has 22.

Mario C.16:12:39

222333 has two groups. Each of size 3 meaning there is no larger group. Since they are both the same

misha16:12:55

122333 is valid, because there is only 2 2 in a row, 222333 in invalid, because there is 3 2 in a row

genmeblog16:12:00

No, there are two larger groups.

misha16:12:24

. (map count (partition-by identity "122333")) => (1 2 3) ;; has group of exactly 2 numbers (map count (partition-by identity "222333")) => (3 3) ;; does not have group of exactly 2 numbers

Mario C.16:12:19

There we go. They should have just written that ^

Mario C.16:12:30

> does not have group of exactly 2 numbers

misha16:12:59

this is why people here bragged about "part 2 was just 1 char diff commit!": (->> ... (some #(<= 2 %))) for part 1 and (->> ... (some #(= 2 %))) for part 2

Mario C.17:12:09

Not for me. I kept thinking "Oh I get it now." Type the answer in and getting "Sorry wrong answer. Plz wait 10 mins before submitting again."

Mario C.17:12:36

But wasn't going to bed until I got the goldie

Mario C.17:12:51

first part was easy though

misha17:12:16

happened a lot to me in other puzzles. It is not in the aoc interests to make it obvious to you what needs to be done, hence lots of text, indirection in terminology, random bold font highlights, "by the ways", ambiguous examples

jrwdunham17:12:34

I wrote a crazy regex to get dec4/pt2 which i'm sharing for laughs. (Liking the concise and sane strategies I'm seeing here):

jrwdunham17:12:36

(def pattern
  (re-pattern
   (str
    "("
    "(^|[^1])11($|[^1])"
    "|"
    "(^|[^2])22($|[^2])"
    "|"
    "(^|[^3])33($|[^3])"
    "|"
    "(^|[^4])44($|[^4])"
    "|"
    "(^|[^5])55($|[^5])"
    "|"
    "(^|[^6])66($|[^6])"
    "|"
    "(^|[^7])77($|[^7])"
    "|"
    "(^|[^8])88($|[^8])"
    "|"
    "(^|[^9])99($|[^9])"
    "|"
    "(^|[^0])00($|[^0])"
    ")")))

😅 8
fingertoe21:12:41

I always feel like I am cheating when I use regex. That never stops me from being tempted. (Including today)

misha17:12:27

zeroes are invalid here opieop

jrwdunham17:12:42

right. still works though.

misha17:12:59

because you filter them out earlier/later

jrwdunham17:12:11

filter them out earlier, with yet another regex

jrwdunham17:12:27

(filter (fn [d] (re-find #"(.)\1" d)))

jrwdunham17:12:51

oh, nevermind, that doesn't do it...

misha17:12:13

I'd like to see concise pattern including all of it: range, group size, ascendingness

Average-user17:12:10

adventofcode-clj-2019.day04> (time (part-1)) "Elapsed time: 19.688852 msecs" 1605 adventofcode-clj-2019.day04> (time (part-2)) "Elapsed time: 23.650609 msecs" 1102

misha17:12:13

slower and less readable kappa

Average-user17:12:01

Yep, i didn't thought about using for. But my solution is more general (not only for six digit length numbers)

Average-user17:12:12

And is only slightly slower

misha17:12:55

of course! hence the trollface in my snippet )

🙂 4
yuhan17:12:40

@misha I did a similar optimization to only iterate through non-decreasing digit-vectors 🙂

(defn incr [ds]
  (let [d (peek ds)]
    (if (= 9 d) ;; recursive
      (let [ds* (incr (pop ds))]
        (conj ds* (peek ds*))) ;; roll over using prev digit
      (conj (pop ds) (inc d)))))

(iterate incr [1 4 6 8])
;; => ([1 4 6 8]
;;     [1 4 6 9]
;;     [1 4 7 7]
;;     [1 4 7 8]
;;     [1 4 7 9]
;;     [1 4 8 8]
;;     [1 4 8 9]
;;     [1 4 9 9]
;;     [1 5 5 5]
;;     [1 5 5 6]
;;     ...)

Average-user17:12:10

adventofcode-clj-2019.day04> (time (part-1)) "Elapsed time: 19.688852 msecs" 1605 adventofcode-clj-2019.day04> (time (part-2)) "Elapsed time: 23.650609 msecs" 1102

misha17:12:25

yeah, but anything in user space is likely to be slower than for opieop

yuhan17:12:51

I replaced the nested for clauses in your solution with (for [n (iterate incr [0 0 0 0 0 0]]) and got a 13.5 msec => 9.0 msec speed up

misha17:12:49

what is incr? inc?

yuhan17:12:17

the recursive function I posted above

yuhan17:12:22

(not great at naming things)

misha17:12:30

is it consistent speed up? do you consistently get 13ms on my snippet? for me it fluctuates +-2ms

misha17:12:03

or did you just compare 9ms on your machine to 13 on mine? troll different code too!

yuhan17:12:31

Both on my machine with the same inputs

jrwdunham17:12:18

@misha my un-aptly named monotonically-increasing? filter seems to be correctly filtering out the 0s

misha17:12:30

I pointed that out so you could speed up regex

jrwdunham17:12:02

i see. See any way to make the regex more concise, with backreferences and lookahead/behind fanciness?

misha17:12:07

not even gonna try d

jrwdunham17:12:42

Yes, also not fast: part 1: Elapsed time: 485.806268 msecs; part 2: Elapsed time: 578.42914 msecs.

jrwdunham17:12:40

taking out the 0s disjunct in the regex speeds things up by 50-100ms

🏎️ 4
Roman Liutikov17:12:11

For speed AND idiomatic code it's probably better to do it in Rust

misha17:12:08

for is idiomatic :)

yuhan17:12:39

got it down to 3.6 ms using transducers 🙂 (measured using Criterium's quick-bench)

yuhan17:12:46

(defn day4
  [start end part]
  (let [dv     (fn [n] (mapv #(Character/getNumericValue %) (str n)))
        dv<    (fn [a b] (= -1 (compare a b)))
        startv (dv start)
        endv   (dv end)
        incr   (fn [ds] ;; increase digit vector until it satisfies non-decreasing condition
                 (let [d (peek ds)]
                   (if (= d 9) ;; recursive
                     (let [ds* (incr (pop ds))]
                       (conj ds* (peek ds*))) ;; roll over using prev digit
                     (conj (pop ds) (inc d)))))
        pw?    (fn [xs]
                 (some #((case part 1 <=, 2 =) 2 (count %))
                   (partition-by identity xs)))]
    (transduce
      (comp
        (drop-while #(dv< % startv))
        (take-while #(dv< % endv))
        (filter pw?))
      (completing (fn [n _] (inc n)))
      0
      (iterate incr (vec (repeat (count startv) (first startv)))))))

(day4 124075 580769 1) ;; => 2150
(day4 124075 580769 2) ;; => 1462

12
jrwdunham18:12:21

Nice @qythium, about 1msec faster than @dmarjenburgh’s solution in my timing.

norman20:12:24

Doing AOC last year was so much easier when I was on vacation for almost the entire month. I have a feeling I'm going to be playing catch up all month...

fellshard20:12:04

Yeah, I may need to curb my participation for a while. Too busy.

fellshard20:12:31

But I feel better about it knowing that I'm not aiming for leaderboard points. I'll learn what I'm aiming to, just more slowly.

fingertoe21:12:08

Simple enough: https://github.com/jreighley/aoc2019/blob/master/src/aoc/aoc4.clj It’s not too often that I use ns without a :require. The separated-pairs? fn seems a bit hacky, but effective.