Fork me on GitHub
#adventofcode
<
2018-12-02
>
pesterhazy00:12:56

I think the "rule" that predicates should return booleans is a bit silly

pesterhazy00:12:46

There nothing wrong with truthiness

taylor00:12:42

I think Rich himself strayed from this guideline for at least one predicate in spec

mfikes00:12:19

I like how Dan Dorman's solution uses a transient that is eventually discarded (no persistent! needed to derive value from the transient). https://github.com/dandorman/advent-of-code-2018/blob/master/src/aoc2018/d01.cljc#L18

danielgrosse21:12:18

Amazing how this speeds up the calculation. I had the solution without transient and it took my mac around 10 minutes to get the result. With Dormans one it had no calculation time at all.

lilactown00:12:50

oh that input->vec is also very nicely clever

mfikes00:12:14

Oh wow. Nice hack.

lilactown00:12:37

wish I had thought of that. I didn’t even think to reach for the reader like the rest of ya’ll; I pieced together a solution using Integer/parseInt

dpsutton00:12:31

i prefer traditional parsing steps. more like real life. I would never ship production code that calls read on input like that. i also don't like when the language makes some things more easy like that

dpsutton00:12:59

like when the syntax they pick happens to align with literals in the language you are using. unless you make a language like that a la racket

lilactown00:12:44

true. It just ate up about 80% of the time of part 1 for me :P

lilactown00:12:56

gotta get those leaderboard spots!

mfikes00:12:23

Oh, come on, how often do you get to do something like

(eval (read-string (str "(apply + [" input "])")))
😜

vijaykiran00:12:45

(eval (read-string 
          (str "(+ " input ")")))

mfikes00:12:06

Cool, I was getting a stack overflow on my input size for this.... wondering why.

mfikes00:12:38

Shia LaBeouf / Chuck Norris, style programming

vijaykiran00:12:49

🙂 That’s pretty much what I did 😄

potetm00:12:56

omg… the waste!

potetm00:12:30

just | into a single grep process!

potetm00:12:40

sry — I’m a bash dev by training 😛

mfikes00:12:07

"This solution does not require programming." Just pure thought.

borkdude00:12:19

I didn’t know Integer/parseInt and js/parseInt both accept +1 and -1, else I would have used that instead of read-string

mfikes00:12:40

To put things in perspective, when I mentioned this problem to my 15-yo, he first said he would take the absolute value of each, but remember the sign, so you would know whether to add or subtract the absolute value.

dpsutton00:12:57

that's where i went at first. they just happened to encode the data in a convenient literal

lilactown00:12:15

I decided to try parseInt +5 first, but if it hadn’t worked I was planning on just removing all +’s before parsing

☝️ 4
mfikes00:12:51

I forgot to even look for + in the input, and just proceeded Leroy Jenkins-style.

mfikes00:12:29

The way most code is written.

mfikes00:12:57

Unless the hammock calls.

lilactown00:12:36

I recently bought an iPad so that I could still computer without being near a dev workstation, so that I would spend less time writing code and more time hammocking

lilactown00:12:11

that went OK until I figured out how to setup ssh / emacs / tmux 🤪

rmprescott18:12:55

I probably shouldn't mention http://repl.it then... ;D

rmprescott19:12:58

My mac is in the shop so I'm working there: https://repl.it/@RalphPrescott/AoC-2018

mfikes00:12:44

The difficulty of entering forms into Replete gives you plenty of time to think if you go that route.

lilactown00:12:21

haha. I did mess with replete. it’s pretty impressive!

lilactown00:12:01

I threw up an issue about being able to save to disk or gist :P I know it’s just a wish-list thing

👍 4
mfikes00:12:39

I'm curious what fraction of the solutions fail to handle the "back to 0" case. (For input [+1 -1], for example)

taylor01:12:52

is the correct answer 1 for that input?

dpsutton01:12:43

depends if you consider a sequence of 0 elements having a sum of 0, then the sequence of 2 elements would have a sum of 0. or most likely the sequence of [1] an then [1 -1 1] having sums of 1 is what they most likely mean

