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-07T02:00:37.778400Z

> You emerge from the chimney to find a circle of your peers. Hark! A spot has been left for you! You take a seat, and they inform you that they’re having a Christmas Eve Retrospective. > > Your mission is to write all of your mad, sad, and glad moments on postcards. You have three minutes. If you fail, Santa will send you back to the North Pole where you’ll spend the next year shoveling coal for the naughty boys and girls.

2
Average-user 2018-12-07T02:10:10.784900Z

I find very satisfying when is possible/necessary to apply discrete mathematics to really solve a problem, so day 6 has been my favourite this year. Like there is always Project Euler but it is too much oriented in number theory or similar topics

fellshard 2018-12-07T02:10:32.785500Z

'Some, but not down the rabbit hole'

fellshard 2018-12-07T02:11:54.785800Z

Discrete Voronoi? ¯\(ツ)

2018-12-07T02:12:28.786Z

looks like it!

Average-user 2018-12-07T02:15:35.786200Z

Well, to really prove that the minimum box approach works, a proof is needed and that proof is not entirely trivial. The roll that Manhattan distance plays over Euclidian one is quite neat

2018-12-07T02:16:14.786400Z

do go on

2018-12-07T02:16:25.786600Z

I just made assumptions like the ape that I am.

2018-12-07T02:19:21.786800Z

I’d love a link or something w/ more info if you happen to have it!

Average-user 2018-12-07T02:22:38.787Z

I did go with assumptions to solve it first, and it worked. But to achieve a non heuristic solution I had to do some math, which I found fun

Average-user 2018-12-07T02:23:23.787200Z

Well my original solution turned out to be the right one, but prove it wasn't completely trivial

Average-user 2018-12-07T02:26:10.787400Z

Can u tell me what approach to solve day6 did u use?

2018-12-07T02:30:00.787600Z

uh, I would say, “brute force with loads of assumptions” 😄

2018-12-07T02:31:47.787800Z

let’s see, part 1 - make a bounding box sig bigger than the points (500x500), remove all ids on the edges, sum the remaining areas, and take the max

2018-12-07T02:33:05.788Z

part 2 - assume a bounding box that encompasses all points is big enough, check every point in the box for inclusion in the “good zone”

Average-user 2018-12-07T02:36:34.788200Z

What do you mean with "ids on the edge" ?

2018-12-07T02:37:23.788400Z

uh, I gave an id to every input point

Average-user 2018-12-07T02:44:33.788600Z

But what does it mean for a coord to be "on the edge"

2018-12-07T02:50:10.788800Z

on the edge of the bounding box

2018-12-07T02:51:22.789Z

like, points that comprise the edges of the bounding box

Average-user 2018-12-07T03:00:24.789400Z

But do u mean points that r exactly on the edge, or the ones that r closer 2 it?

2018-12-07T03:33:59.789600Z

the ones exactly on the edge

Average-user 2018-12-07T03:42:14.789800Z

Im sure there are cases where there are coordinates that are no on the edge that have infinite areas

2018-12-07T03:43:16.790Z

how can that be?

ClashTheBunny 2018-12-07T04:32:57.790600Z

He tried to choose a box big enough that anything out that far would be infinite.

fellshard 2018-12-07T04:33:38.791500Z

Holy crap. Note to self: type hint more. Those box warnings are gonna be super helpful, and the emacs integration helps narrow it right down

ClashTheBunny 2018-12-07T04:35:44.792Z

Super not proud of my six, but here it is: https://gitlab.com/randall.mason/advent-of-code/blob/master/src/advent_of_code_2018/day06.clj

2018-12-07T08:03:14.793600Z

whew, #7's part 2 was quite a grind, but ultimately fun to model scheduling in clojure!

pesterhazy 2018-12-07T08:41:07.794700Z

@rymndhng agreed, this was fun. Would love to see your solution

pesterhazy 2018-12-07T08:41:46.795500Z

I wonder if recursion via loop is the best way to approach this - I did end up with a lot of nested conditionals

borkdude 2018-12-07T10:48:34.796100Z

I thought I could use tree-seq for day 7, but depth-first doesn’t work here… I haven’t solved it yet

borkdude 2018-12-07T10:48:43.796400Z

