Coding questions · Airbnb
Simulate pouring water onto a 1D terrain
This question evaluates understanding of simulation of discrete physical processes, array manipulation, state tracking, and greedy/local-search movement rules, measuring algorithmic design and efficiency competencies.
You are given a 1D terrain represented by an integer array heights, where heights[i] is the height of the column at index i.
Part 1 — Render terrain
Write a function to print an ASCII visualization of the terrain where:
- Each column is drawn using
+characters. - The bottom row (base layer) is always shown.
- Rows are printed from top to bottom.
Example input:
heights = [5,4,3,2,1,3,4,0,3,4]
Example rendering (one possible formatting):
+
++ + +
+++ ++ ++
++++ ++ ++
+++++++ ++
++++++++++ <--- base layer
Part 2 — Pour water and render final state
Implement dumpWater(heights, waterAmount, column) that simulates pouring waterAmount units of water onto the terrain at index column.
Water movement rules (1 unit at a time)
For each unit of water:
- Start at
i = column. - The unit first tries to move left to find the closest position with a strictly lower “effective height” (terrain height + already-settled water) by scanning left while the effective height does not increase.
- More precisely: move left while
eff(left) <= eff(current). - Track the best (lowest) position reached; if any position has
eff < eff(column), settle at the leftmost position among the lowest reached.
- More precisely: move left while
- If no strictly lower position exists on the left, do the symmetric process on the right.
- If neither side has a strictly lower reachable position, the unit settles at
column. - Once settled, that position’s water count increases by 1 (so its effective height increases by 1).
After all water is poured, print the final ASCII visualization using:
+for terrain blocksWfor water blocks (stacked above the terrain)
Example call:
dumpWater([5,4,3,2,1,3,4,0,3,4], waterAmount=8, column=1)
Expected output should match the described final state (formatting may vary as long as block positions are correct).
Function signatures
renderTerrain(heights) -> voiddumpWater(heights, waterAmount, column) -> void(may return the final water distribution and/or print the final rendering)
Constraints (assume)
1 <= len(heights) <= 10^40 <= heights[i] <= 10^50 <= column < len(heights)0 <= waterAmount <= 10^5
Your solution should be correct and reasonably efficient for the above constraints.
Part 1: Render a 1D Terrain as ASCII
You are given a 1D terrain represented by a list of non-negative integers heights, where heights[i] is the number of terrain blocks stacked above column i.
Return an ASCII rendering of the terrain from top to bottom.
Rendering rules:
- Use
'+'for terrain blocks. - Use
'.'for empty space (this makes the output unambiguous for automated testing). - There is always one extra base row at the bottom made entirely of
'+'characters. - The base row is not included in
heights[i]; it is added separately. - All returned rows must have the same length, equal to
len(heights). - If
heightsis empty, return an empty list.
Example:
heights = [1, 0, 2]- Return
["..+", "+.+", "+++"]
Constraints
- 0 <= len(heights) <= 200
- 0 <= heights[i] <= 200
- The total rendered output size will be small enough to fit in memory
Hints
- Build the picture one row at a time, starting from the maximum terrain height down to 1.
- For a given row level
L, columnicontains'+'ifheights[i] >= L; otherwise it contains'.'.
Part 2: Pour Water on a 1D Terrain and Render the Final State
You are given a 1D terrain represented by a list heights, a number of water units waterAmount, and a starting column column.
Simulate pouring water one unit at a time onto the terrain.
Definitions:
effective height(i) = heights[i] + water[i]water[i]is how much water has already settled at columni
For each unit of water:
- Start at
column. - Try to move left by scanning while the next position does not rise:
- While
effective height(i - 1) <= effective height(i), continue moving left. - Among all scanned positions, track the minimum effective height reached.
- If at least one scanned position is strictly lower than the starting effective height, settle at the leftmost position among the lowest ones reached.
- While
- If no strictly lower position exists on the left, do the symmetric process on the right:
- While
effective height(i + 1) <= effective height(i), continue moving right. - If at least one scanned position is strictly lower than the starting effective height, settle at the rightmost position among the lowest ones reached.
- While
- If neither side has a strictly lower reachable position, the water settles at
column. - After settling, that column's water count increases by 1.
After all water is poured, return the final ASCII rendering from top to bottom using:
'+'for terrain blocks'W'for water blocks'.'for empty space- one extra full base row of
'+'at the bottom
This version returns the rendering instead of printing it.
Constraints
- 1 <= len(heights) <= 200
- 0 <= heights[i] <= 100
- 0 <= waterAmount <= 200
- 0 <= column < len(heights)
- The total rendered output size will be small enough to fit in memory
Examples
Example 1
Input: ([2, 1, 2, 1, 2], 1, 2)
Output: ["+W+.+", "+++++", "+++++"]
Explanation: Both sides have a lower reachable column, so the water must prefer the left side first and settle at index 1.
Example 2
Input: ([3, 1, 3], 2, 0)
Output: ["+W+", "+W+", "+++", "+++"]
Explanation: There is no left side, so water falls to the right valley twice, stacking there.
Hints
- Keep a separate
waterarray and always compare columns usingheights[i] + water[i]. - When scanning left or right, stop as soon as the next step would go uphill. While scanning, remember the lowest reachable effective height; on ties, prefer the direction you are scanning toward.