Fork me on GitHub
#adventofcode
<
2017-12-11
>
minikomi02:12:27

Nice weekend everyone? 😄

minikomi02:12:12

got day9.. should have used a map and not vars for the loop/recur

grzm02:12:26

too bad you can't change it 🙂 (git records all of our sins)

dpsutton02:12:02

force push to the rescue

minikomi02:12:33

lol. i like having the history of my refinements for AoC

mfikes02:12:11

@minikomi Nice solution! Your throw may make things more robust, but if the input is valid, I think you should be able to take the three cases \, \newline, and \! and eliminate them, if you take the result-expr for \, and use it instead of the (throw ...).

minikomi02:12:04

yeah, i just had it there to refine my solution.. catch (ha!) the times it went awry.

mfikes02:12:37

Instead of trying to say it in words, this variation on your solution works for me: https://gist.github.com/mfikes/57c1b666c30bb5fd98b235df87b5c189

minikomi02:12:32

oh, is cancel guaranteed to only be in garbage? that's good then!

mfikes02:12:03

Right, I think you can interpret the problem definition that way. And it seems to be borne out by the input data.

minikomi02:12:11

there 🙂 credited you in the commit heh

minikomi04:12:32

man this wording for day 10 part 2 is confusing.

minikomi04:12:36

If the suffix is added, there's 8 3, 4, 1, 5, 17, 31, 73, 47, 23 as the steps.. but the skip sequence carried over is 4 ?

minikomi04:12:56

rather than 9, since 9 steps have occured..?

minikomi04:12:21

oh, ok i got it.

minikomi05:12:31

reductions 💌

fellshard05:12:57

I've gotta search for the number of times part 2 has been reduce -> reductions

dyankowsky05:12:15

I've used Clojure for all three years, and I feel like some of the earlier problems are easier to solve in a procedural style, but I feel like functional languages really start to shine after a few days.

dyankowsky05:12:04

Though the hash cracking one from... last year?... was a bit tough... I had to learn more about Java interop to make it fast

fellshard05:12:24

I'd love to go through and solve these with different paradigms, hone a sense for what gets easier and what gets harder

fellshard05:12:27

Also had Proto Repl finally set up on my laptop for this round 😄

mikelis06:12:17

@fellshard same here, but right now trying to decide between “pretty” with reduce/`reductions` vs 30x faster with apply

minikomi06:12:24