hopefully later today

borkdude 2018-12-07T10:53:20.797500Z

@erwinrooijakkers note that there are 2 other solutions in 2017 that also don’t work for the given input. These solution probably have overlooked a small edge case. You’re still welcome to submit the code, but maybe do a println in the test “TODO: fix for this input”

benoit 2018-12-07T13:59:53.798900Z

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

taylor 2018-12-07T14:29:54.799600Z

these are starting to get too difficult to solve at 11pm CST 💤

✔️ 1
gklijs 2018-12-07T14:43:36.801200Z

For me they're there 6 in the morning, I do get up early, bu then I first have to travel, work, travel, cook, except for at most 30 minutes in the morning, which is to short.

ihabunek 2018-12-07T14:50:16.802100Z

6am for me too, not really meant for us european types. i like sleep too much to even attempt solving them at that ungodly hour.

borkdude 2018-12-07T14:56:11.802800Z

I have four different letters that I can start with. If I choose the first one alphabetically, there is no answer.

borkdude 2018-12-07T14:56:24.803100Z

Should I just try them all, or is there some logic to this?

mattly 2018-12-07T14:56:43.803400Z

I've got a similar situation

mattly 2018-12-07T14:57:21.804Z

but then I'm not sure I don't have a bug

ihabunek 2018-12-07T14:58:51.804500Z

if you give me your input, i can try my solution and tell you if it gives an answer

borkdude 2018-12-07T15:00:06.805100Z

@ihabunek input in PM

mattly 2018-12-07T15:00:52.805400Z

I'm fairly sure I have a bug

borkdude 2018-12-07T15:01:40.805800Z

I’m probably having a bug too, because none of the starting letters give an outcome, while my code works for the example

ihabunek 2018-12-07T15:02:39.806300Z

@mattly @borkdude yeah, both of your inputs give me a solution similar to what I got.

borkdude 2018-12-07T15:02:44.806600Z

thanks

ihabunek 2018-12-07T15:02:47.806800Z

so i'm guessing you have a bug

mattly 2018-12-07T15:02:51.807Z

ok cool

mattly 2018-12-07T15:03:02.807300Z

thanks

benoit 2018-12-07T15:05:57.808100Z

@borkdude I think the first letters should be handled the same way you handle the normal case.

borkdude 2018-12-07T15:05:57.808200Z

@ihabunek do you only have one letter to begin with?

benoit 2018-12-07T15:06:12.808600Z

@borkdude I had 3 letters to begin with

borkdude 2018-12-07T15:06:21.808800Z

ok, so alphabetically that is - right?

mattly 2018-12-07T15:06:26.809Z

found my bug

benoit 2018-12-07T15:07:05.809600Z

@borkdude yes you try each in turn alphabetically

borkdude 2018-12-07T15:07:16.809800Z

ok

mattly 2018-12-07T15:07:55.810200Z

boom, got it, thanks again

ihabunek 2018-12-07T15:08:14.810400Z

\o/

ihabunek 2018-12-07T15:08:37.810800Z

@borkdude let me check

borkdude 2018-12-07T15:10:52.811100Z

I think I found my bug as well

helios 2018-12-07T15:11:14.811700Z

what was it? 🙂

ihabunek 2018-12-07T15:11:19.811900Z

cool, then I won't give any hints 🙂

borkdude 2018-12-07T15:11:52.812200Z

still figuring out, but I’m close…

borkdude 2018-12-07T15:18:06.812500Z

got it right 😄

borkdude 2018-12-07T15:18:14.812700Z

now part two… 😕

borkdude 2018-12-07T17:22:05.813200Z

LOL, my answer for part 2 was too low. So I tried +1… to test if I had a off by one error, and I did.. now I still need to fix it

😆 3
fellshard 2018-12-07T17:34:59.814800Z

Had off by one here as well for quite a while.

2018-12-07T17:45:51.815100Z

same, but too high

2018-12-07T17:47:20.815700Z

The fix was to decrement my counter by 1 🙈 🙉 🙊

2018-12-07T17:54:02.816Z

https://www.twitch.tv/timpote — with shoutouts to the channel 🙂

1
2018-12-07T18:40:26.816800Z

