This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-01
Channels
- # 100-days-of-code (5)
- # adventofcode (234)
- # aleph (13)
- # announcements (2)
- # architecture (3)
- # bangalore-clj (1)
- # beginners (312)
- # calva (7)
- # cider (6)
- # cljdoc (3)
- # cljs-dev (30)
- # cljsrn (2)
- # clojure (40)
- # clojure-austin (2)
- # clojure-dev (65)
- # clojure-greece (1)
- # clojure-italy (29)
- # clojure-kc (1)
- # clojure-russia (2)
- # clojure-uk (26)
- # clojurebridge (1)
- # clojurescript (4)
- # cursive (11)
- # data-science (1)
- # datomic (43)
- # docker (1)
- # duct (7)
- # emacs (3)
- # figwheel-main (7)
- # fulcro (8)
- # garden (3)
- # graphql (8)
- # hyperfiddle (4)
- # off-topic (10)
- # other-languages (12)
- # pathom (4)
- # portkey (1)
- # remote-jobs (3)
- # rum (8)
- # shadow-cljs (40)
- # tools-deps (68)
- # unrepl (2)
- # vim (5)
woke up, made coffee, read the puzzle 1 & wasn't sure if I'm still half asleep or is that really a 1-liner.
Day one is usually just a warmup. I use the time I'd normally take to get the environment warmed up, etc.
I have a standard workspace I use now for these, since there's a lot of common core utils - reading from resources file, parsing integers, defining coarsely-curried functions for interpreters, etc.
I donāt think I will do another, though with some love replete could easily be much more useful. Being able to save some files locally or even better to iCloud, some helpful keys above the keyboard. I wonder if itās open source.
Yeah, I maintain Replete. Custom keyboard stuff is always challenging to pull off while preserving the polished feel, but I definitely agree there could be some keyboard improvement. (You can always use a 3rd party keyboard with it.) The ability to save and edit locally or in iCloud would be nice. We can't do this, as it is not allowed http://blog.fikesfarm.com/posts/2015-08-11-loading-clojurescript-into-your-iphone.html but perhaps content created in Replete could be saved without violating any App Store rules.
I feel like thereās a clever use of lazy seqs in the 2nd part that Iām not seeing
Here is a way to do it using only lazy seqs, but in the end, I didn't like that approach compared to just a direct reduce to find the dup. https://gist.github.com/mfikes/53c53673f66257878ab82408635f297d
Given my constraints, I just went with a loop recur for part 2. Not much room for experimenting.
Submitted my solution for day 1 to Advent of CLJC: https://github.com/borkdude/advent-of-cljc
The fun thing is you can see the timing of every day and user here: https://circleci.com/gh/borkdude/advent-of-cljc/55 when you scroll to the test execution
@helios I donāt know if there is a leaderboard. You might want to create one? @mario.cordova.862 You could also submit a PR to the above repo as an alternative of posting your solution here š
I wouldnāt post your code here directly, a gist would be more appropriate. Of if youāre going to post it, post it only in a thread, so people donāt see the spoiler.
@helios thanks. might also want to add it to the https://github.com/adventofcode-clojurians/adventofcode-clojurians repo
@mario.cordova.862 can you rebase your PR? it has a conflict now
There used to be an adventofcode-clojurians leaderboard, but I donāt have the invitation code. Perhaps clojurians slack log might have it?
Created pull request for adventofcode-clojurians. Also slightly offtopic does anyone else has a internal conflict of writing things in a simple way vs smart? I ask because as a developers I feel that we are constantly judged on quality of our code and how "smart" it is but when reading other people code I like things rather simple.
@karol Sometimes thereās a balance between keeping it simple and hacking it for performance
of course, and that is why I like advent of code because usually the first part can be done without optimization and you need to be clever in second part š but I am fan of optimize only when needed and don't introduced layers of abstraction "for future", because I saw few clojure codebases that look like Java EE with parentheses but it is morning here so I might be just complaining š
And its nothing to do with when you start solving! Time starts for everyone when the problem appears.
@denis.fuenzalida @dandorman thanks for contributing to advent of cljc https://github.com/borkdude/advent-of-cljc
Maybe. Iām not sure how this will work out if multiple users contribute all of their days. If it gets too slow on CI, I might filter the tests only for that user. So running tests multiple times might be something you want to do locally
I guess not too important at this point, the corpus is the important thing. Great initiative!
Would anyone have some time to help me? My process keeps running for part 2 with the puzzle input and just never ends, if I use one of the examples as the input though it does seem to work... (I'll post my code as a thread to this message so spoiler alert!)
(def input (mapv read-string (str/split (slurp "./input") #"\n")))
(defn step [{:keys [frequency-changes current-index frequencies]}]
(let [
new-index (mod (inc current-index) (count frequency-changes))
last-frequency (or (last frequencies) 0)]
{
:current-index new-index
:frequencies (conj frequencies (+ last-frequency (get frequency-changes current-index 0)))
:frequency-changes frequency-changes
}))
(defn last-item-double [l]
(and (> (count l) 1) (> (.indexOf (butlast l) (last l)) -1)))
(defn part2 [frequency-changes] (last (:frequencies (step (last (take-while
(fn [state] (not (last-item-double (:frequencies state))))
(iterate step {
:frequencies []
:frequency-changes frequency-changes
:current-index 0
})))))))
(part2 input)
You are using a very inefficient algorithm to check for an already seen item. Using .indexOf etc etc means every time this run means it has to āwalkā all the previous steps again and again.
As an aside, also consider formatting your code a little bit better as it can be really hard to follow š
thanks for the feedback! I got it to work way faster with a different approach, using loop/recur and a set as you suggested
regarding code formatting, is there a general coding guideline for clojure and a linter like there is for python?
There is the clojure style guidelines by Bbatsov, and a few linters. Thereās a big discussion right now going on in ClojureVerse about this so you can find more info there (sorry, on mobile so canāt paste links easily)
My solution for day 1. https://github.com/benfle/advent-of-code-2018/blob/master/day-1.clj
Here's mine https://git.sr.ht/%7Eihabunek/aoc2018/tree/master/clojure/src/aoc2018/day01.clj
i'm actually doing it in clojure and elixir in parallel, but pretty sure i won't have the time or willpower to do it all the way through in both languages
Simplified to use cycle
. I forgot about this function. Thanks. Yes state is debatable here but since it improves readability and reusability I opted for it š
I can think of a bunch of different ways to solve it offhand ā none of them will take particularly long.
I tend to not even read this channel until I'm done with my solution. Otherwise you might see solution strategies being discussed.
To be honest, I enjoy seeing solution strategies being discussed. (Otherwise, where would they be, all in side threads?)
Also, the ability to look at other people's solutions and other ideas is the main value I get out of this. Much more than solving the problems myself. š
So to answer Mario. I think if you stream in the changes and stream out the frequency in a sorted file you could solve it while just keeping one number in memory. But I didn't bother doing this š
I tend to solve it first then come on here but I am guessing at later days when it becomes more difficult Ill be coming here for pointers :P
Yeah, there's a problem where you are stuck and want a little help, without seeing the solution. :thinking_face:
One thing I see now is that, even though my solution works on my data, I have a defect in it š
My solution https://github.com/bhauman/advent-of-clojure/blob/master/src/advent-2018/day01.clj
My solution gives the wrong answer for this input: [5 10 20 -35]
. I suspect this will be a common mistake.
Thanks for submitting your solution to https://github.com/borkdude/advent-of-cljc @mfikes!
My solution https://github.com/mfikes/advent-of-code/blob/master/src/advent_2018/day_01.cljc
https://gitlab.com/randall.mason/advent-of-code/blob/master/src/advent_of_code_2018/day01.clj
and hereās mine, enjoying seeing the different solutions! https://github.com/taylorwood/advent-of-code/blob/master/src/advent_of_code/2018/1.clj
feeling pretty cheeky about (drop-while #(apply not= (swap-vals! seen conj %)))
:man-juggling:
I also have the same issue with my solution. I wish there was a reduce-until function or something like that.
Thanks!!!
I do wish somebody would make a data oriented source of the examples. I just want to pull in a mapping of input to output.
nice! it seems a lot of people reached the same conclusion for part 2, though I shamelessly went with atoms for my first attempt
I really wanted to find a way to reuse distinct
. Here is one way, but I'm wondering if there is some other clever way to reused the underlying capability in the core lib. https://gist.github.com/mfikes/53c53673f66257878ab82408635f297d
I thought about making a variation of distinct
transducer like while-distinct
or something
(defn while-distinct []
(fn [rf]
(let [seen (volatile! #{})]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (contains? @seen input)
(reduced (rf result input))
(do (vswap! seen conj input)
(rf result input))))))))
(->> (cycle values)
(reductions +)
(eduction (while-distinct))
(last))
though that name isnāt great because it includes the first non-distinct value :man-shrugging:my solution: https://github.com/borkdude/advent-of-cljc/blob/master/src/aoc/y2018/d01/borkdude.cljc
yeah I ended up using loop-recur and cycles: https://github.com/Lokeh/advent-2018/blob/master/day1/src/advent/day1.clj#L54
Itās honestly not something you should think about all the time. But I like running through various levels of efficiency in my head.
so, using cycle+reductions+reduce -> (seq of cycle) + (seq of reductions) + #{set of reduce}
my thought was that pretty much either way a new data structure needs to be generated at least from the solutions I've seen thus far, so I wasn't sure if using reductions was actually less efficient than managing the computations and what has been seen
in a reduce.
Here's my solution: https://github.com/pesterhazy/advent2018/blob/master/src/advent/puzzle01.clj
I'm curious how much room for difference there is in a simple task like this
Iāll ping back here after the stream with a link to github if you just want to review results.
It seems like most solutions involve a reduce
or a direct loop
/ recur
to essentially walk the sequence looking for the first dup.
@mfikes I saw your tweet and couldn't resist š
I thought a bit about how to just calculate it analytically, but didn't see anything easy. Did anybody come up with a way?
Of course I spent 90% of the time setting up the clj
tool with nREPL and the Corfield Comma
@mfikes your idea of using two reductions on top of each other is clever
other than that mine is identical almost to a character
is that a common FP pattern? I wasn't aware
i did something similar. the data to investigate is the reduction. seems not necessarily FP but just this problem to me
reduce
is a great abstraction (obviously!) because you can swap in reductions
and get a nice debugging output for free. Plus if the sequence doesn't terminate, you can lazily take n
off the top of my head, Iāve got ~5 diff ways to go about it
Why the drop 1? This is probably related to why I disagreed with [+1 -1] => 0 rather than 1. But I still don't see why.
yes it gets rid of the 0 sum for the sequence of length 0. i originally didn't have it
My solution uses a "composite accumulator", in this case a vector [acc-freq acc-seen]
. I find myself reaching for composite accumulators often for less-than-simple reduces but I wonder if it's a good pattern
i do that all the time. i only get annoyed because it usually requires a step to pluck apart the composite accumulator at the end
The (->> xs (reductions step-1 init-1) (reduce step-2 init-2))
pattern avoids the composite acc
@dpsutton right, although when you know that you're going to end with reduced
, you won't need it
it would be interesting to compare performance as well. reductions
must incur some performance cost
I always feel a little bad using reduced. The short circuit makes me feel like I'm abusing reduce

@pesterhazy I have the same pattern
@borkdude ours are practically identical
I've seen reducing functions defined outside of the reduce call where they include reduced and I have no idea what reduced does if it is not in a reducing context
it just returns a special Java class, clojure.lang.Reduced
@me1740's stateful predicate is interesting: https://github.com/benfle/advent-of-code-2018/blob/master/day-1.clj#L16 - I'm not sure how I feel about that
Perhaps, close to that idea, but safer, would be to take the source of distinct
and produce an opposite function named duplicates
, and then take the first from that
I guess a stateful sequence processing function (like distinct
) is safer than a stateful predicate
"safer" in the sense that using a stateful predicate for filter
or keep
is violating its contract
whereas the contract of sequences has no such provision
so the idea would be a while-distinct
function?
does the name duplicates
make sense though?
we're looking for the opposite of duplicates, r ight?
I think so? āI want all of the duplicates in this seq.ā As opposed to, āI want the duplicates removed from this seq.ā
gotcha, you'd use (->> xs duplicates first)
actually while-distinct
would work only if it was inclusive of the dupe (which makes little sense)
yeah I had the same thought earlier, duplicates
makes more sense https://clojurians.slack.com/archives/C0GLTDB2T/p1543684422093600?thread_ts=1543683763.088200&cid=C0GLTDB2T
@me1740 Trying to come up with an example:
cljs.user=> (def x (eduction (keep (duplicate?)) [1 2 3 2 4 2 3]))
#'cljs.user/x
cljs.user=> (into [] x)
[2 2 3]
cljs.user=> (into [] x)
[1 2 3 2 4 2 3]
Oh ok I see, thanks. Also explain why you should initialize your state inside a transducer function.
So I had to rewrite that as a transducer with the state inside it:
(defn duplicates
[]
(fn [xf]
(let [seen (volatile! #{})]
(fn
([] (xf))
([result] (xf result))
([result input]
(if (contains? @seen input)
(xf result input)
(do
(vswap! seen conj input)
result)))))))
haha Iām playing w/Quil to visualize the solution as itās calculated, but then I just figured out itāll take ~40 minutes to finish @ 60fps
having both reductions
and duplicates
transducers would be interesting, I wonder if I would remember to use the duplicates one
@borkdude I just updated the invite code for the leaderboard, I deleted the ones I created this afternoon
who owns this advent-of-clojurians repo, I think @thegeez? can you add more people with PR merge rights? It seems Iām the only one doing that right now
Probably not the ideal use, but I used NextJournal to do the day 1 challenges. Link if anyone wants to remix it with other styles: https://nextjournal.com/akmiller/advent-of-code-2018--day-1
I decided to do the first day in both CLJ and Rust. https://github.com/Lokeh/advent-2018/tree/master/day1
weāll see how far I get before succumbing to my lack of Rust knowledge (and frustrations with the type system) and just do the rest in CLJ :P
I think I might update my CLJ solution with a duplicates
xf - wanted to in the moment but it was very late for me last night