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
2018-12-08T00:00:31.887500Z

Nifty, it worked. Brought the run time down from 30 secs for my naive brute force solution to 100 msecs for the efficient solution. I think there's room for improvement still, but it's super satisfying to find the efficient solution hidden in the rubble.

👌 1
fellshard 2018-12-08T00:05:13.888100Z

It makes sense. The manhattan distance function would just look like a 3-d inverted pyramid centered on that point (e.g. \/ ), and the sum of distances is just gonna be the sum of those functions, which in turn are just the sums of the 2-d cross-sections

fellshard 2018-12-08T00:39:49.889800Z

Good call!

2018-12-08T00:47:04.890100Z

sorted-set is also useful in part 2 for keeping track of the in-progress tasks, sorted by time of completion.

fellshard 2018-12-08T01:00:18.891100Z

Mine's not exactly optimally expressed - there's some duplicate calculations I'd like to weed out - but I think it reads nicely 🙂 https://github.com/armstnp/advent-of-code-2018/blob/master/clojure/src/advent_of_code_2018/day7.clj#L67

gklijs 2018-12-08T01:44:01.891300Z

I can't quickly check for myself right now, but if you add something to a 'sorted-set' it might be added out of place? The documentation isn't clear, in Java it's a specific type of set which does keep order.

2018-12-08T02:00:47.891500Z

(conj (conj (conj (sorted-set) 1) 2) 0) => #{0 1 2}

2018-12-08T02:01:40.891700Z

Sorry, that's terribly formatted.

(-> (sorted-set)
    (conj 1)
    (conj 2)
    (conj 0)) => #{0 1 2}

2018-12-08T02:02:35.892200Z

Much better

2018-12-08T02:14:17.892500Z

@gklijs I’m assuming it’s always natural sorting by default.

2018-12-08T02:14:32.892700Z

(same as the java set)

2018-12-08T02:16:21.892900Z

So letters will stay in alphabetic order

ClashTheBunny 2018-12-08T04:37:28.894800Z

I tried passing around data this time and having each function recieve and transmit the same data structure. It could have been just as easily done with an atom. I have never tried something like this before and it was super painful. What do other people do? https://gitlab.com/randall.mason/advent-of-code/blob/master/src/advent_of_code_2018/day07.clj Also, gitlab may be having struggs?

ClashTheBunny 2018-12-08T14:26:30.931400Z

I have finally gotten the update assoc distinction, so at least I'm not learning that! 🙂

2018-12-08T05:01:33.896100Z

I like the idea of ancillary functions taking a large map of all the data, then only operating on the subsets the function needs. It's very "inversion of control" style.

2018-12-08T05:02:19.896300Z

I think you could improve your usage of the style by having your ancillary functions return the whole map, after performing some update-in calls to update the keys that pertain to that function.

2018-12-08T05:03:16.896500Z

Then where you are calling the ancillary functions you can use a threading macro:

(->> the-data
     do-thing-1
     do-thing-2
     do-thing-3)

2018-12-08T05:05:36.896700Z

Ah, I see it's basically what you're doing but instead of calling update-in and letting the other values come along for the ride by default, you are manually reconstituting the map including all the keys that don't pertain to the function.

2018-12-08T05:12:02.896900Z

Here are a couple examples; https://gist.github.com/bgrabow/0306387873ec31e053091eff73c50626

mattly 2018-12-08T05:18:57.897900Z

so is it just me or is day8 part 1 really unclear how you're supposed to split up child nodes?

gklijs 2018-12-08T05:20:37.898200Z

It's clear to me

mattly 2018-12-08T05:21:51.898400Z

hm

mattly 2018-12-08T05:24:17.898600Z

ok i think i got it

gklijs 2018-12-08T05:27:02.898700Z

just tries in the repl (def test-set (sorted-set "d" "c" "r" "m" "a")) gives #{"a" "c" "d" "m" "r"} and (conj "n" test-set) evaluates as #{"a" "c" "d" "m" "n" "r"}

gklijs 2018-12-08T05:27:11.898900Z

so it works

gklijs 2018-12-08T05:27:44.899500Z

I just woke up, want to be the first of the team for once

🙂 1
fingertoe 2018-12-08T05:36:59.900200Z

My day 7: https://github.com/jreighley/advent-of-cljc/blob/master/src/aoc/y2018/d07/jreighley.cljc I would love some code review — I am a lonely self taught hack. 😉

ClashTheBunny 2018-12-08T05:42:29.900400Z

Yeah, that's a whole ton more readable. The way I was doing it I was losing some keys when I tried that. Do you not have to enumerate ll the keys, or just the ones you use?

2018-12-08T05:46:54.900600Z

All the data will be preserved if you bind the whole map in your arg list (the :as the-data part).

2018-12-08T05:47:31.900800Z

And then instead of returning a map from scratch, you return the result of calling (update the-data k f)

2018-12-08T05:49:51.901Z

(let [m {:a 1 :b 2 :c 3}]
  (update m :b inc)) ; => {:a 1, :b 3, :c 3}