@pesterhazy here's what I got for day 7: https://github.com/rymndhng/advent-of-clojure/blob/master/src/advent_2018/07.clj I modelled part 2 with a lazy sequence 😁

2
2018-12-07T19:03:05.818Z

Thanks for the stream and the answers

2018-12-07T19:03:50.818200Z

My pleasure!

2018-12-07T19:18:27.822900Z

Hi folks! I am still pretty new to Clojure (and haven’t programmed any in … years.). My colleagues started AoC and I thought that’s perfect for doing some programming. Does anyone mind having a look at my code and giving me some pointers of what can be better / faster / more clear or any other way useful? Here’s a gist. I also included my test file… https://gist.github.com/MeikeMertsch/6a14074aa336f4d377c5d0fb6a01ca2b

adammiller 2018-12-07T19:23:07.823Z

finally getting around to this one today. I also am getting the correct answer on their sample data, but on real data it's not correct. Anyone else have some sample data and answer that I can use to test?

adammiller 2018-12-07T19:23:16.823200Z

on step 1 that is

adammiller 2018-12-07T19:23:45.823500Z

sample data must definitely be missing edge case

2018-12-07T19:24:47.823600Z

have you considered both the difference in time as well as the count of workers?

2018-12-07T19:25:01.823800Z

I forgot one of them in the beginning

2018-12-07T19:26:05.824Z

oh. Part one. I am sorry 😞

adammiller 2018-12-07T19:26:05.824200Z

this is on step 1 where i'm getting wrong answer (although it's fine for the test data)

adammiller 2018-12-07T19:26:11.824400Z

no problem

2018-12-07T19:27:24.824600Z

Do you want to show your code? Then I can tell you if I spot where you’re making an assumption that isn’t right?

adammiller 2018-12-07T19:32:53.824800Z

I don't mind but I think I may have found it....working on it now. Thanks though!

2018-12-07T19:33:03.825100Z

Good luck 🍀

borkdude 2018-12-07T19:38:50.825400Z

Testing aoc.y2018.d07.borkdude
part-2 took 56.77 msecs
part-1 took 2.43 msecs

🚀 2
borkdude 2018-12-07T19:50:00.825800Z

Testing aoc.y2018.d07.borkdude
part-2 took 45.78 msecs
part-1 took 1.70 msecs

1
borkdude 2018-12-07T19:52:27.826200Z

On CI:

Testing aoc.y2018.d07.borkdude
part-2 took 25.26 msecs
part-1 took 1.25 msecs

borkdude 2018-12-07T19:52:45.826500Z

This wasn’t an easy one for me… lots of println

borkdude 2018-12-07T19:59:46.827300Z

I wouldn’t be surprised if there was a very elegant short solution to this

borkdude 2018-12-07T20:00:41.828500Z

(mfikes start typing, there it comes…)

mfikes 2018-12-07T20:00:49.828800Z

Im getting off-by one as well, wondering if AoC itself has a bug.

borkdude 2018-12-07T20:01:18.829800Z

it’s a bit finicky to get the loop exactly like in the example page

borkdude 2018-12-07T20:01:39.830300Z

I got it only working by mimicking that every second

gklijs 2018-12-07T20:06:30.832300Z

I'm just kind of done, also have the of by one. It's kind of one the example page itself. Somehow you need one second without anybody doing anything

benoit 2018-12-07T20:06:30.832400Z

Part 2 was challenging for me too. Which is why I broke down the algorithm into little step functions.

benoit 2018-12-07T20:07:15.833900Z

@gklijs I think you're right. I also used the fact that all workers were idle for the definition of done.

taylor 2018-12-07T20:07:25.834100Z

can't tell if I'm getting older & dumber or if the difficulty ramp is steeper this year

gklijs 2018-12-07T20:07:44.834600Z

just add one in the return then 😛

borkdude 2018-12-07T20:08:03.835100Z

@taylor somehow I managed to do AoC every day last year, but I wasn’t sure if I was going to do that this year…

taylor 2018-12-07T20:08:59.836400Z

yeah, at some point the problems (at least to me) start becoming complex in a... non-gratifying way. Last year it was the last few days

gklijs 2018-12-07T20:09:29.836800Z

Time for some blasphemy

gklijs 2018-12-07T20:09:52.837200Z

