Here is the map of a two-dimensional hill station where each digit indicates the height of the corresponding position. How much water accumulates in the hill after the rainfall?
Details and Assumptions:
1 2 3 |
|
1 2 3 |
|
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
I like when the code is short, so there was a time-efficient solution to the problem. The key is to check the map layer by layer, and find any areas that are not connected to the edges. You can find the previous solution here . See an improved solution in the next section.
This solution can use fractions as tile-heights, as well as huge positive and negative values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
1 2 |
|
Haha, there are no caves, if there is a hill of height H, then it is a solid hill of height H all the way down.
What is the complexity of your solution? linear in the number of squares?
Log in to reply
Yeah, in the worst case scenario the algorithm checks every square in every layer, that is (width * height * depth) squares. The depth in here is the difference of the highest hill and the lowest valley (9 for that problem)
Log in to reply
Can there be an algorithm whose complexity is independent of the depth?
Log in to reply
@Agnishom Chattopadhyay – I think I have an idea how it could be done! I'll post my results once I try it out.
Log in to reply
@Mykyta Shvets – Great, I look forward to seeing your answer
Log in to reply
@Agnishom Chattopadhyay – Uhm, it's kinda up here. It won't check all layers 0 through 100 if you have a map with spikes like [0, 100, 0, 50]. And it now can handle positive and negative infinity tiles!
I wonder how the 3d version of this problem will look like!
This is the second part for my solution, the first being my original approach and code which can be found below. Since when I first wrote this solution, I have rewritten parts of my code using a much more efficient approach. Inspired by a comment by Agnishom Chattopadhyay, my improved program uses a psuedo-breadth first style approach, which works the following way:
With this approach every block will only be checked once, instead of the below method in which layers had to be ran through multiple times in the simulation. This method takes only about 2 seconds to run, which is once again significantly slower than the code below. This is likely the most optimized this solution is going to get, and I'm honestly a bit surprised this code has gotten to running so fast.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
Seeing this problem for the first time at the start of a family road trip, I had many hours and, sadly, only my phone to write some program for this problem. While I didn't do much planning the general approach I took was the following:
With some sort of plan in mind and plenty of time, I started implementing the code, testing what I had wrote on a couple of small sample cases for the problem. I decided to represent the data as an array of integers, and wrote a helper method create an array of each integer's digits. Finally, after quite some time, I had (what I thought was) a fully functioning program to calculate the remaining water. At last it was time to copy over the quite large 100x100 question data and watch the program run. After typing many commas I finally pressed run and waited for the program to complete, until...the code ran out of execution time. Dang it.
After spending a while optimizing my code I realized how long that program was going to take to run regardless of my efforts and decided to wait until I could copy it into my own computer, with the joys of unlimited execution time. Before postponing my quest the rest of the ride, I realized that any line starting with a zero would be improperly interpreted because the data was stored as an integer, so I decided to instead store that data as an array of strings (which also majorly simplified a pretty unreliable digit gathering method). Finally after getting back to our hotel I was able to run my code without the constraint of efficiency, and after about a pretty slow 20 minutes of waiting received an answer that turned out to be correct. I've consolidated my fairly messy code the best I could below, but I found this program to be quite fun and satisfying to create. The following code will successfully print out the water remaining for any square matrix of test data when given enough time, and I hope you will find it as interesting to interpret as it was for me to write.
Only about a day after writing this solution for the first time did I notice what was making this program so massively inefficient. The method to return a value at each position would have to create a gigantic array each time it was run, which was causing a majority of the time inefficiency. I realized that I could instead assign a value for which represents the hill, water, and air instead of just one for the water and "emptiness" (which would represent both the hill and the air). Now i could just return the value in the position array instead of referencing the hill, which shortened the run time from 20 minutes to...around 10 seconds! The program can now run completely in brilliant's coding environment, which is a major improvement from before. I've replaced the code below to be the efficient version, but have left the inefficient method below if you want to see what caused such a major time waste.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Hey, great job on the hard work. I hope you had fun!
So currently, your program depends on the maximum height of the hills. But something tells me that it might be possible to solve this in a way that is independent of this height. For example, let us say, we had the exact same numbers but multiplied every hills height by 10, in which case it intuitively looks like there should be a simpler way to solve this, rather than doing a layer by layer simulation.
I am guessing there could be breadth first search style approach where you could start filling in from the outerwalls where the water level is the lowest.
Log in to reply
Thanks! Because each value was being represented by a single digit I just limited the heights to 10, but for every new layer of height added the program does gets significantly slower. Now that you’ve mentioned breadth first searching I think I’ll try writing a much more efficient program with a queueing approach, where water connected to the bottommost water blocks for each height is removed. I’ll post that under my previous code once I’ve made some progress, thanks for the suggestion!
Log in to reply
That'd be interesting. I look forward to seeing your idea in action.
Problem Loading...
Note Loading...
Set Loading...
Red indicates no water on cell.
the darker the color the deeper the water is on each cell of the hill.
The dark green indicates no water ( hill is exposed)
The lighter the color the higher the elevation of the standing water on the hill.
Charts where made using conditional formatting in an Excel sheet. I thought someone else may be interested to see a graphical image of the water standing on the hill. These grafts have no value other then my curiosity, interest, and amusement in getting a real world feel for the solution.
I posted this as a different approach to the solution. More eloquent solutions have bean posted. Considering I am a newby to Pyton just getting started looking through a couple of online tutorials and examples a few days ago, I am satisfied with the results. This was my first attempt to do anything in Python.