You are given an array representing heights of towers. It starts raining. Determine how much water is collected between the towers, assuming each tower has width of 1.
Example:
Input: [3, 4, 2, 7, 4, 3, 8, 2, 4]
Expected Output: 11 units of water
*
* W W *
* W W *
* W W *
* W * * W * W *
* * W * * * * W *
* * * * * * * * *
* * * * * * * * *
The problem can be solved in two ways, either iteratively or recursively with dynamic programming. Both rely on the observation that the amount of water collected atop any tower is determined by the shortest of the tallest tower to the left and right of itself. The iterative solution is presented.
Iterative approach
The algorithm iterates through the tower height array twice. First time to determine the tallest tower to the right for each tower, and second time to determine the tallest tower to the left. Then, the minimum of tallest towers at each location is calculated to determine water capacity at that location. Here's the code in Swift.
//
// waterTower.swift
//
// Created by Chris Kuo on 1/28/16.
//
var towers = [3, 4, 2, 7, 4, 3, 8, 2, 4] // Test input
var width = towers.count // width of the tower array
var hr = towers // highest tower to the right of towers[i], inclusive
var hl = towers // highest tower to the left of towers[i], inclusive
for var i in 0..<width-1 {
// For each x location, find tallest tower to the right, including self
for var j in i..<width {
hr[i] = (hr[j] > hr[i]) ? hr[j] : hr[i] // update hr[i] if hr[j] is larger
}
}
for var i = width-1; i > 0; i-- {
for var j = i; j >= 0; j-- {
hl[i] = (hl[j] > hl[i]) ? hl[j] : hl[i] // update hr[i] if hr[j] is larger
}
}
// the "capacity" at each location is the minimum of max heights
// to left or right, minus own height
var capacity = [Int](count: width, repeatedValue: 0)
for var i in 0..<width {
capacity[i] = min(hr[i], hl[i]) - towers[i]
}
// Calculate total water collected
var sum = 0
for x in capacity {
sum += x
}
// Print out input and solution
print("Input: \(towers)")
print("Output: \(sum) units of water")
// Print graphical representation of input and solution
print("")
for var height=towers.maxElement()! ; height > 0; height-- {
for var i in 0..<width {
if height > towers[i] + capacity[i] {
print(" ", terminator: " ")
} else if height > towers[i] {
print("W", terminator: " ")
} else {
print("*", terminator: " ")
}
}
print("")
}
//
// waterTower.swift
//
// Created by Chris Kuo on 1/28/16.
//
var towers = [3, 4, 2, 7, 4, 3, 8, 2, 4] // Test input
var width = towers.count // width of the tower array
var hr = towers // highest tower to the right of towers[i], inclusive
var hl = towers // highest tower to the left of towers[i], inclusive
for var i in 0..<width-1 {
// For each x location, find tallest tower to the right, including self
for var j in i..<width {
hr[i] = (hr[j] > hr[i]) ? hr[j] : hr[i] // update hr[i] if hr[j] is larger
}
}
for var i = width-1; i > 0; i-- {
for var j = i; j >= 0; j-- {
hl[i] = (hl[j] > hl[i]) ? hl[j] : hl[i] // update hr[i] if hr[j] is larger
}
}
// the "capacity" at each location is the minimum of max heights
// to left or right, minus own height
var capacity = [Int](count: width, repeatedValue: 0)
for var i in 0..<width {
capacity[i] = min(hr[i], hl[i]) - towers[i]
}
// Calculate total water collected
var sum = 0
for x in capacity {
sum += x
}
// Print out input and solution
print("Input: \(towers)")
print("Output: \(sum) units of water")
// Print graphical representation of input and solution
print("")
for var height=towers.maxElement()! ; height > 0; height-- {
for var i in 0..<width {
if height > towers[i] + capacity[i] {
print(" ", terminator: " ")
} else if height > towers[i] {
print("W", terminator: " ")
} else {
print("*", terminator: " ")
}
}
print("")
}
With the test input of [3, 4, 2, 7, 4, 3, 8, 2, 4], the program outputs the following:
Input: [3, 4, 2, 7, 4, 3, 8, 2, 4]
Output: 11 units of water
*
* W W *
* W W *
* W W *
* W * * W * W *
* * W * * * * W *
* * * * * * * * *
* * * * * * * * *
That's it, folks!
The information in the post you posted here is useful because it contains some of the best information available. Thanks for sharing it. Keep up the good work esd workbench
ReplyDelete