Fork me on GitHub
#adventofcode
<
2018-12-08
>
fellshard01:12:18

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

ClashTheBunny04:12:28

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?

Ben Grabow05:12:33

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.

Ben Grabow05:12:19

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.

Ben Grabow05:12:16

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)

Ben Grabow05:12:36

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.

ClashTheBunny05:12:29

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?

Ben Grabow05:12:54

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

Ben Grabow05:12:31

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

Ben Grabow05:12:51

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

Ben Grabow05:12:22

@U09NVRNG2 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.

ClashTheBunny14:12:30

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

mattly05:12:57

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

gklijs05:12:37

It's clear to me

mattly05:12:17

ok i think i got it

gklijs05:12:44

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

🙂 4
fingertoe05:12:59

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. 😉

norman05:12:54

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

mattly06:12:44

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

gklijs06:12:16

There is a very sneaky thing in part 2

gklijs06:12:27

You might even say the business requirements aren't clear

mattly06:12:17

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

athos06:12:51

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

baritonehands07:12:19

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]))

baritonehands07:12:07

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

helios08:12:39

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

baritonehands08:12:08

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

baritonehands08:12:21

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

fellshard08:12:18

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.

magic_bloat11:12:56

No stack overflow for me, raw recursion worked fine.

rymndhng11:12:31

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

benoit12:12:40

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

norman13:12:51

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

pesterhazy13:12:42

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

pesterhazy14:12:54

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

pesterhazy14:12:09

and when atoms are required instead

benoit15:12:44

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

pesterhazy15:12:07

basically keep them contained in a single fn right?

benoit15:12:24

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

pesterhazy15:12:05

good points both

pesterhazy13:12:27

- 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)

gklijs13:12:15

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.

pesterhazy14:12:18

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

pesterhazy14:12:05

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

namenu13:12:41

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

namenu13:12:55

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

pesterhazy13:12:03

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

namenu14:12:55

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

😉 4
pesterhazy14:12:32

@mfikes almost identical to mine!

pesterhazy14:12:04

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

meikemertsch14:12:21

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

pesterhazy14:12:48

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

meikemertsch14:12:17

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

pesterhazy14:12:34

just discovered the private leaderboard

prosper 8
ClashTheBunny14:12:11

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...

ClashTheBunny14:12:19

=== 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]}]

ClashTheBunny14:12:00

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]] []))

ClashTheBunny14:12:21

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

mfikes14:12:44

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

mfikes14:12:13

(Of your ns form.)

ClashTheBunny14:12:25

It's an autogenerated file from cljs_test_runner.

ClashTheBunny14:12:18

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...

mfikes14:12:40

That empty vector would normally have the test namespaces listed.

mfikes14:12:59

Mine looks like:

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

mfikes15:12:23

Perhaps you deleted the deftest?

mfikes15:12:39

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

ClashTheBunny15:12:45

Damn! I figured it out.

ClashTheBunny15:12:13

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

mfikes15:12:22

Ahh. Damn!

ClashTheBunny15:12:49

Thanks for the help!

ClashTheBunny15:12:35

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.

ClashTheBunny15:12:56

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

ClashTheBunny15:12:06

Or should clj not be downcasing it?

mfikes15:12:35

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

mfikes15:12:53

Or maybe you are onto something... hrm.

mfikes15:12:42

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.

mfikes14:12:59

@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

pesterhazy14:12:58

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

benoit15:12:34

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

mfikes15:12:14

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

borkdude16:12:26

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

pesterhazy16:12:59

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

mfikes16:12:45

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

borkdude16:12:50

yeah, my solution is probably wrong

borkdude16:12:57

it works for the test input though

meikemertsch17:12:32

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

meikemertsch17:12:52

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

borkdude17:12:19

thanks, I’ll try

meikemertsch17:12:46

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

meikemertsch17:12:01

(They’re comfortable enough to do by hand)

borkdude17:12:47

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

meikemertsch17:12:26

Do you want Part 2 as well?

borkdude17:12:50

I get 80 as well

meikemertsch18:12:37

but the real file still doesn’t work? 😮

meikemertsch18:12:48

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

meikemertsch18:12:33

Have you checked your iterations?

meikemertsch18:12:52

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

meikemertsch18:12:23

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

pesterhazy16:12:25

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

pesterhazy16:12:07

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

borkdude16:12:08

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

pesterhazy16:12:51

I think I should stop now 🙂

gklijs16:12:30

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

mfikes16:12:44

My input data has a depth of 6

norman16:12:41

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…

drowsy16:12:24

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.

fellshard16:12:04

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...

fellshard16:12:55

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)

gklijs16:12:09

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.

fellshard17:12:15

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

meikemertsch17:12:03

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:

fellshard18:12:31

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

meikemertsch18:12:09

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.

potetm19:12:56

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

fingertoe18:12:02

Do we have a private leaderboard on AoC ?

mfikes18:12:16

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

meikemertsch18:12:22

Thanks. And OMG I am not last

dmitrygusev19:12:15

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

