13
votes
Day 3: Crossed Wires
Today's problem description: https://adventofcode.com/2019/day/3
Join the Tildes private leaderboard! You can do that on this page, by entering join code 730956-de85ce0c
.
Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace python
with any of the "short names" listed in this page of supported languages):
<details>
<summary>Part 1</summary>
```python
Your code here.
```
</details>
So, this year's event is my first experience with Elixir, so this is very likely not that elixiry. Even just glancing over this now, I saw a few obvious improvements. But it works, so.
Both solutions are in the same file and use common functions, so I won't try to split them.
Part 1 and Part 2
Copy pasted from my original comment in the original thread
Day 3: Crossed Wires
So I had two attempts at this one. Both of them work and both of them are truly horrible. Good programmers who do not want to poison their minds please look away now. (but hey, at least they both get the same, correct answer).
Part 1 Attempt 1
This is horrible. I used an absolutely massive two dimensional array to visualise the wires. When it runs it uses about 3.2GB's of ram and takes a minute or so to get the result.
I used tabulate to visualise the grid when it was small (10x10) for testing. I took this out for the final, massive array.
I kept on having to increase the size of the array, because the wires kept on going outside of it and causing errors. It worked at 20,000 by 20,000. (very big).
Also I kept on having weird issues where I would set an array to be equal to another array, and then if I changed the first array, the second one would also change. I fixed that by using some jank. For attempt 2 I learned when you say array = array2, they are both the same object, so you need to say array = array2[:] to make them separate.
So perhaps visualisation is not so great when dealing with very big things.
I thought that this was so bad that I should really give it another crack. But I think attempt 2 is arguably worse.
Part 1 Attempt 2
So I thought, rather than make a massive array, why don't we just record every single place that the first line goes (a different, massive array), and then when figuring out the second line, check each place to see if it's in a spot that the first line has also been. If it is, then record those coordinates. Then do the same figuring out to find the closest one.
The good: This uses significantly less memory than the previous attempt (I didn't measure it but gotop didn't show any massive climbs like attempt 1 did)
The bad: This is very slow. Slower than slow. It took 8 minutes to get the correct answer. The guy who completed this challenge first did it in 2 minutes and 38 seconds. They could program this whole thing ~3x faster than I could run mine.
I tried reducing this time by checking if something has already been added to the "history" of the first line and then not adding it a second time (or perhaps more), reducing the size of the array and therefore hopefully making the comparisons quicker. But this made more checks have to be done, so it actually slowed it down. The modified code takes 11 minutes and 40 seconds to run. Ooops! I left that check code in but commented out.
I noticed that when it was being slow, it was getting slow in the "for j in range(Amount):" loops.
When the loops do an "if not CurrentPos in History:" check (for the first line, this is the thing I added to try speed it up that actually slowed it) they go slow. When they check is not present, the first part of the code completes very quickly.
Of course the "if CurrentPos in History:" checks are pretty necessary on the second line because how else would I check if the lines intersect. So this part is still slow.
Perhaps I could speed it up by just storing the end points of each line segment (eg 200,200 and 200,220 could be one segment) and then checking if the proposed spot falls within that range. I'm not sure if this will be faster though and I'm too tired at the moment to try it. Perhaps another time.
Please don't make me feel too bad about what I've just done.
As for Part 2, I'm tired and I'm not sure I will be able to do it. I'll give it a shot another day.
I'm a few days behind, but giggling at this. Love the self depreciation. 3.2 GB of RAM!
At least it works.
For the intersection I had a hard time. I was googling around for a while and found that tuples are better for each coordinate as they're hashable and you can use sets and map() to find the commonality. Thankfully all I had to do was change [] to () but to figure that out took me extensive googling.
Language: Rust
This problem was much more intricate, so the code is much more complicated. I really wish it was cleaner and easier to follow. I had to refactor several times to get part 2 to work at all. If people have readability suggestions, I'm willing to listen (though, please don't be too pedantic).
When I first started working on this problem, I tried to be clever and account for the case where two horizontal or two vertical wires crossed, and then choose the correct point. It's possible, but super complicated and not necessary for the problem, so I gave up (hence the
_
case in thecross_*()
functions).Part 1 and 2
Okay, this was easier than I thought, although I got stuck for quite a bit because I forgot not to count a wire crossing with itself. It also took me a few minutes to figure out that it was only interpreting the first digit of the direction because I didn't convert it into an integer; I'll have to look more into that.
awk
solutions:Part 1
Part 2
My solution below does both part 1 and 2. It is definitely very gross to look at, but much better than my first implementation for the first part that would have needed something like 23 billion comparisons to do the puzzle input.
Since things got kind of complex I decided to add some simple tests to check my work, I think that was helpful for figuring out what was going wrong. Also pretty pleased with how I packaged things up into functions, even if some of the individual functions are messy.
Parts 1 and 2