Last active
February 6, 2021 03:38
-
-
Save jbosse/bea80d713e6362b331b8c94c1df12db9 to your computer and use it in GitHub Desktop.
Trapping Rain (https://leetcode.com/problems/trapping-rain-water/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Rain do | |
def trap(heights) do | |
answer = 0 | |
index_l = 0 | |
index_r = Enum.count(heights) - 1 | |
max_l = 0 | |
max_r = 0 | |
count(heights, answer, index_l, index_r, max_l, max_r) | |
end | |
defp count(heights, answer, index_l, index_r, max_l, max_r) when index_l < index_r do | |
height_l = Enum.at(heights, index_l) | |
height_r = Enum.at(heights, index_r) | |
count(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) | |
end | |
defp count(_heights, answer, _index_l, _index_r, _max_l, _max_r), do: answer | |
defp count(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) when height_l < height_r and height_l >= max_l do | |
count(heights, answer, index_l + 1, index_r, height_l, max_r) | |
end | |
defp count(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) when height_l < height_r do | |
trapped = max_l - height_l | |
count(heights, answer + trapped, index_l + 1, index_r, max_l, max_r) | |
end | |
defp count(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) when height_r >= max_r do | |
count(heights, answer, index_l, index_r - 1, max_l, height_r) | |
end | |
defp count(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) do | |
trapped = max_r - height_r | |
count(heights, answer + trapped, index_l, index_r - 1, max_l, max_r) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule RainTest do | |
use ExUnit.Case | |
test "calculates trapped rain" do | |
assert Rain.trap([0,1,0,2,1,0,1,3,2,1,2,1]) == 6 | |
assert Rain.trap([4,2,0,3,2,5]) == 9 | |
assert Rain.trap([4,2,0,5,5,3]) == 6 | |
assert Rain.trap([0,1,2,1,2,1,2,3,4,3,2,1,2,0]) == 3 | |
assert Rain.trap([5,0,5,5,5,5,1,5,5,2,5,5]) == 12 | |
assert Rain.trap([1,2,3,4,5,4,3,4,5,5,4,3,2,1,2,3]) == 8 | |
assert Rain.trap([5,5,5,5,5]) == 0 | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Rain do | |
def trap(heights) do | |
answer = 0 | |
index_l = 0 | |
index_r = Enum.count(heights) - 1 | |
max_l = 0 | |
max_r = 0 | |
count(heights, answer, index_l, index_r, max_l, max_r) | |
end | |
defp count(heights, answer, index_l, index_r, max_l, max_r) when index_l < index_r do | |
height_l = Enum.at(heights, index_l) | |
height_r = Enum.at(heights, index_r) | |
cond do | |
height_l < height_r -> | |
cond do | |
height_l >= max_l -> | |
count(heights, answer, index_l + 1, index_r, height_l, max_r) | |
true -> | |
trapped = max_l - height_l | |
count(heights, answer + trapped, index_l + 1, index_r, max_l, max_r) | |
end | |
true -> | |
cond do | |
height_r >= max_r -> | |
count(heights, answer, index_l, index_r - 1, max_l, height_r) | |
true -> | |
trapped = max_r - height_r | |
count(heights, answer + trapped, index_l, index_r - 1, max_l, max_r) | |
end | |
end | |
end | |
defp count(_heights, answer, _index_l, _index_r, _max_l, _max_r), do: answer | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Rain do | |
def trap(heights) do | |
answer = 0 | |
index_l = 0 | |
index_r = Enum.count(heights) - 1 | |
max_l = 0 | |
max_r = 0 | |
loop(heights, answer, index_l, index_r, max_l, max_r) | |
end | |
defp loop(heights, answer, index_l, index_r, max_l, max_r) when index_l < index_r do | |
height_l = Enum.at(heights, index_l) | |
height_r = Enum.at(heights, index_r) | |
scan(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) | |
end | |
defp loop(_heights, answer, _index_l, _index_r, _max_l, _max_r), do: answer | |
defp scan(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) when height_l < height_r and height_l >= max_l do | |
new_index_l = index_l + 1 | |
new_max_l = height_l | |
loop(heights, answer, new_index_l, index_r, new_max_l, max_r) | |
end | |
defp scan(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) when height_l < height_r do | |
new_index_l = index_l + 1 | |
trapped = max_l - height_l | |
new_answer = answer + trapped | |
loop(heights, new_answer, new_index_l, index_r, max_l, max_r) | |
end | |
defp scan(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) when height_r >= max_r do | |
new_index_r = index_r - 1 | |
new_max_r = height_r | |
loop(heights, answer, index_l, new_index_r, max_l, new_max_r) | |
end | |
defp scan(heights, answer, index_l, index_r, max_l, max_r, height_l, height_r) do | |
new_index_r = index_r - 1 | |
trapped = max_r - height_r | |
new_answer = answer + trapped | |
loop(heights, new_answer, index_l, new_index_r, max_l, max_r) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Rain do | |
def trap(heights) do | |
state = %{ | |
heights: heights, | |
answer: 0, | |
index_l: 0, | |
index_r: Enum.count(heights) - 1, | |
max_l: 0, | |
max_r: 0, | |
} | |
loop(state) | |
end | |
defp loop(%{index_l: il, index_r: ir} = state) when il < ir do | |
loop_state = state | |
|> Map.put(:height_l, Enum.at(state.heights, il)) | |
|> Map.put(:height_r, Enum.at(state.heights, ir)) | |
scan(loop_state) | |
end | |
defp loop(%{answer: a}), do: a | |
defp scan(%{height_l: hl, height_r: hr, max_l: ml} = loop_state) when hl < hr and hl >= ml do | |
new_loop_state = %{loop_state | index_l: loop_state.index_l + 1, max_l: hl} | |
loop(new_loop_state) | |
end | |
defp scan(%{height_l: hl, height_r: hr} = loop_state) when hl < hr do | |
trapped = loop_state.max_l - hl | |
new_loop_state = %{loop_state | index_l: loop_state.index_l + 1, answer: loop_state.answer + trapped} | |
loop(new_loop_state) | |
end | |
defp scan(%{height_r: hr, max_r: mr} = loop_state) when hr >= mr do | |
new_loop_state = %{loop_state | index_r: loop_state.index_r - 1, max_r: hr} | |
loop(new_loop_state) | |
end | |
defp scan(loop_state) do | |
trapped = loop_state.max_r - loop_state.height_r | |
new_loop_state = %{loop_state | index_r: loop_state.index_r - 1, answer: loop_state.answer + trapped} | |
loop(new_loop_state) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment