Advent of Code 2019 Solution Megathread  Day 3: Crossed Wires
Jon Bristow Updated on ใป2 min read
Advent of Code 2019 Solutions (25 Part Series)
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 doing the wiring for our fuel management system! While we have the time, let's get in there and untangle the shorting out wires and replace it with its more ideal version.
Part 1 was fairly straightforward, but since I didn't know how to convert this into nice intersecting systems of equation, my brute force solution ran into a heapspace problem.
Part 2 was a bit hairy, because I had to back out one of my optimizations for part 1, which revealed (eventually) an issue with how I was calculating the points it passed through.
Overall I would rate this a fairly difficult day 3!
Ongoing Meta
Dev.to List of Leaderboards

1206355c140b9a
 provided by Linda Thompson
If you were part of Ryan Palo's leaderboard last year, you're still a member of that!
If you want me to add your leaderboard code to this page, reply to one of these posts and/or send me a DM containing your code and any theming or notes youโd like me to add. (You can find your private leaderboard code on your "Private Leaderboard" page.)
I'll edit in any leaderboards that people want to post, along with any description for the kinds of people you want to have on it. (My leaderboard is being used as my office's leaderboard.) And if I get something wrong, please call me out or message me and Iโll fix it ASAP.
There's no limit to the number of leaderboards you can join, so there's no problem belonging to a "Beginner" and a language specific one if you want.
Neat Statistics
I'm planning on adding some statistics, but other than "what languages did we see yesterday" does anyone have any ideas?
Advent of Code 2019 Solutions (25 Part Series)
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/advento...
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 fullpoint 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+n^{2} (aka n^{2} ), 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!
Not sure if it's the most efficient way of doing it, but this is how I solved it
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!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. :)
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.
Scala! I'm slowly falling in love with this language.
I way over thought this last night, and had a solution that worked but it was gnarly. Refactored this morning:
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.
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 :)
My brute force JS code. Still looking into a more optimized solution
More browser antics. I think I can refactor this, and possibly make it faster, but it's fast enough.
C++
Part 1
Part 2
Beautiful code Sr. Really straight forward and easy to read and understand.
Today was a challenging Day 3! I was definitely overthinking this problem, and I also ended up accidentally deleting my Part 1 implementation before moving on to Part 2...it's one of those days ๐. Here's what I got:
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 functionoriented 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:
Day 3 in two (convoluted) parts:
Day 3 part 1
Day 3 part 2
Both Clojure
Here's my solution with Clojure. It is generating all the points in the lines, which seems a bit bruteforce, 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/adventofcode...
I am just beginning and I enjoy the language very much :).
It took me quite a bit of time to solve both problems, but I believe I've implemented a relatively optimized solution:
My ugly solution in C , after hours unfortunately :(
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.
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!