2018-12-08T05:51:22.901200Z

@clashthebunny I think the second example in my gist was a little off. If you have a brand new value for a key, you should use assoc. If you want to apply a function on the old value to get the new value, you should use update. Hope that helps.

2018-12-08T05:59:54.902Z

I’m really curious to see other people’s approaches to stream processing today.

mattly 2018-12-08T06:18:44.902500Z

I'm done with part 1, my solution is in my own repo though

gklijs 2018-12-08T06:40:16.902900Z

There is a very sneaky thing in part 2

mattly 2018-12-08T06:42:58.904300Z

yeah

gklijs 2018-12-08T06:43:27.904600Z

You might even say the business requirements aren't clear

mattly 2018-12-08T06:44:17.904900Z

mm, I'd say they're off by a small amount

athos 2018-12-08T06:48:51.905800Z

Today's was relatively easy, compared to yesterday's 😃

baritonehands 2018-12-08T07:54:19.907600Z

My favorite part of day 7 was my fn to parse the line:

(defn parse-line [line]
  (let [[[lhs] [rhs]] (->> (str/split line #"tep ")
                           (drop 1))]
    [lhs rhs]))

baritonehands 2018-12-08T07:58:07.908100Z

Day 8 was definitely easier, day 7 was the hardest so far for me

helios 2018-12-08T08:02:39.909200Z

i've never worked with zippers, and therefore I am having troubles wrapping my head about parsing day 8 😞

baritonehands 2018-12-08T08:04:08.909600Z

I didn't use zippers, just regular split by space

baritonehands 2018-12-08T08:04:21.910Z

but I did use trampoline for the first time to avoid a stack overflow

fellshard 2018-12-08T08:25:18.910500Z

I didn't end up with a deep enough tree to have to worry about stack overflows. Maybe I should test it against other inputs.

2018-12-08T11:00:56.910900Z

No stack overflow for me, raw recursion worked fine.

2018-12-08T11:40:31.914900Z

I think I had similar pains as you @helios, my solution of having a functional parser required using both stack-recursion and loops for state magenement which is unfamiliar for me to piece together. soln: https://github.com/rymndhng/advent-of-clojure/blob/master/src/advent_2018/08.clj

benoit 2018-12-08T12:11:57.915800Z

My solution for Day 8: https://github.com/benfle/advent-of-code-2018/blob/master/day8.clj

benoit 2018-12-08T12:12:40.916500Z

It's always painful to write a parser in a functional style so I did it with local state 🙂

pesterhazy 2018-12-08T13:27:10.917400Z

My day 8: https://github.com/pesterhazy/advent2018/blob/master/src/advent/puzzle08.clj#L37 - I took the functional route

pesterhazy 2018-12-08T13:29:27.919500Z

- bad: I was stuck for half an hour because I didn't realized that children are 1-indexed (why??) - good: In the process I rediscovered clojure.tools.trace (which I'm sure will be useful later on)

uneman 2018-12-08T13:37:41.923Z

I'm trying to use clojure.core.reducer/fold with @.mfikes's day 5 solution. https://gist.github.com/namenu/21e5d99989fddb1447ba446ca53e40a6

uneman 2018-12-08T13:37:55.923300Z

But I don't know why the merging fn is not called. 😞 Any advice?

pesterhazy 2018-12-08T13:46:03.924900Z

Started a journal to remember the problems I'm running into and maybe come up with some conclusions: https://github.com/pesterhazy/advent2018/blob/master/journal.md#L1

2018-12-08T13:49:51.925200Z

I’ve actually never seen/used volatile! before. Looks like a new 1.10 thing? Time to learn something new 🙂

pesterhazy 2018-12-08T13:53:04.925400Z

they've been there since 1.7 https://github.com/clojure/clojure/blob/master/changes.md#21-transducers

pesterhazy 2018-12-08T13:53:42.925700Z

not sure if they're documented except for the (tautological?) docstrings

2018-12-08T13:54:34.926300Z

I found this, https://stackoverflow.com/questions/31288608/what-is-clojure-volatile#comment50623688_31288608 - looks like a good summary

gklijs 2018-12-08T13:59:15.927300Z

It's pretty clear in the text to ignore the 0, and use the 1's as zero. Your lucky with using clojure since sometimes the index is higher then the number of children. With clojure they must are ignored, which not always is a good thing.

uneman 2018-12-08T14:00:55.927800Z

@athos Oh, that's the point! thanks 😄

😉 1
pesterhazy 2018-12-08T14:05:18.928Z

I'm talking about the "meta-data`, which (in my test data) includes no 0s

pesterhazy 2018-12-08T14:06:05.928200Z

I agree that it's clear from the text (I was hasty once more)

pesterhazy 2018-12-08T14:07:54.928400Z

I wonder is there a rule of thumb when volatiles are safe to use

pesterhazy 2018-12-08T14:08:09.928600Z

and when atoms are required instead

pesterhazy 2018-12-08T14:17:32.929400Z

@mfikes almost identical to mine!