taylor01:12:43

oh, I’m thinking specifically about part 2

dpsutton01:12:11

well that's what i'm talking about as well. there are arguments for 0 or 1

taylor01:12:41

ohh I see now, one argument is that the starting frequency of 0 should be considered when looking for the first duplicate

taylor01:12:23

in that case, my solution fails 🙂

taylor01:12:39

>+1, -1 first reaches 0 twice.

taylor01:12:15

but I suppose I can just start with #{0} instead of #{} and handle that

dpsutton01:12:10

it's easy to miss this subtlety. not sure which way to fall but i guess good to be conscious of which one you think is the right answer rather than whatever your reduce expression returns

taylor01:12:11

the AoC test cases seem to indicate the answer should be 0

dpsutton01:12:37

Which test case?

lilactown01:12:53

It's written in the description of the puzzle

☝️ 4
herald12:12:05

Mine did until I started adding tests. At that moment I realized why your solution had consed the reductions onto 0 😛 Although passing 0 as init to reductions worked for me.

Stephen Lester03:12:58

I hope I'm not the only one who smashed the stack trying part 2 😞

Mario C.04:12:01

2 mins gentlemen 😛

orestis07:12:37

So in part2, instead of considering one string against all others, repeating, you are dropping the first character, search for duplicate, second character, search for duplicates etc? Neat!

bhauman15:12:18

thats fun 🙂

dpsutton06:12:01

Ah. The day 1 first duplicate is clever

dpsutton06:12:15

I didn't think of deleting and checking

mfikes06:12:47

This problem will lead to a richer variation of solutions. 🙂

dpsutton06:12:40

I just realized mine is not funny general. I compare them to their neighbors after sorting. But there is no reason the single difference would not move their position in the sorted list

dpsutton06:12:52

Funny = fully

dpsutton06:12:19

Although now I can't think of a better approach than your brute force

ClashTheBunny07:12:34

Day 2 https://gitlab.com/randall.mason/advent-of-code/blob/master/src/advent_of_code_2018/day02.clj Happy about some of it, other parts seem like they could be MUCH better. Perfomance is fine.

dpsutton07:12:24

You can drop the first two comparisons in your levenshtein since all the strings are either equal or replaced. There are no deletions or additions to worry about

dpsutton07:12:26

Ah ok you use simple cost only :)

Mario C.07:12:33

Day 2 part 1 took me 2 hours to do ooof.. Can't come up with a solution for part 2, too tired >.<

orestis07:12:18

Woof, I solved day2 part2 but mfikes has already contributed his data to advent-of-cljc. How do I submit a patch instead of a PR to Github? 🤪

orestis07:12:56

Day2: https://github.com/orestis/advent-of-cljc/blob/master/src/aoc/y2018/d02/orestis.cljc — I need to finally figure out how to get a CLJS REPL setup so I can see why the CLJS tests are failing. Most likely something to do with chars/ints etc.

dpsutton08:12:24

I'm interested to see different approaches that are sound. Mine was probabilistic

helios08:12:11

here's mine: https://github.com/Heliosmaster/advent-of-code-2018/blob/master/src/adventofcode_2018/day2.clj but i liked @mfikes answer a bit more 😉 there are some functions (like keep) that I have used rarely so I tend to forget about them 😄

mfikes13:12:47

On the surface, when count is applied to filter vs. keep, you essentially get the same result for this problem. So you might wonder why I was using keep... it was because the intermediate output in the REPL looked a little simpler, that's all.

borkdude08:12:29

@orestis about failing CLJS-tests: if you change the deftest to clojure.test/deftest you will see the error. I’m not sure why it’s not showing right now. I wrapped the deftest body in time to see the performance. PR welcome that fixes this

orestis08:12:44

In the end cider can happily jack in to a CLJS REPL for me so I fixed my code interactively.

thegeez09:12:57

@borkdude I've invited a few more people as collaborators to help with merging pr's

