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
2017-12-12T06:26:42.000243Z

That was a neat problem!

grzm 2017-12-12T06:38:21.000203Z

Used a core function I hadn't before 🙂

2017-12-12T06:38:55.000011Z

which one?

2017-12-12T06:39:02.000108Z

guessing disj

grzm 2017-12-12T06:39:19.000243Z

tree-seq

2017-12-12T06:39:25.000227Z

ooh nice

2017-12-12T06:39:27.000178Z

link?

grzm 2017-12-12T06:40:47.000120Z

Soon. I'm cleaning up my cljs port

2017-12-12T06:40:53.000184Z

haha no problem

2017-12-12T06:44:48.000131Z

nice, similar to mine but I did it manually 😛

grzm 2017-12-12T06:45:29.000012Z

I'm not too strong at graph work. I took some time to look for something that could do it for me 🙂

spfeiffer 2017-12-12T06:46:10.000120Z

Its amazing and terrifying at the same time what clojure core has to offer…

grzm 2017-12-12T06:47:37.000173Z

I'm working through the Anki deck to try to keep it at hand.

grzm 2017-12-12T06:48:49.000163Z

Like peek and pop in @minikomi’s solution: wouldn't use it because they're not something I'm readily aware of.

2017-12-12T06:49:44.000075Z

oh, guess we can just assume that all programs have an entry

2017-12-12T06:49:55.000076Z

no need to join in the right hand side

grzm 2017-12-12T06:51:19.000137Z

Yeah, that was a double-edged sword, I think. You could end up walking in a circle if you didn't keep track of what you'd already seen.

2017-12-12T06:57:20.000086Z

I wonder if there's a better idiom for (filter #(not some-set %) items)

grzm 2017-12-12T06:57:53.000122Z

(remove some-set items)

2017-12-12T06:58:02.000112Z

oh yeah lol

grzm 2017-12-12T06:58:27.000277Z

Only 22 hours remaining…

borkdude 2017-12-12T07:42:33.000192Z

Today was easy (although mine isn’t as fast as @grzm’s!)

borkdude 2017-12-12T07:48:06.000145Z

I may have killed an elve who was sitting on my CPU today.

fellshard 2017-12-12T08:06:44.000164Z

There is a useful data structure that makes this almost trivial!

fellshard 2017-12-12T08:09:37.000011Z

If you want to dig deeper but don't want full spoilers, I'd recommended reading up on Connected Components in graph theory

fellshard 2017-12-12T08:09:53.000254Z

It's not too rough, thankfully 🙂

borkdude 2017-12-12T08:36:44.000375Z

http://jgrapht.org/ 😉

orestis 2017-12-12T08:41:34.000118Z

I didn’t implement my own graph for this; ubergraph for the rescue. https://github.com/orestis/adventofcode/blob/master/clojure/aoc/src/aoc/2017_day12.clj

orestis 2017-12-12T08:43:21.000057Z

I have to implement a hairy layout algorithm for work today; don’t have the time to actually implement a graph algorithm!

borkdude 2017-12-12T08:44:32.000215Z

@orestis Cool, didn’t know about ubergraph. Thanks.

orestis 2017-12-12T08:44:57.000082Z

I’ll time my solution, just for laughs.

orestis 2017-12-12T08:46:28.000083Z

150-200ms to the answer for part 2, which is then a filter away to give the answer to part 1.

borkdude 2017-12-12T08:47:53.000149Z

pretty good

orestis 2017-12-12T08:48:33.000027Z

To my shame, I admit I tried various functions of ubergraph.alg until I found something that seemed to a useful result.

fellshard 2017-12-12T09:04:27.000061Z

Yep, found the exact functions that will answer these questions in seconds flat

2017-12-12T09:05:13.000316Z

advent.2017.day12> (c/quick-bench (solve2 input-raw))
Evaluation count : 78 in 6 samples of 13 calls.
             Execution time mean : 8.241557 ms

🎩 2
2017-12-12T09:14:37.000302Z

https://github.com/sciyoshi/advent-of-rust-2017/blob/master/src/day12/mod.rs wow, rust has funky tools to use

fellshard 2017-12-12T09:52:18.000327Z

Guh. The documentation for jgrapht is abysmal.

fellshard 2017-12-12T09:52:27.000106Z

No more time to spend on that tonight. Never mind, got it worked out. Pseudograph is sufficient.

fellshard 2017-12-12T10:01:15.000355Z

Always highlight the entrance points to your library in big, bold letters. Same issue I had when I was working with Google Dataflow / Apache Beam for a client.

borkdude 2017-12-12T10:29:25.000139Z

