This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-04
Channels
- # adventofcode (100)
- # announcements (7)
- # architecture (1)
- # aws (14)
- # beginners (209)
- # calva (30)
- # cider (5)
- # cljdoc (2)
- # cljs-dev (37)
- # cljsrn (2)
- # clojure (133)
- # clojure-dev (20)
- # clojure-finland (1)
- # clojure-italy (10)
- # clojure-nl (19)
- # clojure-spec (56)
- # clojure-uk (49)
- # clojurescript (57)
- # clojurex (8)
- # core-async (2)
- # core-logic (1)
- # cursive (38)
- # data-science (19)
- # datomic (28)
- # devcards (3)
- # duct (8)
- # emacs (28)
- # figwheel (1)
- # figwheel-main (31)
- # fulcro (2)
- # jobs (1)
- # kaocha (1)
- # klipse (2)
- # mount (6)
- # nrepl (43)
- # off-topic (20)
- # pathom (3)
- # pedestal (1)
- # re-frame (15)
- # ring-swagger (1)
- # shadow-cljs (47)
- # spacemacs (19)
- # sql (20)
- # tools-deps (58)
- # unrepl (13)
- # vim (5)
and I finally got around to doing day 3 https://github.com/bhauman/advent-of-clojure/blob/master/src/advent-2018/day03.clj
[1518-09-19 23:52] Guard #2083 begins shift
[1518-02-25 00:51] wakes up
[1518-02-28 00:34] wakes up
[1518-04-29 00:54] wakes up
They don’t give you any hint of that apart from > consider the following records, which have already been organized into chronological order
yeah I found the description less than clear
but I guess vague specifications is a real-world programming scenario 🙂
In the description they say: > While this example listed the entries in chronological order, your entries are in the order you found them. You’ll need to organize them before they can be analyzed.
Yeah, you’re right. I missed it because it’s not in the place I expected to find it (task description, rather than input format description)
That also is a real-world programming scenario: don’t read specs before first coffee :woman-facepalming:
Reminds me ☕
I almost had a heart-attack when I checked out the real data and saw it had multiple "wakes up" in a row, after having written my solution. Then I realized that it just wasn't chronologically ordered. Then sort
came to the rescue 🌸
My solution to day 4 https://github.com/pesterhazy/advent2018/blob/master/src/advent/puzzle04.clj#L42
Spent around half the time on parsing/understanding the file format
It was a key realization that there's only one useful chunk of info per line. Also, the specific line format they give means you can sort it in standard lexicographic order to get the correct sequence of events right off the bat, no interpretation of the data required. 🙂
I did sort lexicographicallz
but you still need to match guard-ids, interval starts and ends no?
And event type 🙂
True; I attached that as a tag afterwards, though, since you need to know which type it is to parse correctly in the first place
Solved day 4: https://github.com/borkdude/advent-of-cljc/tree/master/src/aoc/y2018/d04
In CLJ:
Testing aoc.y2018.d04.borkdude
part-2 took 40.23 msecs
part-1 took 3.80 msecs
@pesterhazy It seems our solutions are quite similar
When reading the puzzle, I thought “strategy 1” was trying to mislead me, since they wrote that there were two strategies and I thought you had to come up with another better strategy 😉
here’s my day 4 https://github.com/taylorwood/advent-of-code/blob/master/src/advent_of_code/2018/4.clj reached for clj-time and instaparse b/c why not 🙂
My solution to day 4 https://github.com/benfle/advent-of-code-2018/blob/master/day4.clj
and mine: https://github.com/genmeblog/advent-of-code-2018/blob/master/src/advent_of_code_2018/day04.clj
If I had time I would have refactored into something like @tsulej. If you have the proper data structure with minute-level stats for each guard, the 2 solutions can be very concise.
Yes, I think that proper data structure is crucial here. I spent most of my time to find one. The same applies for day 3.
oh yeah, I always forget you can give sort-by
another argument like (sort-by val > the-things)
Day 4 https://github.com/mfikes/advent-of-code/blob/master/src/advent_2018/day_04.cljc
I’m not done yet (done 1/2), but took a look at this channel, and max-key instead of sort-by in the existing solution … which slowed things down. Did you find it more performant?
Are you thinking (apply max-key...)
has a heavier cost for, say, a map of minute tallies?
(…actually might have been the effect of something triggering in the background… I need to check again once I’ve got a charger 🙂 )
I looked at it, but passed it by because I thought it wasn't quite what I wanted. I'll take another look to see what I'm missing.
@fellshard I had the same: max-key passed my mind but then I thought: oh this is for map keys or something
I think the prospect of (apply max-key...
on 60 elements had me a bit worried, I forget what the rules are for slapping a bunch of arguments in there, even rest-args
@fellshard (apply + (repeat 1000000 1))
seems to work ok in CLJ and CLJS, but (apply + (repeat 10000000 1))
is fast in Clojure but very slow in CLJS (at least in Lumo 1.8.0)
In Java varargs are passed as an array AFAIK so it should be fine. Not sure why it's so slow in CLJS
Probably GC?
Math.max.apply(null, new Array(1000000).fill(0))
blows the stack...
@pesterhazy Update to Lumo 1.9.0. You'll see (apply + (repeat 1000000 1))
a few hundred times faster. Why? This is the result of optimizations made in ClojureScript after last year's Advent of Code. 🙂

changed my max-frequency function. I really should use max-key more often. I think I only remember it until Advent of Code comes along again https://github.com/borkdude/advent-of-cljc/commit/24fa6344c3c64a3fc242d7b2a784df7b73bace8a
Lumo 1.8.0:
cljs.user=> (type (repeat 1000000 1))
cljs.core/LazySeq
Lumo 1.9.0:
cljs.user=> (type (repeat 1000000 1))
cljs.core/Repeat
More info: https://clojurescript.org/news/2018-03-26-release#_reducible_sequence_generators
I’ve browsed clojure.core, but keep forgetting about many of the functions in there. I totally forgot about max-key
and rolled my own. That said, I used what I rolled in a couple of other ways, so it wasn’t a waste
@mfikes the advent of code comes full circle!
it's much faster indeed 🎉
also a good occasion to upgrade lumo
now it's 10x faster than Clojure
$ lumo
cljs.user=> (time (apply + (repeat 10000000 1)))
"Elapsed time: 65.706720 msecs"
10000000
$ clj
Clojure 1.9.0
user=> (time (apply + (repeat 10000000 1)))
"Elapsed time: 657.798409 msecs"
10000000
Is (reduce + ...
any faster?
Looks like yes
user=> (time (apply + (repeat 10000000 1)))
"Elapsed time: 526.222753 msecs"
10000000
user=> (time (apply + (repeat 10000000 1)))
"Elapsed time: 656.773543 msecs"
10000000
user=> (time (reduce + (repeat 10000000 1)))
"Elapsed time: 178.887459 msecs"
10000000
user=> (time (reduce + (repeat 10000000 1)))
"Elapsed time: 47.995412 msecs"
10000000
user=> (time (reduce + (repeat 10000000 1)))
"Elapsed time: 39.555085 msecs"
10000000
performance is weird
In this case, Lumo may be running at native speed. See https://www.youtube.com/watch?v=LopU-kMpe8I
anyone know why (read-string "01")
or (read-string "02")
... all the way up to 07 work just fine but (read-string "08")
and (read-string "09")
throw exceptions saying it is an invalid number? Would assume all would or none would.
I've used this almost every day so far:
(defn str->int [^String s]
(Integer/parseInt s))
Does this work with the positive numbers, like "+5"?
I thought I tried that and it didn't work. Is fixed by the ^string metadata?
Hmmm.... Dang. Wonder what I had problems with...
Maybe it was just the int
function...
but yeah, java Long/parseLong
permits + and -: https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#parseLong(java.lang.String)
I’m forever wrapping Long/parseLong in a function. It’s a source of never ending frustration for me that Clojure doesn’t have to-long and to-double
The function reader literal syntax is pretty terse: #(Long/parseLong %)
. Much nicer than a top level (defn ...)
form, if that's what you've been using.
I did this for day 3:
(map (comp #(Integer/parseInt %)
(memfn trim)))
yeah, for cljc read-string was just faster, but better not to use it for these scenarios (in real code)
@adammiller not sure if you do advent-of-cljc, but there’s aoc.utils/parse-int
for cross platform
yes, I saw that. Actually just moved my day 3 solution there yesterday....just locally though.
@adammiller welcome to submit individual puzzles for any day
ok, i'll see about moving my day 4 and then submit them. Thanks!
Does this work with the positive numbers, like "+5"?