Fork me on GitHub
#adventofcode
<
2019-12-03
>
Sam N00:12:55

My day 2. Based on other solutions, I need to learn to use for a bit better, but happy overall. https://github.com/SNordlinger/advent2019/blob/master/2/clj/src/comp.clj

bentrent01:12:58

My day AOC (up to day2) : https://repl.it/@ben_w_trent/aoc2019 Lessons learned: (for [x (range 99) y (range 99)] [x y]) Did not know about for for generating sequences 😄. I was doing some super complex combinatorics and thought that there HAD to be a better way. Glad there is

taylor02:12:56

Also beware range is exclusive upper bound but I think the problem calls for inclusive range

bentrent02:12:44

Ah, cool. Well, my solution was under 99 :).

dpsutton02:12:44

day 2 was a bit simpler since there was only multiplication and addition involved. and they chose quite easy numbers to solve it

dpsutton03:12:17

part 2 is a particularly nice way to add core.logic as well

potetm03:12:03

order of operations tripped me up at the end

potetm03:12:30

I’ve brain-dumped all order of operations rules

mnespor03:12:55

(ns advent.day02.day02
  (:require [clojure.math.combinatorics :as combo]))

(def blah (combo/selections (range 100) 2))

erwinrooijakkers08:12:05

Gets only half the combinations 😉

mnespor15:12:36

It gets 'em all, doesn't it?

advent.day02.day02> (combo/selections (range 3) 2)
((0 0) (0 1) (0 2) (1 0) (1 1) (1 2) (2 0) (2 1) (2 2)

kenj03:12:46

one thing that came up in my brute force search was it wasn’t clear what the best way to break from the search was. I ended up using some, but is there a better way to basically do:

for i in coll:
  if i == search_item:
    return i

kenj03:12:07

thus avoiding searching the rest of the collection?

kenj03:12:46

I’ve read the docs a bunch of times and :when and :while still confuse me for for

erwinrooijakkers08:12:02

for is lazy so when you get the first it terminates early

kenj19:12:46

I thought since sequences are lazy, they might "chunk"? After thinking about it, I think that might be true even for my some usage. The only way to avoid chunking is using reduce/`reduced`, or maybe bypass chunking with lazy-seq?

erwinrooijakkers22:12:37

Why would chunking be a problem?

kenj02:12:42

Because chunking would eval until 32 possible matches are found, or the source coll is exhausted, then first returns to first one. This would be the opposite of termination at the first found.

tws04:12:38

reduced can exit early from a reduction

fellshard04:12:37

Ooh, good idea re: core.logic. I'll have to try it, definitely cleaner than for ...

lilactown04:12:13

@risinglight one thing you can take advantage of is the fact that for is lazy

lilactown04:12:39

So instead of “breaking” from a for loop, you instead can read each element from the sequence it produces until you get your result

rutledgepaulv04:12:38

usually if i want to break i’d reach for loop/recur, or as mentioned reduce/reduced

lilactown04:12:20

ugh I can’t remove the preview on mobile

lilactown04:12:53

github .com/Lokeh/advent-2019/blob/master/day2.org#part-2 (pasting it again so that Slack won’t show the rich preview... which I can’t delete on mobile)

lilactown04:12:18

reduced is also fine but if your data can be reasonably done using for, then take-while is usually a better answer than turning to reduce and reduced

kenj04:12:12

take-while seems like the wrong thing for what is essentially a find of a single item. some I guess is good enough, I was just annoyed I had to modify the pred to rerun the found value https://github.com/KennyMonster/aoc_2019/blob/737ec52c74fea4dc42f856b6b69cb73588e016ba/src/day_2.clj#L66

kenj04:12:50

Would be nice to have the predicate just be a predicate in this particular case

mchampine05:12:10

And… we’re off!

misha06:12:24

@alex.lee.jackson aoc is not a good way to learn clojure. Maybe the first puzzle of each day is, but most of the 2nd ones steer you towards the loop recur pretty consistently, if you don't want to wait for results forever.

nam.hyunwoo07:12:45

loop recur can be decomplected into state & reducing function. I'm curious if you prefer loop recur over a sequential approach. or is it only desireable on 2nd ones for performance reason?

misha07:12:11

it ends up being the same amount of eager code, same early termination, a bunch of state "variables", but reduce is 2 things, 1 of which now has a very hairy fn signature and loads of destructuring

misha07:12:22

besides, most reduces are implemented via loop recur under the hood, so might as well just skip the middle man (especially in context of average aoc part 2 puzzle)

nam.hyunwoo08:12:35

thanks for the explaination! 🙂

misha08:12:55

np. but if reduce fits nicely (whatever that means in the moment) - use it!

fellshard08:12:17

For me, depends on how much state I'm juggling. Too much and I'll reify it as a reduce fn.

misha08:12:26

wow, I tend to loop too much coupled state instead. (in context of aoc. in another context: too much coupled state usually means you have issues somewhere else)

genmeblog13:12:37

I checked my last years code and never used any loop. I used recur sometimes, once custom type to speed the things up. But never needed to use loop/recur. I suppose that what's crucial is a selection of best matching data structure to the problem and to the Clojure.

rjray06:12:00

Day 3 done. This has escalated.

misha06:12:23

just a bit

misha06:12:08

can't even hear CPU fan noises on take-while kappa

mchampine07:12:51

Done. Whew. Thank goodness part2 was a small increment if you chose the right grid representation.

mchampine07:12:51

Done. Whew. Thank goodness part2 was a small increment if you chose the right grid representation.

yenda12:12:04

which one did you chose? I went with a map of sets and changed it to a map of map for the part2 which was a small change

mchampine16:12:28

I used a simple list of x,y pairs. Once I had the intersections I could just drop everything after that point and the remaining points were the path length.

mchampine16:12:24

That is, for each intersection point search the full path (ordered list of points) for it. All the points before it are the length of the path to get there. The shortest path wins.

misha09:12:33

:when (not (and (= (first segment-1) [0 0])
                (= (first segment-2) [0 0])))]