dmitrygusev19:12:46

I’m new to clojure and lisp

potetm19:12:47

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

meikemertsch20:12:20

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

potetm20:12:51

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.

meikemertsch20:12:31

Structuring it? Like building a tree?

potetm20:12:41

Text is hard 😄

meikemertsch20:12:05

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

potetm20:12:48

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

potetm20:12:13

So instead of

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

potetm20:12:41

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

potetm20:12:01

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

potetm19:12:10

I feel like the results are all over!

potetm19:12:26

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

potetm19:12:24

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

potetm19:12:30

so reifying the data is probably always worth

potetm19:12:51

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

meikemertsch20:12:58

: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!

dmitrygusev20:12:30

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

meikemertsch20:12:46

I’m far from it, too 😄

meikemertsch20:12:22

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.

potetm20:12:51

@U04V437EA Do you have an example?

dmitrygusev20:12:42

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

dmitrygusev20:12:26

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

meikemertsch20:12:52

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

potetm20:12:43

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

potetm20:12:03

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

potetm20:12:00

@U0A7TVBLN 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.

dmitrygusev20:12:31

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

potetm20:12:45

O(n) (3*n I think)

potetm20:12:08

but O(n) anyways

potetm20:12:06

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.

meikemertsch20:12:49

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

meikemertsch20:12:23

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

potetm20:12:54

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

dmitrygusev20:12:27

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

potetm20:12:52

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

dmitrygusev20:12:54

knowing something is O(n) helps, for sure

potetm20:12:18

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

meikemertsch20:12:19

I noticed. 39 seconds worth of a behavioral change

potetm20:12:57

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

potetm20:12:18

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

potetm20:12:38

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

meikemertsch20:12:57

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

meikemertsch20:12:38

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)

potetm20:12:54

ah I’m sorry, I misread this

meikemertsch20:12:48

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

potetm20:12:57

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

potetm20:12:10

calling vec goes over all the data immediately

potetm20:12:22

so you’re potentially adding a lot of extra processing

potetm20:12:33

depending on the length of the list

meikemertsch20:12:27

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

dmitrygusev20:12:22

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)

potetm20:12:24

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

potetm20:12:12

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

meikemertsch20:12:57

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

potetm21:12:11

😄 😄 😄

potetm21:12:20

so let’s talk about butlast

potetm21:12:46

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

potetm21:12:06

pop is constant time

potetm21:12:48

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

meikemertsch21:12:52

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

meikemertsch21:12:06

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

benoit20:12:40

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

dmitrygusev20:12:13

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

mfikes20:12:07

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

meikemertsch21:12:00

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

mfikes22:12:45

Nice. Very similar to Paulus' and mine. 🙂

borkdude22:12:21

it took me too long…

mfikes22:12:40

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

borkdude22:12:10

no, I didn’t start with the tree

borkdude22:12:19

I had another solution that only gave me the meta values

mfikes22:12:11

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

borkdude22:12:13

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

mfikes22:12:18

Nice, a rare appearance of trampoline 🙂

Average-user22:12:12

I'm not even sure if is correctly placed

taylor22:12:58

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

borkdude22:12:33

I noticed that too 🙂

mfikes22:12:35

Lots of solutions involving the expression

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

✔️ 8
mfikes22:12:44

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

borkdude22:12:24

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

magic_bloat22:12:40

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

potetm22:12:44

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

mfikes22:12:49

@borkdude Yeah, you had

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

potetm22:12:06

just a poorly formatted tree afaict

borkdude22:12:21

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

Average-user22:12:46

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

mfikes22:12:53

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.

borkdude22:12:21

that’s what the state monad is for yes

potetm22:12:47

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

mfikes22:12:06

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

mfikes22:12:45

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

borkdude22:12:43

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

potetm22:12:37

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

borkdude22:12:13

you saw what?

potetm22:12:43

your original posting re: haskell

potetm22:12:07

just before you deleted it

borkdude22:12:29

oh yeah 😉

potetm22:12:43

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

borkdude22:12:43

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

pesterhazy22:12:28

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

pesterhazy22:12:47

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

borkdude22:12:53

no problem 😉

borkdude22:12:28

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

Average-user22:12:16

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

mfikes22:12:24

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

pesterhazy22:12:16

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

mfikes22:12:48

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

taylor22:12:58

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

potetm22:12:17

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

potetm22:12:40

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

potetm22:12:06

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

taylor22:12:05

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

😬 4
borkdude23:12:07

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?

taylor23:12:49

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

Average-user23:12:56

I think untill now, hardness has been equivalent to 2017

taylor23:12:32

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

😆 8
pesterhazy23:12:32

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

gklijs23:12:52

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

mfikes23:12:45

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

truestory 4
mfikes23:12:18

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

mfikes23:12:20

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

borkdude23:12:00

he used reduce where you used iterate right?

mfikes23:12:36

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

mfikes23:12:09

reduce over range was my first approach

borkdude23:12:08

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

mfikes23:12:43

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