mfikes 2018-12-08T14:18:19.930100Z

Wow!

pesterhazy 2018-12-08T14:20:04.931Z

differences - reduce vs loop (I think I prefer loop here) - different tree-seq params (not sure why mine works)

pesterhazy 2018-12-08T14:25:34.931300Z

just discovered the private leaderboard

2
ClashTheBunny 2018-12-08T14:45:11.934Z

I'm getting a spec error on my local machine from time to time on the advent-of-cljc tests. Does anybody know what I'm doing wrong? This compiled fine last night...

ClashTheBunny 2018-12-08T14:45:19.934100Z

=== Running clojure test aoc.y2018.d07.clashthebunny

Running tests in #{"src"}

Testing user

Ran 0 tests containing 0 assertions.
0 failures, 0 errors.

=== Running cljs test aoc.y2018.d07.clashthebunny
#error {
 :cause Library name must be specified as a symbol in :require / :require-macros; offending spec: [] at line 1 /Users/ranmason/code/advent-of-cljc/cljs-test-runner-out/gen/cljs_test_runner/gen.cljs
 :data {:file #object[java.io.File 0x70c69586 /Users/ranmason/code/advent-of-cljc/cljs-test-runner-out/gen/cljs_test_runner/gen.cljs], :line 1, :column 1, :tag :cljs/analysis-error}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message Library name must be specified as a symbol in :require / :require-macros; offending spec: [] at line 1 /Users/ranmason/code/advent-of-cljc/cljs-test-runner-out/gen/cljs_test_runner/gen.cljs
   :data {:file #object[java.io.File 0x70c69586 /Users/ranmason/code/advent-of-cljc/cljs-test-runner-out/gen/cljs_test_runner/gen.cljs], :line 1, :column 1, :tag :cljs/analysis-error}
   :at [cljs.analyzer$error invokeStatic analyzer.cljc 718]}]

ClashTheBunny 2018-12-08T14:46:00.934300Z

That file is generated with the empty brakets at the top:

cat /Users/ranmason/code/advent-of-cljc/cljs-test-runner-out/gen/cljs_test_runner/gen.cljs
(ns cljs-test-runner.gen
       (:require [doo.runner :refer-macros [doo-tests]] []))

ClashTheBunny 2018-12-08T14:49:21.934900Z

I've done a git clean -fdx, so I am pretty sure I'm not being bitten by cache.

mfikes 2018-12-08T14:51:59.937700Z

@pesterhazy Yeah, both bother me a little: loop directly says what you are doing, albeit at a very low level, and it feels like I'm shoehorning reduce by driving it with range and essentially ignoring the range values. What you really want to do in words is "iterate over this n times". I've updated my solution to try to be closer to that: https://github.com/mfikes/advent-of-code/commit/7c60c2b1468e1863a30ba5ec9573f9a12d12736e

2018-12-08T14:52:21.938Z

As a beginner I’d like to ask why you prefer loop over reduce here?

pesterhazy 2018-12-08T14:53:58.939200Z

yeah iterate seems like the most descriptive choice (I actually considered but discarded it - not sure why)

pesterhazy 2018-12-08T14:54:48.939400Z

essentially because the 2nd argument in the reduce-fn is ignored

2018-12-08T14:55:17.939600Z

I just saw you mentioned it in the main thread. Thanks tons!

mfikes 2018-12-08T14:56:44.939800Z

@clashthebunny What is that empty vector doing at the end?

mfikes 2018-12-08T14:57:13.940Z

(Of your ns form.)

ClashTheBunny 2018-12-08T14:57:25.940200Z

It's an autogenerated file from cljs_test_runner.

ClashTheBunny 2018-12-08T14:58:18.940400Z

So I assume I made either made an egregious error in the clojure side of things or I have a bug in the versions of things I use...

mfikes 2018-12-08T14:59:40.940600Z

That empty vector would normally have the test namespaces listed.

mfikes 2018-12-08T14:59:59.940800Z

Mine looks like:

(ns cljs-test-runner.gen
       (:require [doo.runner :refer-macros [doo-tests]] [aoc.y2018.d08.mfikes]))

mfikes 2018-12-08T15:00:23.941Z

Perhaps you deleted the deftest?

mfikes 2018-12-08T15:02:39.941600Z

No... that doesn't provoke that kind of failure.

ClashTheBunny 2018-12-08T15:02:45.941800Z

Damn! I figured it out.

ClashTheBunny 2018-12-08T15:03:13.942Z

It's the whole uppercase wasn't allowed in the username and then I ran it again with lowercase.

mfikes 2018-12-08T15:03:22.942200Z

Ahh. Damn!

ClashTheBunny 2018-12-08T15:03:49.942400Z

Thanks for the help!

ClashTheBunny 2018-12-08T15:04:35.942600Z

So script/test-one aoc.y2018.d07.ClashTheBunny works for both cljs and clj, but script/test-one aoc.y2018.d07.clashthebunny only works for clj.

ClashTheBunny 2018-12-08T15:04:56.942800Z

Is this something that would be expected? Should cljs downcase the namespace?