can be just (disj [0 0]) from all collisions 2 lines below

misha09:12:55

besides, how do you know that [0 0] is only first in segment? and that lines do not go through [0 0] ever again

fellshard10:12:48

The problem statement explicitly says to ignore it. Otherwise, definitely just an assumption. 🙂

misha10:12:01

yeah, it says ignore [0 0], but I mean, you assume it appears only on segment start, and no segment ends at [0 0]

misha10:12:18

so segment [[0 -2] [0 -1] [0 0]] might leak [0 0] into collisions set

fellshard15:12:16

It might; one of the keys to AoC is figuring out which assumptions you can make safely, sometimes the hard way. Sometimes your solution only works for your input, just because it doesn't challenge that particular assumption. The primary reason I expect there's no [0 0] collision is that it would be a 'trivial solution' to part 1, too easily accidentally guessed for a quick leaderboard time, even if by a fraction of people; that's just not how he operates.

fellshard08:12:31

Whoops, left my reminder comment at the top

mpcjanssen09:12:00

part2 was actually easier today

mpcjanssen09:12:35

Probably because I am storing separate points on the line

uosl10:12:45

My solution for today's part2 is sloow: "Elapsed time: 7919.040046 msecs" I'm getting flashbacks from last year when my part2 solutions were too inefficient to compute in time 😓

misha11:12:52

stick transient in there kappa

yenda12:12:46

or rather rethink your datastructures

yenda12:12:26

mine takes 75ms with maps

uosl12:12:34

Would you mind sharing your solution? I'm curious how it looks with maps.

yenda12:12:38

did you go with some lists/vectors?

uosl12:12:13

yes, I went with a vector of all the coordinates for a line, then turned it into a set for running intersection

mpcjanssen12:12:03

same here and same perf

mpcjanssen14:12:07

I am doing everything on my phone this year, would be much more difficult with other other languages. But works great with clojure and jupyter

mpcjanssen14:12:41

Interesting (positive) side effects, I make more granular functions and think more before starting to type.

genmeblog14:12:23

Hardcore coding 🙂

mpcjanssen14:12:10

Holiday time waster 🙂

mpcjanssen14:12:10

Let's see how long I can keep it up

genmeblog14:12:13

Writing anything on the phone (even simple messages) is so inconvenient that I can't even imagine editing the code.

mpcjanssen14:12:00

The trick is to type less (so think first) and a good soft keyboard helps.

genmeblog14:12:29

For sure. The idea to think more before typing is always beneficial

tws14:12:11

2019 day 3 is similar to 2016 day 1. Just absolute moves instead of relative turns. I wound up putting that code into a aoc.grid library.

pesterhazy16:12:06

haha, already planning ahead for 2020! 🙂

fingertoe15:12:23

Got the first part done — running 500-700 ms. Traded the leaderboard points for sleep. Will finish part 2 later today..

Mario C.19:12:24

Just finished day 3. This one was tedious. Gonna look at other solutions. I modeled my solution based on lines (two points) and intersections (points). Perhaps it may have been easier to build a grid.

erwinrooijakkers22:12:01

https://github.com/transducer/adventofcode/blob/master/src/adventofcode/2019/day3.clj not a masterpiece - don’t see how to improve the clojure or the performance. NOTE: peek instead of last to get last element of a vector led to running twice as fast.

genmeblog23:12:33

Nice solution. But I see you were lucky. Intersections can have negative coordinates and you should sum absolute values rather than filtering negative results (see manhattan distance definition).

erwinrooijakkers23:12:25

Aha so sum absolute values and remove zero?

tws23:12:13

did you try using clojure.set/intersection and measure the performance? curious.

erwinrooijakkers09:12:49

I will try that 🙂 hehe

erwinrooijakkers09:12:53

Didn’t think about that

erwinrooijakkers11:12:27

Initial: “Elapsed time: 1323.049568 msecs” With clojure.set/intersection “Elapsed time: 861.311297 msecs” 😉