(apply str (map #(format "%02x" %) xored)) Was pretty happy wit that hexidecimal-string-conversion 😄

minikomi06:12:40

format is such a beast

orestis09:12:26

Hi all! @fellshard Indeed, “coda” is a musical term; It literally means “tail” in Italian. It refers to the bars that come after a repeating part. I don’t know how it popped into my mind, but I like it better than “tail” which can be confusing when destructuring linked lists.

orestis09:12:37

Today I didn’t have much time to arrive to the solution from first principles; I had to lookup hex grids and how they work.

orestis09:12:19

I’ve included a link to a nice article in my solution code.

borkdude10:12:29

Day 11 is a bit difficult for me

borkdude10:12:49

I’ll peek at @orestis's link

karlis12:12:19

my solution for today: https://github.com/skazhy/advent/blob/master/src/advent/2017/day11.clj with a handy ascii art on how the coordinates are handled.

mikelis12:12:55

In my opinion, today’s challenge lent itself well to one of the most elegant & concise solutions this year so far https://github.com/axelarge/advent-of-code/blob/master/src/advent_of_code/2017/day11.clj

orestis12:12:57

@mikelis.vindavs That is indeed very nice.

borkdude13:12:20

Did anyone else get emotional while reading > “It’s my child process,” she says, “he’s gotten lost in an infinite grid!”

nooga13:12:41

cube coordinates everywhere 😄

borkdude13:12:45

@mfikes isomorphic once again

borkdude13:12:11

I have to admit without the hint about cube coordinates I would still be thinking right now

mfikes13:12:52

Me too. I did some quick research and chose that coordinate system because it makes calculating distance trivial.

borkdude13:12:45

The photo in the spoiler thread above did it for me

nooga13:12:08

I’m wrote a game on hex grid once so it was a no-brainer

erwin13:12:06

I solved it without cube coordinates, by using the simplified versions of de diagonals for north and south. So NE + NW = (1,1) + (1,-1) = (2,0). Calculation is simple after that, similar to using a Z-axis.

mikelis13:12:36

nice approach with the input resolving directly to coordinate tuples 👍:skin-tone-2:

borkdude13:12:08

it seems so simple once you see it

erwin13:12:49

today was fast to compensate for yesterday, which was very slow for me 😁

nooga13:12:48

input/input

nooga13:12:34

woo, i forgot that reductions exists

erwin13:12:49

oow, still a defect? wrote the solution in a repl / nightcode at work and pasted it in github in one file. Let me fix that.

mfikes13:12:01

There is an interesting perf anomaly with @erwin's solve-2 where it runs in 124 ms for me in Clojure vs. 15 ms in self-hosted ClojureScript. Hrm.

borkdude13:12:11

@mfikes sanity check: do they yield the same outcome?

mfikes13:12:39

This was the page I hit for the research I did. It has incredible visualizations of the coordinate systems. https://www.redblobgames.com/grids/hexagons/

borkdude13:12:34

I hit that one too and then I tried the q layouts, but had problems calculating the distance

mfikes13:12:34

I scrolled down to the Distances section and saw that Cube coordinates has a nice formula.

borkdude13:12:32

yeah, that’s the same system as on the photograph, but I was nearly awake then 😉

bhauman14:12:56

ok just finished, I spent some time on paper trying to devine the properties of the system first

bhauman14:12:06

now to see what others did

borkdude14:12:53

+1 for the Christmas ascii art @bhauman

bhauman14:12:39

@borkdude thats from the first advent of code

bhauman14:12:26

oh I see others did this as well, congrats @mikelis.vindavs!!

bhauman14:12:59

oh wait yours is different but I think logically equivalent

mfikes14:12:52

Interesting. @bhauman's also exhibits that odd perf anomaly where part 2 is much faster in Planck.

mfikes14:12:21

90 ms vs. 30 ms

bhauman14:12:40

well its the same work, so maybe its warmed up

mfikes14:12:38

Planck starts off at 90 ms but then drops down to 30 ms. My guess (based on some stuff Timothy Baldridge was saying): JavaScriptCore uses a tracing JIT, so after it sees execution, it can compile things to machine code that relies purely on primitives. There is evidently something tracing JITs can do that the Java VM can't do with its current implementation, but I don't fully appreciate what is going on.

mfikes14:12:05

Perhaps the day 11 problem happens to be highly amenable to tracing analysis, involving a tight loop of math at its core.

borkdude14:12:29

This sounds like an Advent of Code problem in itself

bhauman14:12:31

javascript engines are freaking crazy

borkdude14:12:09

Day 12: > Part 1: some random array walking > Part 2: perhaps the day 12 problem happens to be highly amenable to tracing analysis, involving a tight loop of math at its core. > Determine the time spent after running the algorithm on the output of part 1.

mfikes14:12:32

FWIW, my solution also exhibits the odd perf anomaly: part-2 is 124 ms in Clojure and 19 ms in Planck / JavaScriptCore.

erwin14:12:17

using the tips and tricks from day5 i see some boxed math and reflection optimization possibilities, so I would say that it is indeed the tracing jit

mfikes14:12:33

FWIW, nooga's is also exhibiting the same phenomenon

borkdude14:12:50

@mfikes what about your own?

mfikes14:12:34

Yeah, for me the call to Math/max was using reflection. 😱 My solution dropped from 124 ms to 8 ms with https://github.com/mfikes/advent-of-code/commit/8b71e9a87f7e9dee970fc6f5176edf30bb2569db#diff-71207370594c4dd13d58690ffbff0646

Alonoaky14:12:55

try using (defn abs [n] (max n (- n))) instead

mfikes14:12:57

So, in short, no tracing JIT magic, just plain old reflection being damned slow.

Alonoaky14:12:09

would probably have same effect

borkdude14:12:57

wasn’t this kind of type hint also valid? (defn ^long distance […] …). When I call distance from the REPL it works fine

borkdude14:12:16

But when I call it from another form, I get: java.lang.IllegalArgumentException: Unable to resolve classname: [email protected]

borkdude14:12:09

Short snippet of what I mean:

(defn ^long d [] 1)
(Math/abs (d))

mfikes14:12:56

@borkdude I think that's where they go in ClojureScript, but in Clojure

(defn d ^long [] 1)

mfikes14:12:24

I'm not so sure, TBH.

borkdude14:12:01

cool, 12 ms for both parts now

borkdude14:12:45

why can’t I use ^longs here (instead of annotating each element): https://github.com/borkdude/aoc2017/blob/master/src/day11.clj#L28

mfikes14:12:54

Hmm. ^longs means a primitive array of ^long right?

borkdude14:12:22

> What about when you have a sequence of values, all of a uniform type? Clojure provides a number of special hints for these cases, namely ^ints, ^floats, ^longs, and ^doubles. https://github.com/clojure-cookbook/clojure-cookbook/blob/master/08_deployment-and-distribution/8-05_type-hinting.asciidoc

borkdude14:12:54

works for apply +

borkdude14:12:26

maybe it’s not supported in a destructuring form

borkdude14:12:56

I’ll ask in #clojure

borkdude15:12:44

This works though:

(defn f [[x y z :as ^longs args]]
    (apply + args))

borkdude15:12:23

so I think as long as you’re using the entire sequence, the type hint will work, but not for individually destructured elements

borkdude15:12:39

Turns out + doesn’t need the type hint, so it’s bogus anyway

borkdude15:12:40

This is a bit funny. This give a type hint warning:

(defn f [[x y z]]
  (+ x y z))
but this doesn’t
(defn f [[x y z]]
  (apply + [x y z]))

borkdude15:12:28

I guess because a vector cannot contain primitives anyway

mfikes15:12:54

Hmm @borkdude I don't get a reflection warning on your first form (in Clojure 1.9.0)

mfikes15:12:22

Or, what do you mean by "type hint warning"?

borkdude15:12:58

@mfikes (set! *unchecked-math* :warn-on-boxed)

mfikes15:12:06

Ahh, that's cool. By doing (set! *unchecked-math* :warn-on-boxed) you are essentially saying you want the (+ ...) form to use unchecked math (presumably replacing clojure.core/+ with clojure.core/unchecked-add in some way at compile time), but it is warning that it can't actually employ unchecked math because the values are boxed as Object instances? (Which can be fixed by type hinting them.) But in the second form, + is not being compiled—it is being passed in as a higher-order function to apply, so the result is that you get checked arithmetic regardless.

mfikes15:12:11

I'd like to know why you can't make the second form use unchecked arithmetic by changing it to:

(defn f [[x y z]]
  (reduce unchecked-add [x y z]))

borkdude15:12:34

vectors can’t contain primitives, but not sure if I understand the problem

mfikes15:12:12

OK, so

(unchecked-add Long/MAX_VALUE Long/MAX_VALUE)
but no
(apply unchecked-add [Long/MAX_VALUE Long/MAX_VALUE])

mfikes15:12:38

Also no

(let [ua unchecked-add] (ua Long/MAX_VALUE Long/MAX_VALUE))
Compiler chicanery.

borkdude15:12:54

same reason as before, inlining doesn’t work with higher order?

borkdude16:12:22

the lib is now “archived”?

thegeez16:12:37

I finished an alternate solution for day11 that doesn't use a coordinate system https://github.com/thegeez/clj-advent-of-code-2017/blob/master/src/advent/day11.clj#L166

chrisblom16:12:07

cool, so many different approaches

borkdude17:12:30

@thegeez Care to give us the tl;dr explanation?

thegeez17:12:11

replacement-moves turns two moves into either zero, one or two moves. For instance [:n :s] is the same as doing nothing, [:n :se] is the same as take a single :se step one by one the steps from moves are added to the shortest path, where the added step might undo a previous step, combine with another step into a single step or the step is added

borkdude17:12:58

very creative!

thegeez17:12:06

The first version of that took way too long for part two, but now it works