@fellshard link to your solution?

borkdude 2017-12-12T10:35:22.000412Z

Btw, @fellshard, did you perhaps mean data-prioritymap?

borkdude 2017-12-12T11:32:10.000090Z

@thegeez cool! is it fast?

2017-12-12T11:37:50.000121Z

fast enough, part 1 224ms, part 2 1.4seconds. both including parsing input, but not slurping input

bhauman 2017-12-12T12:02:57.000141Z

@minikomi (filter (complement myset) stuff)

bhauman 2017-12-12T12:03:52.000320Z

I find complement set comes in pretty handy, as well

borkdude 2017-12-12T13:50:23.000441Z

@bhauman just out of curiosity, how fast is your part 2?

bhauman 2017-12-12T13:51:03.000229Z

oh like 800ms

borkdude 2017-12-12T13:51:04.000306Z

and why did you need disj here? https://github.com/bhauman/advent-of-clojure-2016/blob/master/src/advent_of_clojure_2017/day12.clj#L16

bhauman 2017-12-12T13:51:23.000554Z

a tiny optimization

borkdude 2017-12-12T13:51:46.000115Z

It seems the input didn’t have x -> y z x?

bhauman 2017-12-12T13:52:03.000679Z

my input did

bhauman 2017-12-12T13:52:10.000395Z

x -> x

bhauman 2017-12-12T13:52:16.000203Z

x -> x y z

borkdude 2017-12-12T13:52:17.000618Z

ah, it did? hmm I should look into mine then

bhauman 2017-12-12T13:55:47.000531Z

it really doesn't need to be there, as it doesn't have a big affect, it only doubles the leaf step

borkdude 2017-12-12T13:57:00.000395Z

ah yes, there are many of them, now I printed them, e.g. 1991 (439 1991)

borkdude 2017-12-12T14:19:45.000106Z

SPOILER in thread

borkdude 2017-12-12T14:19:57.000369Z

@bhauman I didn’t know tree-seq could do this, amazing.

borkdude 2017-12-12T14:20:14.000240Z