pesterhazy10:12:48

This time I spent most of my time on setting up rebel-readline, and on writing a lazy pairs function

borkdude10:12:27

I didn’t try to write clever code, just did the most straightforward thing to get to the solution fast, because I had a coffee meeting coming up

pesterhazy10:12:43

No excuses!! 🙂

pesterhazy10:12:35

is there a cutoff time when you need to submit solutions? https://clojurians.slack.com/archives/C0GLTDB2T/p1543726681192500

ClashTheBunny14:12:08

You get more points on the leaderboard the faster you submit! You don't have to finish every problem to work on the next one. You could practice on other years' problems if you wanted to!

orestis11:12:01

No, not at all. You could do these next year.

karol12:12:47

https://github.com/kfirmanty/advent-of-code-2018/blob/master/src/advent_of_code_2018/day2.clj my solution is also rather not optimized, but it might be fun to look back after few days and try to create most performant solution (but probably with lesser readibility)

karol12:12:41

I especially have a feeling that there is a simpler way to do: (defn without-diff [id1 id2] (apply str (map #(when (= %1 %2) %1) id1 id2))) so I will check other solutions 😉

gklijs12:12:46

Anyone hooked in something like https://github.com/gobanos/cargo-aoc I got jmh setup for Java now, would be nice to compare results. I don't know if I have the time, but otherwise I might setup a project, comparing several solutions.

helios12:12:44

@pesterhazy the countdown was for the new puzzle release 🙂

borkdude12:12:16

@gklijs are you aware of https://github.com/borkdude/advent-of-cljc or is that a different thing?

gklijs12:12:13

I know it's there and like to look at the solutions, but don't know if there is some performance measure there?

borkdude12:12:54

if you go to the CircleCI icon, open a build and then look at the tests, you will see something like that

borkdude12:12:49

not anything fancy, just time, not criterion

gklijs12:12:51

found them

borkdude12:12:02

but it would be trivial to hook that up. I’m only concerned about the time to build

gklijs12:12:34

You don't want it in your build, it takes really long. I now have a separate profile to run them, just putting the result back with the method and then remove the annotation in java, so I can easily run the other ones.

borkdude12:12:35

you could make a branch, replace the time call with criterium quickbench, push the branch and watch the build. if we don’t merge it to master, it should be fine.

benoit12:12:08

Very clever solution from @mfikes. It ismy first advent-of-code. Do the solutions often build on previous days's solutions? Do we build up code for 23 days to make writing the solution on the 24 a bit easier?

karol13:12:15

If I remember correctly in 2017 there was once a day to built upon solution of previous day but I think it was a exception to the rule

gklijs13:12:32

the @mfikes solution is also very fast compared to the others

Testing aoc.y2018.d02.borkdude
part-2 took 54.986879 msecs
part-1 took 0.38845 msecs

Testing aoc.y2018.d02.dfuenzalida
part-2 took 126.335371 msecs
part-1 took 5.086755 msecs

Testing aoc.y2018.d02.mfikes
part-2 took 4.250777 msecs
part-1 took 7.145989 msecs

Testing aoc.y2018.d02.mrmcc3
part-2 took 82.483809 msecs
part-1 took 4.544113 msecs

Testing aoc.y2018.d02.orestis
part-2 took 103.404907 msecs
part-1 took 8.286482 msecs

mfikes13:12:39

Hmm. I didn’t write it with speed in mind.

mfikes13:12:25

I actually wonder if day 2 had day 1 in mind… in this case there was the concept of “sameness / duplication” in both problems.

gklijs13:12:38

no, I was also surprised, gonna use it in my javaRx now, and compare to me previous solution.

benoit14:12:31

ok, thanks.

gklijs14:12:14

Turned out to be slightly faster than the previous solution, 3.445 msecs on a warmed up vm

vijaykiran18:12:57

Are these from CI ?

part-1 "Elapsed time: 5.87954 msecs"
part-2 "Elapsed time: 0.829347 msecs"
These are mine from (time …) < it is super-ugly-code though

gklijs19:12:41

The list is from CI, the 3,445 is from jmh benching.

vijaykiran19:12:59

okay! I only ran (time ..)

gklijs19:12:47

I have something similar in Java now, and the rust create also has it, will be adding some CI config to get some numbers there

gklijs12:12:54

Can of related to that I often struggle with how generic a solution should be, for my java colleagues I also see them putting some effort in nicely handling edge cases.

gklijs12:12:38

Default settings, at least in java take about 15 minutes for each method.

ClashTheBunny14:12:08

You get more points on the leaderboard the faster you submit! You don't have to finish every problem to work on the next one. You could practice on other years' problems if you wanted to!

taylor15:12:07

day 2 was fun. I feel like there’ll be more variety in the solutions, here’s mine https://github.com/taylorwood/advent-of-code/blob/master/src/advent_of_code/2018/2.clj

bhauman15:12:55

just finished

bhauman15:12:32

now to look at the other answers 🙂

dpsutton15:12:16

So it seems brute Force is the only strategy?

bhauman16:12:43

for the most part one way or the other you are going to have to compare until you find

bhauman16:12:26

one interesting thing is that sorting the list may increase the likelyhood that the search ends sooner

bhauman16:12:11

as you normally generate combinations from the original order

bhauman16:12:07

actually this is not true for my data it increased the number of cycles quite a bit

bhauman16:12:37

actually a tree search would probably provide the best performance

bhauman16:12:19

as you are eliminating prior comparisons

mfikes17:12:04

It is possible to parallelize the search. For the algorithm I'm using, the problem is essentially linear in the input, but with it doing a linear search over each character position, one at a time. The answer happens to be at position 20 for my input data. Those searches per character position can be done in parallel. The problem size isn't really big enough to benefit greatly from this, but it can cut it down from 3 ms to 1.5 ms. https://gist.github.com/mfikes/d2cf0c9de3808564f7b039f10635ede4#file-parallel-clj-L34-L44

bhauman17:12:34

my tree solution is 7ms

bhauman17:12:54

compared to lazy search of 99ms

bhauman17:12:25

the tree search intelligently eliminates large swaths of search area

taylor17:12:27

Very cool. Gonna need to study this for a while :face_with_monocle:

gklijs17:12:30

Is that with warm up? Rust is doing around 0.25 ms for each of day two

bhauman17:12:30

of course it is

gklijs17:12:39

With RxJava it's about 3/6 ms, measured with jmh. I'm still kind of figuring out what I like best/want to get better in.

andrew.sinclair18:12:59

Hi all! I love this time of year! My solutions aim for leaderboard points rather than elegance and best practices. It’s great to see all the unique ways other clojurians come up with!

dpsutton18:12:13

@bhauman i was reading your tree search and it prunes a bit too heavily (search ["abc" "ddd" "zbc" "ahg" "zzz"]) should match abc/zbc => "bc" but it fails to find them

bhauman18:12:16

@dpsutton oh cool thanks, I think thats a base case lemme check it out

bhauman18:12:12

oh I broke it when I refactored

lilactown19:12:04

> TFW you accidentally leave that println inside the inner loop of your solution and you run it on your real input facepalm

lilactown19:12:15

at least in CIDER/Emacs outputting that much text to a buffer wrecks me

rmprescott19:12:01

Tempted to ask this on another channel - but it's also some hints on the first few problems. Are there any more idiomatic approaches to these short helpers?

bhauman19:12:16

@dpsutton nope its just wrong 🙂

dpsutton19:12:39

Mine too :)

dpsutton19:12:27

a sort and compare with neighbor works on the input but is not right in general. (i realized after doing that)

bhauman19:12:17

I found the problem but of course it slows it down 🙂

dpsutton19:12:35

yes you have to be more cautious of when you can prune things

dpsutton19:12:56

is it instead of apply intersection you look for duplicates?

bhauman19:12:46

right now I’m intersecting two by two

dpsutton19:12:01

i was mulling that idea just now

bhauman19:12:13

which is searching for duplicates

dpsutton19:12:15

look for things with the first two characters have non-empty intersection

lilactown19:12:44

oof, ya’ll are making me feel bad. my day2 part2 solution is ~600ms 😆

bhauman19:12:26

I’m thinking that its better to do this as a tree as well

vijaykiran19:12:26

As long as it works 🙂 We are not in a hurry

dpsutton19:12:12

@lilactown but the "fast" versions we are talking about are unsound 🙂 slow and steady

lilactown19:12:52

still, going fast is fun!

vijaykiran19:12:07

Hey - my version is fast and it is very sound (as in very noisy) 😄

vijaykiran19:12:11

For the second one, I was even considering not writing code and Cmd+F and eye-ball the similar strings

rmprescott19:12:14

@bhauman - i'm missing something. I don't see how you can do this other than pairwise. What would you use as the comparison in your tree?

rmprescott19:12:00

I can't think of anything that (properly) constrains the solution space.

bhauman19:12:55

hold on committing

bhauman19:12:08

in this solution I’m doing a depth first search

bhauman19:12:28

so it should eliminate comparisons

bhauman19:12:05

its takes a third of the amount of time as my straight forward solution

bhauman19:12:17

now breadth first search would really be interesting

bhauman19:12:49

and updated again with comments

mfikes20:12:04

IIRC, we will probably see a few perf-critical ones in a couple weeks (where your algorithm is important if you want it to complete in a few minutes)

☝️ 4
💯 4
mfikes20:12:49

Or within the RAM you have 🙂

lilactown20:12:24

answer: just throw a naive solution at a cluster and come back the next day 😛

lilactown20:12:36

slow and steady!

pesterhazy20:12:50

surely @mfikes's solution must be the fastest no?

mfikes20:12:09

Oddly, mine wasn't at all meant to be fast. It got lucky.

herald20:12:11

was there a problem like that last year? it does say this in the about page: >every problem has a solution that completes in at most 15 seconds on ten-year-old hardware.

herald20:12:49

although my first attempt at day 1 part 2 would have taken at least 15 minutes to finish :rolling_on_the_floor_laughing:

pesterhazy20:12:55

my super-inefficient solution completes in 47ms

mfikes20:12:56

There was that one with the particle simulation that was a real PITA, where you had to almost eyball the solution.

mfikes20:12:13

Day 20 last year.

herald20:12:16

ooo. this is my first year so looking forward to any problems that places me in a rut

mfikes20:12:13

IIRC, one pattern is where part 1 can be done with a naive algorithm, and then Wastl asks you to do it for a problem with a billion iterations in part 2.

pesterhazy20:12:35

It's my first year as well. What will Day 3 bring? More duplicate detection? 🙂

bhauman20:12:40

@vijaykiran try [“abc” “ddd” “zbc” “ahg” “zzz”]

bhauman20:12:50

your solution fails for me on that

vijaykiran20:12:54

sorted stuff breaks it - I made some assumptions after sorting my puzzle input

Mario C.20:12:45

wow part 2 was pretty cumbersome my solution was kinda hacky but it got the job done 😛 https://github.com/HeyItsMario/AdventOfCode2018/tree/master/day2

lilactown20:12:15

let’s see. last year’s day 1 was pretty similar (summing things). day 2 was doing some integer math (finding min/max, divisors)

dpsutton20:12:27

yeah. and then you start trying to code generically for part 1 and then you don't get to reuse any for part 2 sometimes

lilactown20:12:18

there were a few times last year where if you solved part 1 a certain way, part 2 fell out of it quite nicely

lilactown20:12:32

but most of the time I spent trying to make part 1 “generic” without knowing part 2 was a waste, yes

mfikes20:12:53

Day 16 was of last year was an example of naive part 1 could in theory solve part 2, but it involved a dance of some sort that went out a billion iterations

potetm20:12:53

@gklijs I’d love to see your Rust/RxJava example

potetm20:12:09

did you do any optimizations or is it basically brute force?

potetm20:12:46

I can’t get my brute force below ~130ms or so

gklijs20:12:46

I did do the mfikes trick, but that didn't do much to performance, did lose half the needed code. In Rust I'm really inexperienced, so need to google for a lot of stuff,and just happy when it runs. But I figure especially the second one really does well, since it's just moving pointers around. Code at https://github.com/gklijs/advent_of_code_2018 'Gerard' is RxJava, 'Rust/oac_2018' is rust, the other folder are Java from colleagues.

gklijs20:12:02

It could also be your problem is harder, that's the nice thing about https://github.com/borkdude/advent-of-cljc they all use the same data

potetm20:12:52

ah, didn’t even consider that

potetm20:12:00

I mean… also just hardware

gklijs20:12:59

It's the first year for me, and also for the company, maybe next year I set something up with GraalVM

potetm20:12:15

the mfikes trick (w/ transducers) gets me down to ~2ms

potetm20:12:38

actually… holy hara

nooga20:12:24

for early puzzles I just write really long oneliners in a repl, they tend to be convoluted and slow 😂

4
potetm20:12:37

(str (subs s 0 i)
     (subs s (inc i)))
^is WAY faster than
(.toString (.deleteCharAt (StringBuilder. s) i))

potetm20:12:04

down to .5ms

mfikes21:12:48

Reflection?

potetm21:12:20

I hinted the constructor

potetm21:12:23

in my timing

pesterhazy21:12:03

@nooga I'm the same way, whatever I can possibly squeeze into a one-liner in the repl

pesterhazy21:12:24

only roadblock: rebel-readline, as great as it is, doesn't submit when I hit Return while the cursor is not at the end of the line

simple_smile 4
potetm21:12:48

(fn [^String s]
  (.toString (.deleteCharAt (StringBuilder. s)
                            ^Long i))
is comparable

mfikes21:12:35

So, transducers got it down to half a millisecond. Nice.

mfikes21:12:50

Rust speed within reach. 🙂

mfikes21:12:52

Hah! Every time that happens on Apropos, we shout out Bruuuucee!

mfikes21:12:03

Now we know they way 🙂

potetm21:12:15

Bad news…

potetm21:12:24

My .5ms was bugged

mfikes21:12:37

Damn. 👿

slipset21:12:42

ah, spent way too much time on part two of day two.

mfikes21:12:47

IMHO, day 2 part 2 was a bit harder than you would expect, so early on

slipset21:12:40

I was over complicating things a bit.

slipset21:12:04

I’m probably not so concerned with speed 🙂

slipset21:12:51

Don’t want to spoil anything 🙂

pesterhazy21:12:28

@bhauman is there any way to bind the Enter key to clojure-force-accept-line rather than accept-line?

pesterhazy21:12:42

I tried

cat ~/.clojure/rebel_readline.edn
{:key-bindings { :emacs [["RETURN" :clojure-force-accept-line]] }}

pesterhazy21:12:07

I can bind ^J, which is nice, but a real Enter/Return would be better

bhauman21:12:36

^J or ^m I think

pesterhazy21:12:39

wait! this works

pesterhazy21:12:41

{:key-bindings { :emacs [["^M" :clojure-force-accept-line]] }}

bhauman21:12:53

yes control M is a real return

pesterhazy21:12:02

it's always just after bothering someone that you find the answer yourself

bhauman21:12:21

so the thing is that you don’t get multiline that way

pesterhazy21:12:41

yeah maybe I can bind that to ^j

pesterhazy21:12:10

honestly I don't often write multiple lines except by mistake

pesterhazy21:12:46

yeah, ^j is bound to accept-line by default - that works well for me

pesterhazy21:12:58

now it's perfect 🎉

metal 4
borkdude21:12:57

Day 2 for Advent of CLJC:

Testing aoc.y2018.d02.borkdude
part-2 took 47.616232 msecs
part-1 took 0.408357 msecs

Testing aoc.y2018.d02.dfuenzalida
part-2 took 118.803809 msecs
part-1 took 5.012151 msecs

Testing aoc.y2018.d02.iamdrowsy
part-2 took 362.461886 msecs
part-1 took 4.806461 msecs

Testing aoc.y2018.d02.mfikes
part-2 took 4.994811 msecs
part-1 took 7.194342 msecs

Testing aoc.y2018.d02.mrmcc3
part-2 took 92.999763 msecs
part-1 took 5.206182 msecs

Testing aoc.y2018.d02.orestis
part-2 took 98.666185 msecs
part-1 took 8.78663 msecs
https://circleci.com/gh/borkdude/advent-of-cljc/91

borkdude21:12:46

Good job everyone and thanks for contributing.

borkdude22:12:01

mfikes really nailed it. when I saw his function that deleted one char from a string I was like: oh yeah, of course… 🙂

Mario C.22:12:29

very humbling seeing y'alls such succinct solutions

potetm22:12:31

(criterium/quick-bench
  (into []
        (comp (keep (fn [i]
                      (first (into []
                                   (comp (map (fn [^String s]
                                                (.toString (.deleteCharAt (StringBuilder. s)
                                                                          ^Long i))))
                                         (dups)
                                         (take 1))
                                   in))))
              (take 1))
        (range (count (first in)))))
Evaluation count : 828 in 6 samples of 138 calls.
             Execution time mean : 702.838769 µs
    Execution time std-deviation : 19.556882 µs
   Execution time lower quantile : 668.965703 µs ( 2.5%)
   Execution time upper quantile : 718.893138 µs (97.5%)
                   Overhead used : 1.830592 ns

potetm22:12:30

where dups is a transducer that emits duplicates

slipset23:12:52

I wish I understood the reasoning behind @mfikes solution to todays second problem.

mfikes23:12:30

Maybe I could draw a picture of it

mfikes23:12:10

I visualize it as first eliminating a column of characters and then seeing if that causes a duplicate to appear in the remaining strings

🎉 4
rmprescott23:12:23

divide and conquer -- nice!

mfikes23:12:59

abc
axc
def
Eliminate the middle column in that example

👍 4
mfikes23:12:17

ac then appears twice

slipset23:12:00

Quite cheeky to use yesterdays solution though 🙂

borkdude23:12:34

he factored out a function that he could re-use: https://github.com/borkdude/advent-of-cljc/commit/17c8f768c75fbb69187eb4ecf892d17612172cdd it could have ended up in some utils namespace as well

fellshard23:12:26

I'm trying to recreate my solutions in Elixir as a sort of lift-and-shift approach. A lot of common utility between Clojure and Elixir, though the latter is certainly far more verbose and doesn't have quite the same expressiveness for its core lib. Still not bad.

devn23:12:19

wow, did not think i'd wind up using reductions on problem 1 😄

devn23:12:48

one of my favorite functions that i keep in my back pocket

👌 4
dpsutton23:12:51

Reductions and iterate always feel so fancy and sophisticated to me ha

devn23:12:10

wow, that's actually kind of interesting

devn23:12:20

i feel like early on when i was using clojure i used iterate a lot

devn23:12:25

but i don't use it very often these days

devn23:12:51

like when you mentioned it, i was like "oh right, that exists"

dpsutton23:12:17

I don't use it very often in our webapp or backend stuff but I like to model solutions to "clever" problems with it

devn23:12:53

i guess i used it pretty often in 4clojure problems when golfing

devn23:12:28

and in project euler solutions

devn23:12:35

which is why i remember it being a "back in the day" kind of thing

dpsutton23:12:31

That makes sense. It doesn't seem to align with real world things I have to do so it really feels insightful when it works

devn23:12:29

btw, reductions is "fancy", but i remember using it for a problem where i had a sequence of lines of chat, similar to the way they're presented in slack, so you'd see a nickname, and then you wouldn't see it on any lines they typed immediately after, but i wanted it filled in everywhere