Main part of the java solution

private static Integer go(final Map<Character, Set<Character>> graph, final int workers, final int additionalSeconds) {
        int workersWorking = 0;
        List<Character> done = new ArrayList<>();
        Map<Character, Integer> atWork = new HashMap<>();
        int timeSpend = 0;
        while(! graph.isEmpty()){
            Character nextTask = nextTask(graph, done);
            while(nextTask != null && workersWorking <= workers){
                workersWorking++;
                atWork.put(nextTask, nextTask - 64 + additionalSeconds);
                graph.remove(nextTask);
                nextTask = nextTask(graph, done);
            }
            int progresTimeBy = atWork.values().stream().reduce(Integer.MAX_VALUE, (o,n) -> n < o ? n : o);
            timeSpend+= progresTimeBy;
            List<Character> justCompleted = new ArrayList<>();
            for(Map.Entry<Character, Integer> entry : atWork.entrySet()){
                if(entry.getValue() == progresTimeBy){
                    justCompleted.add(entry.getKey());
                }else{
                    entry.setValue(entry.getValue() - progresTimeBy);
                }
            }
            for(Character complete : justCompleted){
                atWork.remove(complete);
                done.add(complete);
                workersWorking--;
            }
        }
        return timeSpend + 1;
    }

taylor 2018-12-07T20:10:06.837500Z

MY EYES!

😉 1
2018-12-07T20:10:57.837800Z

What are those dots in…. wait… that’s Java 😮 😱

borkdude 2018-12-07T20:11:26.838100Z

nice, you optimized your Clojure code

borkdude 2018-12-07T20:12:49.839Z

@taylor yeah, last year there were some fun insight, like https://en.wikipedia.org/wiki/Ulam_spiral

borkdude 2018-12-07T20:13:05.839500Z

and on another day bhauman had some very nice solution with tree-seq, I still remember that one

ClashTheBunny 2018-12-07T20:14:27.840200Z

It would be really nice if I didn't have to sign up for a bunch of different accounts to get more test data...

borkdude 2018-12-07T20:15:25.841200Z

@clashthebunny the creator of AoC was a bit worried about me doing that: https://github.com/borkdude/advent-of-cljc/issues/6

gklijs 2018-12-07T20:15:30.841600Z

If you know the value from the cookie you can get their data

ClashTheBunny 2018-12-07T20:15:31.841700Z

I know.

ClashTheBunny 2018-12-07T20:16:19.842700Z

I just wish there were other options, like give me 5 test cases generated the same way as you do the normal ones that aren't actually for credit.

gklijs 2018-12-07T20:17:33.843200Z

It's worse, the example doesn't match with the actual value needed

borkdude 2018-12-07T20:19:23.843900Z

usually if there are problems, look at https://www.reddit.com/r/adventofcode/ to verify if it’s a real one

borkdude 2018-12-07T20:38:43.845Z

Message from the global leaderboard: > Because of a bug in the day 6 puzzle that made it unsolvable for some users until about two hours after unlock, day 6 is worth no points on the global leaderboard.

borkdude 2018-12-07T20:52:55.846300Z

oh yes, str/join can be called without a sep. so I don’t have to do (apply str coll) which I’m very used to. https://github.com/borkdude/advent-of-cljc/blob/master/src/aoc/y2018/d07/iamdrowsy.cljc#L36

borkdude 2018-12-07T20:53:17.846700Z

and this solution is fast!

2018-12-07T20:53:30.847Z

but also not that pretty 🙂

borkdude 2018-12-07T20:54:01.847300Z

I’m not sure if today has a pretty solution

adammiller 2018-12-07T20:55:48.847700Z

step 1 pretty small simple....step 2 i'm still working on so I don't know yet!

adammiller 2018-12-07T21:06:49.848900Z

although i had problem with step 1 where my solution worked great for their test data but not the real one. Had to create some of my own examples to realize my issue.

taylor 2018-12-07T21:09:59.849400Z

same, I struggled with a bad approach for two hours b/c it passed on the simple example

gklijs 2018-12-07T21:13:45.851800Z

In that case I start to doubt my solution.. I get 14 on the example, but correct answer on the actual one, but a co-worker has the 'correct' answer in both cases