ClashTheBunny 2018-12-08T15:05:06.943Z

Or should clj not be downcasing it?

mfikes 2018-12-08T15:05:35.943200Z

No... this isn't really a case-specific problem. It happens if you ask it to run tests for which there is no namespace.

mfikes 2018-12-08T15:05:53.943400Z

Or maybe you are onto something... hrm.

mfikes 2018-12-08T15:06:42.943600Z

I don't know where the problem lies, either Michiel's script, or upstream in one of the test runners. Perhaps file a ticket against advent-of-cljc.

benoit 2018-12-08T15:10:44.943800Z

My rule of thumb is to use volatile unless I have concurrency. There is also transient for IEditableCollection. https://clojure.org/reference/transients

pesterhazy 2018-12-08T15:14:07.944Z

basically keep them contained in a single fn right?

benoit 2018-12-08T15:27:24.944200Z

There are two aspects: - for correctness: ensure the volatiles/transients are not accessed by multiple threads. They don't ensure atomicity. - for code organization: If I use state I prefer to keep it as local as possible so in this case inside the function

benoit 2018-12-08T15:30:34.946100Z

For some reasons it always bugs me when the functional style forces me to keep all the state around and change my function signatures.

pesterhazy 2018-12-08T15:32:05.946200Z

good points both

mfikes 2018-12-08T15:36:14.946800Z

Yeah, having to thread the remaining sequence through is a bit of a pain for this one.

borkdude 2018-12-08T16:14:26.947800Z

damn, I’m close, but I’m having a stackoverflow. I might have to throw the towel due to time constraints 😢

pesterhazy 2018-12-08T16:16:59.948400Z

funny, I used naive recursion and didn't run into any stack overflows

mfikes 2018-12-08T16:17:45.949Z

Yeah, I think the depth of the tree is smaller than typical stack limits.

borkdude 2018-12-08T16:18:50.950Z

yeah, my solution is probably wrong

borkdude 2018-12-08T16:18:57.950300Z

it works for the test input though

pesterhazy 2018-12-08T16:19:25.950800Z

After a few rounds of yakshaving, I ended up with a script to create the next puzzleNN.clj, usable as clojure -m advent.main: https://github.com/pesterhazy/advent2018/blob/master/src/advent/main.clj#L3

pesterhazy 2018-12-08T16:20:07.951900Z

Even better, scripts/dev automatically starts rebel-readline in the latest puzzle namespace

borkdude 2018-12-08T16:20:08.952Z

cool. there’s also a script like this in advent-of-cljc

pesterhazy 2018-12-08T16:20:51.952200Z

I think I should stop now 🙂

gklijs 2018-12-08T16:21:30.952600Z

If you want you could also make it to get your problem

mfikes 2018-12-08T16:24:44.952900Z

My input data has a depth of 6

2018-12-08T16:32:41.955100Z

As I was doing this I worried there would be some degenerate case where we’d need to save the score for a node to be efficient, like maybe metadata [1 1 1 …} on 5 or 6 nested nodes…

2018-12-08T16:44:24.957200Z

I took this into account and multiplied the node-value by it's frequency, and it is quite a bit faster, but as my full runtime is dominated by parsing the tree, it doesn't make much of a difference.

fellshard 2018-12-08T16:51:04.958300Z

I've been thinking about this, and I really do think it's possible to do both parts as a single, linear pass that doesn't require recursion...

fellshard 2018-12-08T16:55:55.958400Z

Yeah, it's basically just turning the recursion stack into an explicit one. But it would certainly make the parts that consume the stream easier to handle, I suspect, by breaking apart the functions that handle different read states (reading header, reading body, reading metadata)

gklijs 2018-12-08T16:58:09.958600Z

It's possible because I'm doing it, but it's much easier with mutable data, but you can have that as well in clojure.

2018-12-08T17:03:32.958800Z

I had the same. The test input isn’t stacked deeply. Do you need another test input? 2 1 3 3 0 1 2 0 3 7 8 9 1 1 0 2 6 12 1 4 1 2 1 3 0 1 17 1 4 4 2

2018-12-08T17:09:52.959100Z

That one broke my first implementation as did the real data.

fellshard 2018-12-08T17:11:15.959300Z

I still enjoy the lisp-y way of pushing environments onto an explicit stack. That said, I'm probably making life hard for myself 🙂

2018-12-08T17:21:03.959500Z

I can see how to do that with part 1 but with part 2 I don’t think I stand a chance to to something without a second pass. Unless I don’t understand what you mean with “second pass” :thinking_face:

borkdude 2018-12-08T17:28:19.959800Z

thanks, I’ll try

2018-12-08T17:28:46.960Z

If you need the numbers for part 1 or 2, just tell me.

2018-12-08T17:29:01.960200Z

(They’re comfortable enough to do by hand)

borkdude 2018-12-08T17:29:47.960500Z

can you tell me the number for the test input you just gave me?

2018-12-08T17:32:19.960700Z

Part 1: 80

2018-12-08T17:32:26.960900Z