(tree-seq
   (constantly true)
   {0 #{2 3}
    2 #{4 5}
    3 #{6 7}}
   0)
how does it see this as a tree? I don’t understand it yet.

2017-12-12T14:25:41.000056Z

The second function converts a value to children 0 comes in, you get children 2 and 3 2 and 3 come in, they give 4 and 5; and 6 and 7 respectively.

borkdude 2017-12-12T14:26:45.000360Z

ah, so the second arg is also a function, let’s see

grzm 2017-12-12T14:30:07.000014Z

@borkdude the quick-bench for part-2 was wrong. copy-paste error late at night. I get 25-29ms for part-2.

borkdude 2017-12-12T14:30:19.000545Z

so normally you pass in a tree, but now only the number 0 is used as the “root” of the tree. then children are looked up in this “tree” by (children 0) which is then the tree which is walked. This is brilliant.

borkdude 2017-12-12T14:30:51.000233Z

very nice

borkdude 2017-12-12T14:31:05.000244Z

My mind is blown by @bhauman’s solution. 💡

3
bhauman 2017-12-12T14:34:38.000275Z

sorry, was making breakfast but yeah tree-seq is powerful

mfikes 2017-12-12T14:45:31.000292Z

@grzm Nice solution! Only suggestion I'd make is to use a volatile instead of atom in prog-group.

grzm 2017-12-12T14:46:22.000390Z

Thanks! And thanks for the pointer.

grzm 2017-12-12T14:47:18.000440Z

@bhauman I like how you pulled seen into the tree-seq branch? function

👍 1
grzm 2017-12-12T14:49:58.000511Z

@mfikes Doesn't seem to do much in terms of performance, at least for this problem.

grzm 2017-12-12T14:50:40.000488Z

Would there be another reason to prefer volatile over atom?

bhauman 2017-12-12T14:52:35.000338Z

I used a volatile for a second but then thought that there is no reason that tree-seq couldn't be run in parallel and so preferred atom

mfikes 2017-12-12T14:53:01.000201Z

I wonder if @fellshard was referring to this one https://en.wikipedia.org/wiki/Disjoint-set_data_structure

👌 1
grzm 2017-12-12T14:55:47.000134Z

Maybe next year I'll focus on reducers/fork instead of transducers 🙂

borkdude 2017-12-12T14:56:36.000709Z

@grzm why?

grzm 2017-12-12T14:56:57.000161Z

Just to learn/reinforce another area of the library. To be able to choose the right tool for the job I at least need to know what tools are out there. Right now I've got big holes in my knowledge of the core library.

👍 2
borkdude 2017-12-12T14:57:26.000596Z

yeah. we are relying on the fact here that branch? can be side-effecting (to do the atom bookkeeping), but it’s probably a safe assumption

mfikes 2017-12-12T14:58:01.000536Z

The definition of remove is essentially (filter (complement pred) coll)

grzm 2017-12-12T14:59:31.000190Z

Are these times right? Are people really solving this in less than 3 minutes? http://adventofcode.com/2017/leaderboard/day/12

borkdude 2017-12-12T14:59:31.000372Z

tree-seq really a short/simple function

mfikes 2017-12-12T15:00:18.000637Z

@grzm Nah, volatile is only better than atom for perf reasons. So it may become an idiom to use volatiles for local function state and atoms for defs. (Essentially a thing where you don't think about it.)

grzm 2017-12-12T15:00:40.000134Z

That makes sense.

mfikes 2017-12-12T15:09:03.000442Z

For those curious, the algorithm I'm using comes in at 10.6 ms for part 1 and 11.4 ms for part 2 if you exclude the I/O and parsing (and apply the algorithm to parsed data)

mfikes 2017-12-12T15:10:27.000296Z

(It is easy to convert that algorithm from a functional one to an imperative one that bashes on a mutable array and I think that works much more quickly.)

mfikes 2017-12-12T15:11:44.000050Z

I didn't invent the algorithm. It is a popular one from 1964.

borkdude 2017-12-12T15:38:24.000187Z

@fellshard Is jgrapht any faster than the others?

fellshard 2017-12-12T15:40:34.000002Z

I haven't benched anything yet 😅

fellshard 2017-12-12T15:41:30.000078Z

I'd expect union-find to be fastest, if only by dint of skipping the graph entirely. Union-find has inverse-Ackermann amortized performance.

fellshard 2017-12-12T15:41:45.000461Z

AKA 'effectively constant'

mfikes 2017-12-12T15:59:00.000801Z

If you do a mutable union-find, part 1 comes in at 539 µs for me and part 2 at 1.12 ms.

mfikes 2017-12-12T15:59:21.000109Z

Here is the code that I benchmarked to produce those numbers: https://gist.github.com/mfikes/fc2e94db229b53d68f243cd7b8c253b5

👌 2
🦜 1
mfikes 2017-12-12T16:01:09.000789Z

As above, this excludes the I/O and parsing

fellshard 2017-12-12T16:06:19.000532Z

Yeah, that's one thing I noted - the union-find library I picked up has no capacity to leverage the bind-to-root optimization you'd normally use. So I suppose that makes its perf more like log(n).

mfikes 2017-12-12T16:19:04.000590Z

Union-find seems like a good example of an imperative algorithm from the 60s-70s which is difficult to efficiently express in a functional way.

mfikes 2017-12-12T16:19:39.000857Z

(I haven't found a way to write it in "normal" Clojure that runs as fast as bashing on arrays.)

fellshard 2017-12-12T16:26:10.000938Z

You could always pass the tree back with every operation. Perhaps hiding it behind an atom would allow you to make modifications that are 'effectively immutable'?

fellshard 2017-12-12T16:26:53.000092Z

Trust the contract to hold properties, I guess, with a dash of testing for certainty

mfikes 2017-12-12T16:47:23.000859Z

@fellshard I am passing the tree back. Perhaps it is the case that I have a functional version that has the same computational complexity and I’m just seeing a constant overhead associated with working with persistent data structures. I’m going to scrutinize it a bit more. Here it is for reference https://github.com/mfikes/advent-of-code/blob/master/src/advent_2017/day_12.cljc#L19-L37

mfikes 2017-12-12T16:52:13.000659Z

I’m going to see if that can be written with transients instead.

mfikes 2017-12-12T18:03:45.000385Z

Well, the good news is that it is possible to get part from 10.6 ms down to 1.35 ms by using transients, which compares well to the imperative version that runs in 539 µs. https://gist.github.com/mfikes/c4cf04d10bbfc8c2862fe15a58642501

😄 3
grzm 2017-12-12T18:40:22.000724Z

crikey, @mfikes. (Or should I say fikey?) That's impressive.

borkdude 2017-12-12T19:03:44.000075Z

https://xkcd.com/356/

😂 3
borkdude 2017-12-12T19:51:44.000231Z

@mfikes what is the name of the 1964 algorithm?

mfikes 2017-12-12T19:52:17.000837Z

I call it union-find, but it has other names https://en.wikipedia.org/wiki/Disjoint-set_data_structure

borkdude 2017-12-12T19:57:22.000230Z

cool, thanks. you learn a lot from these nerd snipes 🙂