Home Posts Tags Post Search Tag Search

Post 46

Hacker Rank 20 - Max Fence Height

Published on: 2025-07-07 Tags: elixir, Side Project, Hacker Rank
For this one we need to figure out the largest rectangle that would be made by a set of single unit wide boards on a fence. 

Sample Input
6
2 5 7 4 1 8

Sample Output
12

To do this we want to use a stack and an index set of board heights. With this we can add in new indexed heights to the stack and pop them when we get a new height that is less than the top of the stack. 


Step 1: Add a Sentinel Bar

We add a sentinel 0 at the end of the list. This ensures we flush all remaining bars from the stack at the end.

posts = posts ++ [0]
indexed = Enum.with_index(posts)

Now indexed looks like:

[{2, 0}, {1, 1}, {5, 2}, {6, 3}, {2, 4}, {3, 5}, {0, 6}]

📌 Step 2: Initialize Stack and Max Area

We use a stack to store {height, index} pairs. It helps track bars in increasing height order. We also track the max_area.

rectangle_loop(indexed, [], 0)

📌 Step 3: Main Loop

We loop through each {height, index} from the histogram:

def rectangle_loop([], _stack, max_area), do: max_area

def rectangle_loop([{height, index} = current | tail], stack, max_area) do
  case stack do
    # If the current height is less than the top of the stack
    [{top_height, top_index} | rest] when height < top_height ->
      # 🔁 Step 4: Pop from stack and calculate area
      width = case rest do
        [{_, prev_index} | _] -> index - prev_index - 1
        [] -> index
      end

      area = top_height * width
      # Re-process current bar after popping
      rectangle_loop([current | tail], rest, max(max_area, area))

    # ✅ Step 5: Otherwise push current bar
    _ ->
      rectangle_loop(tail, [current | stack], max_area)
  end
end

📌 Step 4: Popping and Area Calculation

When the current bar is shorter than the top of the stack, we:

    Pop the taller bar (it ends here).

    Compute the rectangle it could have formed.

    Width is based on how far back it extends.

# stack before popping
stack = [{6, 3}, {5, 2}]

# current = {2, 4} → shorter than 6 → pop
popped = {6, 3}

# rest = [{5, 2}] → new top
# width = 4 - 2 - 1 = 1
# area = 6 * 1 = 6

This process continues until the current height is not less than the new top of the stack.
📌 Step 5: Push When Safe

If the current bar is taller or equal to the bar at the top of the stack, we push it:

rectangle_loop(tail, [current | stack], max_area)

This preserves the increasing height order in the stack.
📌 Final Flush (Sentinel)

At the end, the 0 forces all remaining bars to be popped, ensuring all rectangles are considered.