borkdude 2018-12-07T21:17:43.853600Z

@gklijs I got 14 as well a couple of times

2018-12-07T21:19:07.854400Z

I didn’t have any major non-obvious bugs, but I did make a false start. My first pass through, I traversed the graph from leafs to head. Choosing the most expensive node that didn’t depend on anything not yet traversed.

2018-12-07T21:19:36.855100Z

This produced an equivalent traversal for the sample input, but not the test input

2018-12-07T21:21:20.857400Z

Changing the traversal required only changing two words, so thankfully my poor decision didn’t cost much

adammiller 2018-12-07T21:22:10.858Z

did the same exact thing, and yes it was pretty simple to switch from depth to head traversal.

borkdude 2018-12-07T21:22:32.858200Z

Testing aoc.y2018.d07.borkdude
part-2 took 25.33 msecs
part-1 took 1.19 msecs

Testing aoc.y2018.d07.iamdrowsy
part-2 took 11.15 msecs
part-1 took 1.73 msecs

Testing aoc.y2018.d07.mfikes
part-2 took 21.22 msecs
part-1 took 39.40 msecs

mfikes 2018-12-07T21:23:44.859800Z

I had some false starts trying to sort first and then write a stable topological sort. I finally made progress when I carefully read the sample solution sequence and essentially wrote an imitation of that description.

borkdude 2018-12-07T21:24:31.860Z

same here

mfikes 2018-12-07T21:25:03.860700Z

In other words, that bulleted list under the graph is essentially an algorithm.

mfikes 2018-12-07T21:27:18.860800Z

FWIW my part-1 was initially faster, but since perf was good enough, I made part-1 be based on running part-2 in 2nd gear.

borkdude 2018-12-07T21:27:38.861200Z

you mean an algorithm with a name?

borkdude 2018-12-07T21:27:54.861500Z

yeah, I liked your refactor. I was tempted to do the same

mfikes 2018-12-07T21:28:07.861900Z

Nah, I just mean: They are telling you one way to actually solve the problem.

borkdude 2018-12-07T21:28:07.862Z

but I chose to move the common things into a delay instead

borkdude 2018-12-07T21:28:28.862300Z

which is ugly, but it works

mfikes 2018-12-07T21:28:35.862600Z

Instead of just leaving you with a problem description.

borkdude 2018-12-07T21:29:18.863200Z

yeah, you had to read very closely.

mfikes 2018-12-07T21:30:44.864100Z

Yeah, I didn't read that part initially (it is arguably not essential), and doggedly pursued my own path. When I saw the word "available" in that description, that did the trick for me.

taylor 2018-12-07T21:30:50.864200Z

which I did not do at first 🙂

mfikes 2018-12-07T21:31:43.864700Z

Perhaps many readers stop right at the sentence "If more than one step is ready, choose the step which is first alphabetically." (Recognizing that it is a partial order that it turned into a total order by that constraint.)

➕ 1
mfikes 2018-12-07T21:35:33.866200Z

We need to get Wastl to add {:year 2018} to that little "year clicker" in the upper left of the main part of the page 🙂

👌 1
borkdude 2018-12-07T21:35:48.866600Z

I wonder how much fun Eric Wastl had by creating this. Oh, do these two things in one iteration sometimes so people get an off by one error probably

2018-12-07T22:00:35.868700Z

Interesting that on my data set and @borkdude’s data set I never had more than 5 tasks ready at a time, so I never ran out of workers. I engineered my solution (incorrectly I think) to handle a backlog of ready tasks but it never came into use. I wonder if this is true for all data sets?

benoit 2018-12-07T22:02:15.869400Z

@ben.grabow I think you were right to do it this way. There was no way to know this from the description of the problem.

2018-12-07T22:04:04.871600Z

I say "incorrectly" because I think my implementation is wrong, not because it's unnecessary. I am taking items out of the backlog in the order they were unblocked, when I should be taking out in alphabetical order at the time a worker is available.

benoit 2018-12-07T22:04:22.871800Z

oh ok

adammiller 2018-12-07T22:19:52.873Z

I only did that in the first part. Haven't done the 2nd part yet, although i was trying a similar solution but no luck as of yet.

fellshard 2018-12-07T22:20:43.873500Z