Do you want Part 2 as well?

borkdude 2018-12-08T17:41:50.961100Z

I get 80 as well

fellshard 2018-12-08T18:02:31.961300Z

Accumulating your total with a single walk through the tree's data, beginning to end, no back-tracking

fingertoe 2018-12-08T18:34:02.962700Z

Do we have a private leaderboard on AoC ?

2018-12-08T18:34:24.963300Z

sweet

2018-12-08T18:34:37.963800Z

but the real file still doesn’t work? 😮

2018-12-08T18:36:09.964200Z

Urgh. Nope. I couldn’t do that. But I will now attempt to use tree-seq for walking the tree after I built it… I also want to change how I built the tree because it’s s l o w.

mfikes 2018-12-08T18:37:16.964900Z

Yes, the invite code is in the little bit of text next to the pin icon and at https://github.com/adventofcode-clojurians/adventofcode-clojurians#leaderboard

2018-12-08T18:52:22.965400Z

Thanks. And OMG I am not last

borkdude 2018-12-08T18:53:15.965600Z

yeah

2018-12-08T18:54:48.965800Z

I’m sorry that the additional test input didn’t help 😞

borkdude 2018-12-08T18:55:00.966Z

no problem

2018-12-08T18:55:33.966200Z

Have you checked your iterations?

2018-12-08T18:55:38.966400Z

Hang on.

2018-12-08T18:55:52.966600Z

Have you considered that there is a newline at the end of the test file?

2018-12-08T18:56:23.966800Z

(That one kicked my bucket a few times already and I guess that’s not it. But as a tester I have to ask 😉 )

borkdude 2018-12-08T19:09:47.967100Z

got it now

2018-12-08T19:12:41.967300Z

\o/

2018-12-08T19:12:44.967500Z

what was it?

2018-12-08T19:30:56.968300Z

I’m almost certain that this will turn into manually managed frames.

dmitrygusev 2018-12-08T19:46:36.969100Z

my solutions: https://gist.github.com/dmitrygusev/316119976f77368eb9356aa82a0d0b17

dmitrygusev 2018-12-08T19:49:15.970900Z

they’re raw and not refactored after I’ve got correct answer, which should stress the pain I had while solving them 🙂

dmitrygusev 2018-12-08T19:49:46.971400Z

I’m new to clojure and lisp

2018-12-08T19:53:14.971700Z

man….

2018-12-08T19:53:47.972300Z

I’ve gone back and forth between reifying data and doing things algorithmically during AoC

2018-12-08T19:54:10.972800Z

I feel like the results are all over!

2018-12-08T19:54:26.973100Z

Today’s is so much better if you just build the tree.

2018-12-08T19:55:24.973500Z

well… I suppose I’m conflating “reify data” with “use sequence fns”

2018-12-08T19:55:30.973800Z

so reifying the data is probably always worth

2018-12-08T19:55:51.974300Z

sequence fns — not so much. Often too slow for the task when it comes to AoC

2018-12-08T20:12:20.975900Z

Uhm… I just learned a new word. Reify. I am not sure yet if I understand it completely though I consulted a lexicon

2018-12-08T20:24:58.977500Z

:shocked_face_with_exploding_head: I just learned that a test that runs in 1s with vectors can run 40s if I use lists. I guess it’s worth deciding the right way!

2018-12-08T20:30:51.979500Z

In this case: There’s an implied data structure in the sequence of numbers for Day 8. Reifying it means to make it into clojure maps, lists, and vectors instead of requiring pre-understood knowledge.

2018-12-08T20:32:31.980Z

Structuring it? Like building a tree?

2018-12-08T20:33:41.980200Z

Text is hard 😄

2018-12-08T20:34:05.980700Z

Yepp. Especially when you’re not a native speaker 😄

dmitrygusev 2018-12-08T20:34:30.981300Z

I’m still finding it difficult to estimate computational complexity of an algorithm in Clojure 😕

2018-12-08T20:34:46.981400Z

I’m far from it, too 😄

2018-12-08T20:35:22.981600Z

But I am learning tons by AoC. First I try to solve it and now I am trying to optimize and to try things out.

2018-12-08T20:35:48.981800Z

It is a tree, but it’s represented as a list of numbers. Better is to make the relationships explicit.

2018-12-08T20:36:13.982Z

So instead of

[2 0 0 3 10 11 12]
Do
{:metadata []
 :children [{:metadata [10 11 12]}]}

2018-12-08T20:36:41.982200Z

How do you walk the first? Well… You the developer must be told what each number means.

2018-12-08T20:37:01.982500Z

How do you walk the second? The relationships are explicit in the structure. It’s immediately obvious.

benoit 2018-12-08T20:37:40.983100Z

There are some information about the complexity of the Clojure data structures here: https://clojure.org/reference/data_structures#Collections

2018-12-08T20:37:51.983200Z

@dmitrygusev Do you have an example?

dmitrygusev 2018-12-08T20:38:42.983400Z

pick any from the gist I’ve posted, i.e. day1 pt 2

