It's day 3, and we've gone from code interpreters to spatial mapping.
Day 3 - The Problem
Looks like someone wasn't very organized when...
For further actions, you may consider blocking this person and/or reporting abuse
Not sure if it's the most efficient way of doing it, but this is how I solved it
So, I see everyone did it like I did - recording all visited nodes on the grid and checking for intersections. Now, without considering part 2, is there a smarter way? I'm pretty sure there has to be.
You can generate segments with only the start and end points and check where they intersect, which would require less memory. But the math is more complicated and I'm not sure it's faster, since you can't use a hash table to find the intersections.
This is how did it (I assumed the memory requirement of enumerating all of the visited nodes in the grid would be too much).
buuut the code got really messy and I don't know if there's a cleaner way to do it.
It's so long I don't want to reproduce it here 😱 github.com/MustafaHaddara/advent-o...
The only thing I can see right off the bat is that you’re checking for vertical/horizontal via start/end points, but you could have kept that information (UDLR) alongside the line segment definition. Other than that it makes sense, and other than being too deeply nested for my compulsive refactoring instinct, it doesn’t look much longer than my full-point enumerator.
(If you use a linked list, it doesn’t take more than 30 seconds or so for part b)
d'oh that would have made things much more readable.
I was complaining to a coworker that I've done collision detection for 2d games before, and this felt similar, but is sort of like "hard mode" because I didn't necessarily know which endpoint of each line was on the left/right or top/bottom. Keeping that info would have made things more straightforward!
It’s why I love working with people who know the same codebase as me! When you PR or rubber duck, you often get some perspective that makes the “ugly” bits fall into place that you were too close to see!
I think I have a way it wouldn’t be ridiculous, but you have to process the list with both solutions in mind so you only have to do one Cartesian join.
First precalculate all the start/end points of each instruction in each wire.
Then, for each piece of wire a, go looking for all pieces of wire b that intersect. You should do this while keeping track of how far you’ve come on wire a. Likewise, while looping through wire b, you should keep track of your distance so it can be recorded in the data structure that captures the intersection point. Anyway, flatmap this all into one list.
Once you have them all, then you can do two different minBy type lookups to find answers a and b.
It seems more space and memory efficient. The processor efficiency seems like it’s a wash though.
I think my solution has a similar big O: 3n+n2 (aka n2 ), but the size of n in this pseudo code is the number of instructions, not points. In my input, the number of points is several orders of magnitude higher than the number of instructions and intersection points. Additionally, the code for calculating the “bend positions” of the wire is also way less complicated since you’re not appending lists to lists.
This is how I did it last night! Ended up being way slower and the code was much uglier.
That's what I suspected would happen. I think the best optimization is to calculate the list of points for both paths and then convert one of them to a hash table and iterate over the other one and filter out the elements that are not in the hash table. This is complexity O(n) because iterating over one list is O(n) and checking whether a random element exists in a hash table is still O(1). I don't think any smart trick with segments can get a better complexity.
PHP, because I'm having to learn it at my internship at the moment. Something isn't right here, because it takes several minutes to run, but at least the solution appears eventually.
If you’re enumerating every point you’re operating with two lists of hundreds of thousands of items. Worse, I don’t think there’s a way around a cartesian join of the two sets (potentially squaring your already hideous number of data).
Running into performance problems is expected, driving the solution into minutes if you’re not careful (I crashed my jvm and lost a few minutes manually killing it and my ide as they consumed as much processor and memory power as they could)
I was able to improve the speed hugely with just a little tweaking, from over 7 minutes to around 0.1 seconds!
Took me an extra day to clean it up so I wasn't disgusted with it. I definitely followed the Advent of Code "Brute Force until proven otherwise" approach. I considered doing it by only considering each leg of wire as two endpoints and calculating the intersections, but this was easier and more straightforward.
I also tried out Rust's type aliases to make things read a bit easier, which I'm really happy with.
Part 2 almost got me with a sneaky "Off by Two" error. I forgot to count the step off of the origin on both wires, leading me to be short by 2 on my final answer. A quick test case based on the examples provided showed I landed at 608 instead of 610 and I got suspicious.
Altogether much happier with this than I was last night. :)
Had to reach for Haskell again. This may happen on the hard ones! Solved it using correct line segment intersections rather than enumerating every single coordinate.
Scratched my head on part 2 for a bit then realised each segment could store the accumulated length, then it was a simple shortening calculation for each line at the intersections.
I'm not proud of that
intersection
function. 12 variables in scope. The horror!I still have nightmares from previous year's assignment based on coordinates, but luckily this wasn't as bad. Here's my solution for part two in Elixir:
Check part one here
Woo! Day 3 is in the bag. :D
I'm hosting my solutions on repl.it, and this one they don't let me finish calculating - I'm gonna have to look for some better optimization in order to let it finish within the resource boundary they set.
Anyway, I was able to handle the calculation locally and got the answers. I used the instructions to create sets of visited points, and then used set intersection to find the crossings. From there, it was finding either the minimum distance from the origin, or finding the minimum walk distance.
C++
Part 1
Part 2
Beautiful code Sr. Really straight forward and easy to read and understand.
I way over thought this last night, and had a solution that worked but it was gnarly. Refactored this morning:
More browser antics. I think I can refactor this, and possibly make it faster, but it's fast enough.
My brute force JS code. Still looking into a more optimized solution
Solution with Swift. Took a long route and first tried with Int Array and failed. Went with Set second time and seems working. But its very slow even on my MacBook Pro. :(
Definitely looking forward to improve my solution by getting inspiration from others code :)
Kotlin Solution! No monads today, sadly, but I pulled in Java's LinkedList implementation for memory efficiency.
I tried to draw the full layout represented by my input as ascii, but it turned out to be a 200MB file. Imagemagick filled my hard drive trying to parse it.
Scala! I'm slowly falling in love with this language.
Woooooo, finally got this one! Took me 2 days, but dangit I solved it on my own and I feel super pleased and relieved. lol
What's lame is I basically had the right idea yesterday, but wasn't adding the absolute value of the coordinates, so was getting the wrong values back and thought my whole solution was wrong. 😒 So I rage deleted everything last night, and rewrote it all today and got it working! 😊
Got to use a set for the first real time, which worked out nicely! I figured I could plot out each coordinate visited by the first wire, and store those in a set (since where a wire crosses itself doesn't matter). Then, for the second wire, I go through and just check to see if the set contains that coordinate already, and if so, store that in it's own array to check over at the end. Ran pretty quickly, though I'm sure I could factor the code to be a bit more function-oriented than I did. Just wanted it to work! lol
Thankfully, part 2 didn't take me all that long...just refactoring my first path run to count the steps taken so far and figure out how/where to store them, then adding it as an extra value onto the end of my crossed points array. Easy! (Ending up reading my coords and counter as a string, so that comparisons were easier to do.)
JavaScript:
I'm using AoC this year to learn Python. Last year I used it to learn nodejs.
Day 3 was a doozy for me, partly because I started it at 11pm (I'm on American Central Time), but partly because I overthought the problem and thought I would map the whole thing as a 2D array. After screwing my head on a little bit more, I went with simply tracking the path of the wire with x/y tuples, then finding the intersections between the two wires. Manhattan distance was baked into each tuple (just add the absolute values of x and y together and voila).
For my first crack at Part One, I originally used sets. When I discovered Part Two, I just had to change the sets to lists and then I got path distance for free.
My ugly solution in C , after hours unfortunately :(
Day 3 in two (convoluted) parts:
Day 3 part 1
Day 3 part 2
Both Clojure
It took me quite a bit of time to solve both problems, but I believe I've implemented a relatively optimized solution:
Here's my solution with Clojure. It is generating all the points in the lines, which seems a bit brute-force, but at least on my machine it works swiftly;)
I'm also posting my solutions to github.
Wow, your solution is so compact!
Mine is very verbose, and I am not done with part 2 yet! (will try tonight, but it's hard when working 11h a day...).
Maybe you could have a look on my solution and give me some pointers on how I could get better at Clojure?
gitlab.com/simonced/advent-of-code...
I am just beginning and I enjoy the language very much :).
Can somebody help with undesrstanding the premise.
I am a little bit confused from the description of part 1. What should be considered the central port?
Well, technically it can be anything you want!
However, since the answer is the distance from the "center port", you might as well make things easier on yourself by declaring that it is
(0,0)
Oh, ok. Thank you!