The visual chart they give for part 2 basically tells how to interpret it, I think

fellshard 2018-12-07T22:21:06.874200Z

Each letter on each row represents a full second starting at that number that is dedicated to that work

fellshard 2018-12-07T22:22:11.874800Z

https://en.wikipedia.org/wiki/Topological_sorting

🙏 1
fellshard 2018-12-07T22:22:30.875300Z

So the first row says 'starting at time 0, C is being worked on for one second, meaning that work on C will continue until at least the 1-second mark; it fills that entire first second.

fellshard 2018-12-07T22:23:06.875900Z

Extend that to the penultimate row, where the last piece of work is being done: 'starting at time 14, E is being worked on for one second'

fellshard 2018-12-07T22:23:28.876600Z

This means that the work on E finishes at second 15

fellshard 2018-12-07T22:24:12.877300Z

Being consistent in how you frame each step in terms of the overall time is a bit tricky, for sure

mfikes 2018-12-07T22:28:00.877700Z

I sent this to Eric: https://twitter.com/mfikes/status/1071169374587899905

4
mfikes 2018-12-07T22:41:18.879800Z

👍 9
6
🤘 1
2018-12-07T22:44:07.881500Z

Later tonight I'm going to take another stab at d6p2. I think it can be wildly efficient. If my reasoning is correct, then the "total manhattan distance" map has a consistent x-profile at every y-value, and a consistent y-profile at every x-value. To get the solution you compute one x-profile, one y-profile, then you can use those two profile to compute the rest of the "total manhattan distance" map without looking up the points at all. I feel like this would be instantly obvious when looking at a visual representation of the answer.

2018-12-07T22:46:49.882200Z

part2 is not very clean, and I think now I even see a a bug, but part 1 is a relatively straightforward traversal using loop. I’ll step through it here.

2018-12-07T22:48:13.882400Z

I represented the graph exactly like a the input. I have a vector of edges like [“C” “A”] which means there is an edge from C to A.

2018-12-07T22:49:05.882600Z

A very simple approach is to maintain a list of nodes you’ve visited and a list of nodes you haven’t visited

2018-12-07T22:50:07.882800Z

Then have a function that picks an unvisited node that is reachable and visit it. (move it from the unvisited list to the visited list) You repeat until you are done

2018-12-07T22:51:11.883100Z

In my solution here, I maintain the graph, the nodes list (everything I can visit) and the visited list (in order)

2018-12-07T22:51:58.883300Z

The function next-work does the job of selecting the next node I should visit (the lowest of all the ones I can visit).

2018-12-07T22:52:06.883500Z

I think what is tripping me up is how to find the newly unblocked nodes by traversing the dep graph from a newly completed node. Right now I'm doing a bunch of filtering over the entire list of nodes.

2018-12-07T22:52:43.883700Z

I did this by removing he unblocked edges from the graph

☝️ 1
2018-12-07T22:53:31.883900Z

So if I visit “C” , I remove [“C” “A”] and [“C” “F”] from the graph

2018-12-07T22:53:56.884100Z

and by doing so, A and F becoming visitable

2018-12-07T22:56:25.884300Z

In removing the edges like this I only have to ask for any node N if there as an edge [? N].

2018-12-07T22:56:54.884500Z

If you don’t remove the edges, you’d jave to ask if there is an edge [? N] where ? is not visited

2018-12-07T22:59:43.884700Z

It seems like I need two graphs, one of X -blocks-> Y and one of Y -is-blocked-by-> X. I follow the first graph to find the potentially unblocked nodes when a node is completed, and I use (and modify) the second graph to figure out if a potentially unblocked node is actually unblocked. Without those I think I need to do some set-based or iteration-based queries along the way. Does that sound right?

2018-12-07T23:02:53.884900Z

You could invert the graph, but there’s really no need

pesterhazy 2018-12-07T23:06:07.886200Z

Those curly braces take a while getting used to but after while you stop seeing them

2018-12-07T23:06:34.886400Z

If there is a edge [“X” “Y”], which means “X” before “Y”, if you’ve visited “X” then you can disregard the edge. There’s nothing more to check

2018-12-07T23:08:09.886600Z

Makes sense. Thanks for the explanation, it helped a lot!