dmitrygusev 2018-12-08T20:39:26.983600Z

the problem is there are plenty of built-in functions whose complexity is unknown

2018-12-08T20:39:52.983800Z

I have four Revisions in this gist and especially the difference between Rev 3 and Rev 4 are mind blowing https://gist.github.com/MeikeMertsch/f1f3a1bfc157c3ed3a6cfcb1dec0ff57

dmitrygusev 2018-12-08T20:40:13.984200Z

> their specific behavior is slightly different for different types of collections this ^

2018-12-08T20:40:43.984300Z

@dmitrygusev I’m not sure what you mean by that statement. The complexity is pretty well stated for most operations on most structures.

2018-12-08T20:41:03.984500Z

But it is sometimes polymorphic. So you must be aware of the type of the underlying structure.

2018-12-08T20:44:00.984700Z

@meikemertsch Is there a particular change you’re interested in hearing about. Instead of “this whole diff,” it’s easier to talk about, “This change from concat to conj” or whatever.

dmitrygusev 2018-12-08T20:44:31.985Z

(map-invert
          (frequencies
            (flatten
              (vals
                ids-by-minutes))))
i.e. how can you estimate complexity for the above?

2018-12-08T20:45:45.985200Z

O(n) (3*n I think)

2018-12-08T20:46:02.985400Z

sry 2*n

2018-12-08T20:46:08.985600Z

but O(n) anyways

2018-12-08T20:47:06.986800Z

flatten is lazy O(n), frequencies is eager O(n), map-invert is eager O(n). The lazy will get rolled into the first eager O(n) so it doesn’t contribute.

2018-12-08T20:47:49.987900Z

Language is hard… what’s “O(n)“?

mfikes 2018-12-08T20:48:07.988500Z

Once you fundamentally get your algorithm sorted, you can often tweak things to ensure optimizations like chunked sequences or directly reducible collections help.

2018-12-08T20:48:23.988600Z

oh. Just check the diff from rev 3 to 4. it’s just two lines. And really just a conversion

2018-12-08T20:48:54.988800Z

But it’s obviously not polynomial or more. It’s going over some data a few times.

dmitrygusev 2018-12-08T20:49:27.989Z

yeah, I meant the C in front of O(n) is difficult to estimate

2018-12-08T20:49:52.989200Z

@meikemertsch The last revision changes behavior. It’s not an isolated optimization.

dmitrygusev 2018-12-08T20:49:54.989400Z

knowing something is O(n) helps, for sure

2018-12-08T20:50:18.989600Z

Right, gotcha. So is it the laziness that’s difficult?

2018-12-08T20:50:19.989800Z

I noticed. 39 seconds worth of a behavioral change

dmitrygusev 2018-12-08T20:50:31.990Z

y

2018-12-08T20:50:57.990200Z

Yeah, that takes a while to get used too, I agree.

2018-12-08T20:51:18.990400Z

@meikemertsch One of those should return an incorrect result, I would presume.

2018-12-08T20:51:38.990600Z

So it might be faster because you’ve dropped some data. idk the context.

2018-12-08T20:52:57.990800Z

no. Both rune fine. Before trying that out I changed all peeks, pops and conjs, so they would work the same for vecs and lists

2018-12-08T20:53:38.991100Z

that’s why the vector version is so slow already. With peeks, pops, and conjs I gain almost half a second speed (see version 2)

2018-12-08T20:53:54.991400Z

ah I’m sorry, I misread this

2018-12-08T20:54:48.991600Z

Obviously I access data WAY more often from the end than from the front. And lists aren’t built for that, right??

2018-12-08T20:54:57.991800Z

Okay, so you’re running into the same lazy evaluation issues @dmitrygusev was talking about

2018-12-08T20:55:10.992Z

calling vec goes over all the data immediately

2018-12-08T20:55:22.992200Z

so you’re potentially adding a lot of extra processing

2018-12-08T20:55:33.992400Z

depending on the length of the list

2018-12-08T20:56:27.992600Z

using vec made me 39seconds (!) faster (:shocked_face_with_exploding_head: )

dmitrygusev 2018-12-08T20:57:22.992900Z

vec vs list is like array with direct access vs linked list, get element from vec is O(1), from list it’s O(n)

2018-12-08T20:57:24.993100Z

So I think I’m misunderstanding the question 🙂 It looks like you took out calls to vec (I presume to make it faster)

2018-12-08T20:58:12.993300Z

But, in general, there’s a lot going on in the solution, so it’s difficult to characterize where it’s spending its time.

2018-12-08T20:59:57.993600Z

haha. Sorry for the confusion. My tests ran 500msec and I wanted them faster so I checked my collection operations and spotted that I did a whole lot of conversions to vectors. So I refactored them out. With the result that everything was s l o w e r

2018-12-08T21:00:11.993800Z

😄 😄 😄

2018-12-08T21:00:20.994Z

so let’s talk about butlast

2018-12-08T21:00:46.994200Z

the docstring on it directly says it’s a linear scan

2018-12-08T21:01:06.994400Z

pop is constant time

2018-12-08T21:01:48.994600Z

I’m not certain that’s your issue, but that’s a common mistake

2018-12-08T21:06:52.994900Z

I am quite impressed with what you can read out of those docs. Most of the internals are just “blahb” to me

2018-12-08T21:07:06.995100Z

I can read the words but I don’t understand what they mean.

2018-12-08T21:10:00.995600Z

At least I figured out the tree-seq again. I am fairly happy with that

mfikes 2018-12-08T22:16:45.996600Z

Nice. Very similar to Paulus' and mine. 🙂

borkdude 2018-12-08T22:18:21.996800Z

it took me too long…

mfikes 2018-12-08T22:19:40.997400Z

Did you start with the tree approach? Or something optimized for part 1 that was then converted to tree?

borkdude 2018-12-08T22:21:10.997700Z

no, I didn’t start with the tree

borkdude 2018-12-08T22:21:19.998Z

I had another solution that only gave me the meta values

mfikes 2018-12-08T22:22:11.998400Z

Yeah, I suspect if you go down that path, then part 2 becomes exceedingly difficult.

borkdude 2018-12-08T22:23:13.998900Z

CLJ:

Testing aoc.y2018.d08.borkdude
part-2 took 7.98 msecs
part-1 took 2.81 msecs

Testing aoc.y2018.d08.iamdrowsy
part-2 took 10.25 msecs
part-1 took 14.21 msecs

Testing aoc.y2018.d08.mfikes
part-2 took 18.30 msecs
part-1 took 21.29 msecs
CLJS:
Testing aoc.y2018.d08.borkdude
part-1 took 20.00 msecs
part-2 took 2.00 msecs

Testing aoc.y2018.d08.iamdrowsy
part-1 took 58.00 msecs
part-2 took 38.00 msecs

Testing aoc.y2018.d08.mfikes
part-1 took 120.00 msecs
part-2 took 76.00 msecs

mfikes 2018-12-08T22:24:18.999500Z

Nice, a rare appearance of trampoline 🙂

borkdude 2018-12-08T22:25:33.000200Z

I noticed that too 🙂

mfikes 2018-12-08T22:25:35.000400Z

Lots of solutions involving the expression

[{:children children, :metadata metadata} the-rest-of-the-seq]
🙂

✔️ 2
Average-user 2018-12-08T22:26:12.000700Z

I'm not even sure if is correctly placed

2018-12-08T22:26:17.001Z

mine too

mfikes 2018-12-08T22:26:44.001600Z

If we had a state monad that we were all used to using maybe we could avoid that. Othewise this aspect was troublesome.

borkdude 2018-12-08T22:27:24.002300Z

I had [n-children n-meta & nums]

2018-12-08T22:27:40.002800Z

I used an integer position instead of the-rest-of-the-seq, and left the input vector untouched.

2018-12-08T22:27:44.003100Z

you have an outline of how state monad would have helped? i dont see it

mfikes 2018-12-08T22:27:49.003500Z

@borkdude Yeah, you had

[{:meta (vec meta)
          :children children} rest]

2018-12-08T22:28:06.004200Z

just a poorly formatted tree afaict

borkdude 2018-12-08T22:28:21.004700Z

I could probably optimize that by not going through a seq at all, but staying in a vec

Average-user 2018-12-08T22:28:46.005800Z

I had no time yesterday to read, but how did you approach part2 of day 7?

mfikes 2018-12-08T22:28:53.006100Z

The way I see it, you have this extra appendage you have to thread through all of your calls, which is state you need to pass around. Perhaps a monad of some sort would help hide a bit of that complexity.

borkdude 2018-12-08T22:29:21.006500Z

that’s what the state monad is for yes

2018-12-08T22:29:47.007300Z

uh, I could def be wrong, I don’t think it helps in recursive situations

mfikes 2018-12-08T22:30:06.007800Z

Otherwise lots of [what-i-want extra-crap] destructuring, along with passing extra-crap around.

Average-user 2018-12-08T22:30:44.008500Z

https://github.com/glguy/advent2018/blob/master/execs/Day08.hs (solution with State Monad)

mfikes 2018-12-08T22:30:45.008600Z

Yeah, I don't have enough experience with state monads to know if they work in recursive situations. Well, I have nearly zero experience.

borkdude 2018-12-08T22:31:43.009700Z

I worked through the http://HaskellBook.com this year. I have a little bit of experience with the State monad, and StateT monad transformer.. but I’m not using that a lot so just a matter of time before I forget again

2018-12-08T22:32:43.010300Z

well aren’t we just a bunch of dynalang apes 😄 :troll:

2018-12-08T22:34:14.011300Z

:lol:

2018-12-08T22:34:37.011800Z

I saw that. And I appreciated it while it lasted 😛

borkdude 2018-12-08T22:34:43.012200Z

Haskell: banging on the type system until it works. Clojure: banging on the REPL until it works.

borkdude 2018-12-08T22:35:13.012800Z

you saw what?

2018-12-08T22:35:43.013200Z

your original posting re: haskell

2018-12-08T22:36:07.013400Z

just before you deleted it

pesterhazy 2018-12-08T22:36:28.013800Z

does anyone know any other interesting users coming from other language to follow? The postgres guy is super interesting https://github.com/xocolatl/advent-of-code/tree/master/2018

borkdude 2018-12-08T22:36:29.013900Z

oh yeah 😉

pesterhazy 2018-12-08T22:36:47.014400Z

(this was mentioned here a few days ago, thanks for that)

borkdude 2018-12-08T22:36:53.014600Z

no problem 😉

borkdude 2018-12-08T22:37:28.016Z

I was on a private leaderboard with him last year and one PureScript user (so three different langs). it was fun to see the different solutions

borkdude 2018-12-08T22:38:24.017Z

oh wow, impressive @lucaspolymeris

pesterhazy 2018-12-08T22:39:01.017500Z

chapeau @lucaspolymeris!

Average-user 2018-12-08T22:40:16.018600Z

There are some missing stuff, and others very slow . So if you know Prolog glad to accept PRs

pesterhazy 2018-12-08T22:40:48.019100Z

This list looks great: https://github.com/Bogdanp/awesome-advent-of-code

taylor 2018-12-08T22:45:58.019700Z

I don’t think it’s doing anything, because parse-data never returns a function

mfikes 2018-12-08T22:46:24.020300Z

These Scala solutions look more compact that I would have expected. (Perhaps the author is golfing or that's fairly idiomatic?) https://github.com/FlorianCassayre/AdventOfCode-2018

pesterhazy 2018-12-08T22:48:16.021200Z

Yes that looks pretty good, better than most of the haskell/ocaml solution I've looked at

mfikes 2018-12-08T22:48:48.021700Z

Yeah, I'm leaning towards the idea that the author is pretty good.

taylor 2018-12-08T22:50:58.022600Z

I think I’ve convinced myself that solving day 8 w/o recursion would require some gnarly stack juggling

2018-12-08T22:53:42.022800Z

yes

2018-12-08T22:54:17.023800Z

you’d have to basically re-implement call stack frames 😄

2018-12-08T22:54:40.024400Z

“here’s all the state we had at this frame, and where we left off when we were here”

2018-12-08T22:55:06.024800Z

(Just for part 2. I did stack-based in part 1 for funsies.)

taylor 2018-12-08T22:57:05.026100Z

I feel like day 8 is foreshadowing a problem where direct recursion won’t be feasible 😰

😬 1
borkdude 2018-12-08T23:01:07.027400Z

last year (2017) I saw someone write here: in 2016 the puzzles were harder, now they’re sometimes too easy. I haven’t heard that this year yet?

taylor 2018-12-08T23:02:49.028700Z

I feel like first week of 2018 is slightly more challenging than first week of 2017

Average-user 2018-12-08T23:02:56.028800Z

I think untill now, hardness has been equivalent to 2017

taylor 2018-12-08T23:03:32.029400Z

by 2030 AoC will have exhausted every problem but P=NP

😆 2
pesterhazy 2018-12-08T23:11:32.030100Z

Nice F# solution - also has to thread through the "remainingTree"

gklijs 2018-12-08T23:12:52.032700Z

Probably once you've done them for one year it also becomes easier? It's a pretty specific kind of problems.

mfikes 2018-12-08T23:13:45.033Z

Yeah it is interesting;

let meta, remainingTree = List.splitAt metadata tree'
and
val (metadata, other) = right.splitAt(nMetadata)
and
(let [[meta rest] (split-at n-meta nums)]
all look very similar

1
mfikes 2018-12-08T23:15:18.033900Z

(We are all roughly employing the same algorithm, even using the language's built-in "split at" functions.) That's F#, Scala, Clojure

taylor 2018-12-08T23:19:25.034300Z

here’s a day 8 stack-based solution https://www.reddit.com/r/adventofcode/comments/a47ubw/2018_day_8_solutions/ebc99t8/

❗ 1
mfikes 2018-12-08T23:23:20.035800Z

I think there's something about this particular problem that forces you down a similar path (whereas other problems admit a richer variety of approaches.) I found James Henderson's bit of code here https://github.com/jarohen/advent-of-code/blob/master/2018/src/aoc2018/day8.clj#L9-L20 way too similar to mine here https://github.com/mfikes/advent-of-code/blob/b89aff099c2dd42928e038f3d70344b685f7d889/src/advent_2018/day_08.cljc#L9-L18

borkdude 2018-12-08T23:26:00.036500Z

he used reduce where you used iterate right?

mfikes 2018-12-08T23:26:36.037600Z

I only later changed mine to iterate after the conversation with Paulus

mfikes 2018-12-08T23:27:09.038400Z

reduce over range was my first approach

borkdude 2018-12-08T23:29:08.039300Z

both make sense to me. reduce with a counter could also have been used, but that starts to look like a normal loop

mfikes 2018-12-08T23:32:43.039900Z

I think I learned the iterate / nth pattern from Bruce from last year