# Water collected between towers

Water collected between towers
You are encouraged to solve this task according to the task description, using any language you may know.

In a two-dimensional world, we begin with any bar-chart (or row of close-packed 'towers', each of unit width), and then it rains, completely filling all convex enclosures in the chart with water.

```9               ██           9               ██
8               ██           8               ██
7     ██        ██           7     ██░░░░░░░░██
6     ██  ██    ██           6     ██░░██░░░░██
5 ██  ██  ██  ████           5 ██░░██░░██░░████
4 ██  ██  ████████           4 ██░░██░░████████
3 ██████  ████████           3 ██████░░████████
2 ████████████████  ██       2 ████████████████░░██
1 ████████████████████       1 ████████████████████```

In the example above, a bar chart representing the values [5, 3, 7, 2, 6, 4, 5, 9, 1, 2] has filled, collecting 14 units of water.

Write a function, in your language, from a given array of heights, to the number of water units that can be held in this way, by a corresponding bar chart.

Calculate the number of water units that could be collected by bar charts representing each of the following seven series:

```   [[1, 5, 3, 7, 2],
[5, 3, 7, 2, 6, 4, 5, 9, 1, 2],
[2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1],
[5, 5, 5, 5],
[5, 6, 7, 8],
[8, 7, 7, 6],
[6, 7, 10, 7, 6]]```

See, also:

## AppleScript

Translation of: JavaScript

<lang AppleScript>-- waterCollected :: [Int] -> Int on waterCollected(xs)

```   set leftWalls to scanl1(my max, xs)
set rightWalls to scanr1(my max, xs)

set waterLevels to zipWith(my min, leftWalls, rightWalls)

-- positive :: Num a => a -> Bool
script positive
on lambda(x)
x > 0
end lambda
end script

-- minus :: Num a => a -> a -> a
script minus
on lambda(a, b)
a - b
end lambda
end script

sum(filter(positive, zipWith(minus, waterLevels, xs)))
```

end waterCollected

-- TEST ------------------------------------------------------------------ on run

```   map(waterCollected, ¬
[[1, 5, 3, 7, 2], ¬
[5, 3, 7, 2, 6, 4, 5, 9, 1, 2], ¬
[2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1], ¬
[5, 5, 5, 5], ¬
[5, 6, 7, 8], ¬
[8, 7, 7, 6], ¬
[6, 7, 10, 7, 6]])

--> {2, 14, 35, 0, 0, 0, 0}
```

end run

-- GENERIC FUNCTIONS ------------------------------------------------------

-- scanl1 :: (a -> a -> a) -> [a] -> [a] on scanl1(f, xs)

```   if length of xs > 0 then
scanl(f, item 1 of xs, items 2 thru -1 of xs)
else
{}
end if
```

end scanl1

-- scanr1 :: (a -> a -> a) -> [a] -> [a] on scanr1(f, xs)

```   if length of xs > 0 then
scanr(f, item -1 of xs, items 1 thru -2 of xs)
else
{}
end if
```

end scanr1

-- scanl :: (b -> a -> b) -> b -> [a] -> [b] on scanl(f, startValue, xs)

```   tell mReturn(f)
set v to startValue
set lng to length of xs
set lst to {startValue}
repeat with i from 1 to lng
set v to lambda(v, item i of xs, i, xs)
set end of lst to v
end repeat
return lst
end tell
```

end scanl

-- scanr :: (b -> a -> b) -> b -> [a] -> [b] on scanr(f, startValue, xs)

```   tell mReturn(f)
set v to startValue
set lng to length of xs
set lst to {startValue}
repeat with i from lng to 1 by -1
set v to lambda(v, item i of xs, i, xs)
set end of lst to v
end repeat
return reverse of lst
end tell
```

end scanr

-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] on zipWith(f, xs, ys)

```   set nx to length of xs
set ny to length of ys
if nx < 1 or ny < 1 then
{}
else
set lng to cond(nx < ny, nx, ny)
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, item i of ys)
end repeat
return lst
end tell
end if
```

end zipWith

-- map :: (a -> b) -> [a] -> [b] on map(f, xs)

```   tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
end repeat
return lst
end tell
```

end map

-- filter :: (a -> Bool) -> [a] -> [a] on filter(f, xs)

```   tell mReturn(f)
set lst to {}
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if lambda(v, i, xs) then set end of lst to v
end repeat
return lst
end tell
```

end filter

-- sum :: Num a => [a] -> a on sum(xs)

```   script add
on lambda(a, b)
a + b
end lambda
end script

```

end sum

-- foldl :: (a -> b -> a) -> a -> [b] -> a on foldl(f, startValue, xs)

```   tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to lambda(v, item i of xs, i, xs)
end repeat
return v
end tell
```

end foldl

-- Lift 2nd class handler function into 1st class script wrapper -- mReturn :: Handler -> Script on mReturn(f)

```   if class of f is script then
f
else
script
property lambda : f
end script
end if
```

end mReturn

-- init :: [a] -> [a] on init(xs)

```   if length of xs > 1 then
items 1 thru -2 of xs
else
{}
end if
```

end init

-- tail :: [a] -> [a] on tail(xs)

```   if length of xs > 1 then
items 2 thru -1 of xs
else
{}
end if
```

end tail

-- max :: Ord a => a -> a -> a on max(x, y)

```   if x > y then
x
else
y
end if
```

end max

-- min :: Ord a => a -> a -> a on min(x, y)

```   if y < x then
y
else
x
end if
```

end min

-- cond :: Bool -> a -> a -> a on cond(bool, f, g)

```   if bool then
f
else
g
end if
```

end cond</lang>

Output:

<lang AppleScript>{2, 14, 35, 0, 0, 0, 0}</lang>

## AWK

<lang AWK>

1. syntax: GAWK -f WATER_COLLECTED_BETWEEN_TOWERS.AWK [-v debug={0|1}]

BEGIN {

```   wcbt("1,5,3,7,2")
wcbt("5,3,7,2,6,4,5,9,1,2")
wcbt("2,6,3,5,2,8,1,4,2,2,5,3,5,7,4,1")
wcbt("5,5,5,5")
wcbt("5,6,7,8")
wcbt("8,7,7,6")
wcbt("6,7,10,7,6")
exit(0)
```

} function wcbt(str, ans,hl,hr,i,n,tower) {

```   n = split(str,tower,",")
for (i=n; i>=0; i--) { # scan right to left
hr[i] = max(tower[i],(i<n)?hr[i+1]:0)
}
for (i=0; i<=n; i++) { # scan left to right
hl[i] = max(tower[i],(i!=0)?hl[i-1]:0)
ans += min(hl[i],hr[i]) - tower[i]
}
printf("%4d : %s\n",ans,str)
if (debug == 1) {
for (i=1; i<=n; i++) { printf("%-4s",tower[i]) } ; print("tower")
for (i=1; i<=n; i++) { printf("%-4s",hl[i]) } ; print("l-r")
for (i=1; i<=n; i++) { printf("%-4s",hr[i]) } ; print("r-l")
for (i=1; i<=n; i++) { printf("%-4s",min(hl[i],hr[i])) } ; print("min")
for (i=1; i<=n; i++) { printf("%-4s",min(hl[i],hr[i])-tower[i]) } ; print("sum\n")
}
```

} function max(x,y) { return((x > y) ? x : y) } function min(x,y) { return((x < y) ? x : y) } </lang>

Output:
```   2 : 1,5,3,7,2
14 : 5,3,7,2,6,4,5,9,1,2
35 : 2,6,3,5,2,8,1,4,2,2,5,3,5,7,4,1
0 : 5,5,5,5
0 : 5,6,7,8
0 : 8,7,7,6
0 : 6,7,10,7,6
```

## Go

<lang go> package main

import "fmt"

func maxl(hm []int ) []int{ res := make([]int,len(hm)) max := 1 for i := 0; i < len(hm);i++{ if(hm[i] > max){ max = hm[i] } res[i] = max; } return res } func maxr(hm []int ) []int{ res := make([]int,len(hm)) max := 1 for i := len(hm) - 1 ; i >= 0;i--{ if(hm[i] > max){ max = hm[i] } res[i] = max; } return res } func min(a,b []int) []int { res := make([]int,len(a)) for i := 0; i < len(a);i++{ if a[i] >= b[i]{ res[i] = b[i] }else { res[i] = a[i] } } return res } func diff(hm, min []int) []int { res := make([]int,len(hm)) for i := 0; i < len(hm);i++{ if min[i] > hm[i]{ res[i] = min[i] - hm[i] } } return res } func sum(a []int) int { res := 0 for i := 0; i < len(a);i++{ res += a[i] } return res }

func waterCollected(hm []int) int { maxr := maxr(hm) maxl := maxl(hm) min := min(maxr,maxl) diff := diff(hm,min) sum := sum(diff) return sum }

func main() { fmt.Println(waterCollected([]int{1, 5, 3, 7, 2})) fmt.Println(waterCollected([]int{5, 3, 7, 2, 6, 4, 5, 9, 1, 2})) fmt.Println(waterCollected([]int{2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1})) fmt.Println(waterCollected([]int{5, 5, 5, 5})) fmt.Println(waterCollected([]int{5, 6, 7, 8})) fmt.Println(waterCollected([]int{8, 7, 7, 6})) fmt.Println(waterCollected([]int{6, 7, 10, 7, 6})) }</lang>

Output:
```2
14
35
0
0
0
0
```

Following the approach of cdk's Haskell solution at Stack Overflow:

<lang haskell>waterCollected :: [Int] -> Int waterCollected xs =

``` sum \$ -- Sum of water depths over each of:
filter (> 0) \$ -- the columns that are covered by some water.
zipWith
(-) -- Where coverages are differences between
(zipWith
min -- water levels,   (lower in each case of:
(scanl1 max xs) -- highest wall to left, and
(scanr1 max xs) -- highest wall to right)
)
xs -- and column tops.
```

main :: IO () main =

``` mapM_
(print . waterCollected)
[ [1, 5, 3, 7, 2]
, [5, 3, 7, 2, 6, 4, 5, 9, 1, 2]
, [2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1]
, [5, 5, 5, 5]
, [5, 6, 7, 8]
, [8, 7, 7, 6]
, [6, 7, 10, 7, 6]
]</lang>
```
Output:
```2
14
35
0
0
0
0```

## JavaScript

### ES5

<lang JavaScript>(function () {

```   'use strict';
```
```   // waterCollected :: [Int] -> Int
var waterCollected = function (xs) {
return sum(                   // water above each bar
zipWith(function (a, b) {
return a - b;     // difference between water level and bar
},
zipWith(min,          // lower of two flanking walls
scanl1(max, xs),  // highest walls to left
scanr1(max, xs)   // highest walls to right
),
xs                    // tops of bars
)
.filter(function (x) {
return x > 0;         // only bars with water above them
})
);
};
```
```   // GENERIC FUNCTIONS ----------------------------------------
```
```   // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
var zipWith = function (f, xs, ys) {
var ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map(function (x, i) {
return f(x, ys[i]);
});
};
```
```   // scanl1 is a variant of scanl that has no starting value argument
// scanl1 :: (a -> a -> a) -> [a] -> [a]
var scanl1 = function (f, xs) {
return xs.length > 0 ? scanl(f, xs[0], xs.slice(1)) : [];
};
```
```   // scanr1 is a variant of scanr that has no starting value argument
// scanr1 :: (a -> a -> a) -> [a] -> [a]
var scanr1 = function (f, xs) {
return xs.length > 0 ? scanr(f, xs.slice(-1)[0], xs.slice(0, -1)) : [];
};
```
```   // scanl :: (b -> a -> b) -> b -> [a] -> [b]
var scanl = function (f, startValue, xs) {
var lst = [startValue];
return xs.reduce(function (a, x) {
var v = f(a, x);
return lst.push(v), v;
}, startValue), lst;
};
```
```   // scanr :: (b -> a -> b) -> b -> [a] -> [b]
var scanr = function (f, startValue, xs) {
var lst = [startValue];
return xs.reduceRight(function (a, x) {
var v = f(a, x);
return lst.push(v), v;
}, startValue), lst.reverse();
};
```
```   // sum :: (Num a) => [a] -> a
var sum = function (xs) {
return xs.reduce(function (a, x) {
return a + x;
}, 0);
};
```
```   // max :: Ord a => a -> a -> a
var max = function (a, b) {
return a > b ? a : b;
};
```
```   // min :: Ord a => a -> a -> a
var min = function (a, b) {
return b < a ? b : a;
};
```
```   // TEST ---------------------------------------------------
return [
[1, 5, 3, 7, 2],
[5, 3, 7, 2, 6, 4, 5, 9, 1, 2],
[2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1],
[5, 5, 5, 5],
[5, 6, 7, 8],
[8, 7, 7, 6],
[6, 7, 10, 7, 6]
].map(waterCollected);
```
```   //--> [2, 14, 35, 0, 0, 0, 0]
```

})();</lang>

Output:

<lang JavaScript>[2, 14, 35, 0, 0, 0, 0]</lang>

### ES6

<lang JavaScript>(() => {

```   'use strict';

// waterCollected :: [Int] -> Int
const waterCollected = xs => {
const maxToRight = scanr1(max, xs),
maxToLeft = scanl1(max, xs),
levels = zipWith(min, maxToLeft, maxToRight);
```
```       return sum(zipWith(difference, levels, xs)
.filter(x => x > 0));
};
```

```   // GENERIC FUNCTIONS ----------------------------------------
```
```   // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
const ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map((x, i) => f(x, ys[i]));
}
```
```   // scanl1 is a variant of scanl that has no starting value argument
// scanl1 :: (a -> a -> a) -> [a] -> [a]
const scanl1 = (f, xs) =>
xs.length > 0 ? scanl(f, xs[0], xs.slice(1)) : [];
```
```   // scanr1 is a variant of scanr that has no starting value argument
// scanr1 :: (a -> a -> a) -> [a] -> [a]
const scanr1 = (f, xs) =>
xs.length > 0 ? scanr(f, xs.slice(-1)[0], xs.slice(0, -1)) : [];
```
```   // scanl :: (b -> a -> b) -> b -> [a] -> [b]
const scanl = (f, startValue, xs) => {
const lst = [startValue];
return (
xs.reduce((a, x) => {
const v = f(a, x);
return (lst.push(v), v);
}, startValue),
lst
);
};
```
```   // scanr :: (b -> a -> b) -> b -> [a] -> [b]
const scanr = (f, startValue, xs) => {
const lst = [startValue];
return (
xs.reduceRight((a, x) => {
const v = f(a, x);
return (lst.push(v), v);
}, startValue),
lst.reverse()
);
};
```
```   // difference :: (Num a) => a -> a -> a
const difference = (a, b) => a - b;
```
```   // sum :: (Num a) => [a] -> a
const sum = xs => xs.reduce((a, x) => a + x, 0);
```
```   // max :: Ord a => a -> a -> a
const max = (a, b) => a > b ? a : b;
```
```   // min :: Ord a => a -> a -> a
const min = (a, b) => b < a ? b : a;
```

```   // TEST ---------------------------------------------------
return [
[1, 5, 3, 7, 2],
[5, 3, 7, 2, 6, 4, 5, 9, 1, 2],
[2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1],
[5, 5, 5, 5],
[5, 6, 7, 8],
[8, 7, 7, 6],
[6, 7, 10, 7, 6]
].map(waterCollected);
```
```   //--> [2, 14, 35, 0, 0, 0, 0]
```

})();</lang>

Output:

<lang JavaScript>[2, 14, 35, 0, 0, 0, 0]</lang>

## Perl

<lang perl>use Modern::Perl; use List::Util qw{ min max sum };

sub water_collected {

```   my @t = map { { TOWER => \$_, LEFT => 0, RIGHT => 0, LEVEL => 0 } } @_;
```
```   my ( \$l, \$r ) = ( 0, 0 );
\$_->{LEFT}  = ( \$l = max( \$l, \$_->{TOWER} ) ) for @t;
\$_->{RIGHT} = ( \$r = max( \$r, \$_->{TOWER} ) ) for reverse @t;
\$_->{LEVEL} = min( \$_->{LEFT}, \$_->{RIGHT} )  for @t;
```
```   return sum map { \$_->{LEVEL} > 0 ? \$_->{LEVEL} - \$_->{TOWER} : 0 } @t;
```

}

say join ' ', map { water_collected( @{\$_} ) } (

```   [ 1, 5,  3, 7, 2 ],
[ 5, 3,  7, 2, 6, 4, 5, 9, 1, 2 ],
[ 2, 6,  3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1 ],
[ 5, 5,  5, 5 ],
[ 5, 6,  7, 8 ],
[ 8, 7,  7, 6 ],
[ 6, 7, 10, 7, 6 ],
```

);</lang>

Output:
`2 14 35 0 0 0 0`

## Perl 6

<lang perl6>sub max_l ( @a ) { [\max] @a } sub max_r ( @a ) { ([\max] @a.reverse).reverse }

sub water_collected ( @towers ) {

```   return 0 if @towers <= 2;
```
```   my @levels = max_l(@towers) »min« max_r(@towers);
```
```   return ( @levels »-« @towers ).grep( * > 0 ).sum;
```

}

say map &water_collected,

```   [ 1, 5,  3, 7, 2 ],
[ 5, 3,  7, 2, 6, 4, 5, 9, 1, 2 ],
[ 2, 6,  3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1 ],
[ 5, 5,  5, 5 ],
[ 5, 6,  7, 8 ],
[ 8, 7,  7, 6 ],
[ 6, 7, 10, 7, 6 ],
```
</lang>
Output:
`(2 14 35 0 0 0 0)`

## REXX

### version 1

<lang rexx>/* REXX */ Call bars '1 5 3 7 2' Call bars '5 3 7 2 6 4 5 9 1 2' Call bars '2 6 3 5 2 8 1 4 2 2 5 3 5 7 4 1' Call bars '5 5 5 5' Call bars '5 6 7 8' Call bars '8 7 7 6' Call bars '6 7 10 7 6' Exit bars: Parse Arg bars bar.0=words(bars) high=0 box.=' ' Do i=1 To words(bars)

``` bar.i=word(bars,i)
high=max(high,bar.i)
Do j=1 To bar.i
box.i.j='x'
End
End
```

m=1 w=0 Do Forever

``` Do i=m+1 To bar.0
If bar.i>bar.m Then
Leave
End
If i>bar.0 Then Leave
n=i
Do i=m+1 To n-1
w=w+bar.m-bar.i
Do j=bar.i+1 To bar.m
box.i.j='*'
End
End
m=n
End
```

m=bar.0 Do Forever

``` Do i=bar.0 To 1 By -1
If bar.i>bar.m Then
Leave
End
If i<1 Then Leave
n=i
Do i=m-1 To n+1 By -1
w=w+bar.m-bar.i
Do j=bar.i+1 To bar.m
box.i.j='*'
End
End
m=n
End
```

Say bars '->' w Call show Return show: Do j=high To 1 By -1

``` ol=
Do i=1 To bar.0
ol=ol box.i.j
End
Say ol
End
```

Return</lang>

Output:
```1 5 3 7 2 -> 2
x
x
x * x
x * x
x x x
x x x x
x x x x x
5 3 7 2 6 4 5 9 1 2 -> 14
x
x
x * * * * x
x * x * * x
x * x * x * x x
x * x * x x x x
x x x * x x x x
x x x x x x x x * x
x x x x x x x x x x
2 6 3 5 2 8 1 4 2 2 5 3 5 7 4 1 -> 35
x
x * * * * * * * x
x * * * x * * * * * * * x
x * x * x * * * * x * x x
x * x * x * x * * x * x x x
x x x * x * x * * x x x x x
x x x x x x * x x x x x x x x
x x x x x x x x x x x x x x x x
5 5 5 5 -> 0
x x x x
x x x x
x x x x
x x x x
x x x x
5 6 7 8 -> 0
x
x x
x x x
x x x x
x x x x
x x x x
x x x x
x x x x
8 7 7 6 -> 0
x
x x x
x x x x
x x x x
x x x x
x x x x
x x x x
x x x x
6 7 10 7 6 -> 0
x
x
x
x x x
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x```

### version 2

<lang rexx>/*REXX program calculates and displays the amount of rainwater collected between towers.*/ call tower 1 5 3 7 2 call tower 5 3 7 2 6 4 5 9 1 2 call tower 2 6 3 5 2 8 1 4 2 2 5 3 5 7 4 1 call tower 5 5 5 5 call tower 5 6 7 8 call tower 8 7 7 6 call tower 6 7 10 7 6 exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ tower: procedure; arg y; #=words(y); t.=0; L.=0 /*the T. array holds the tower heights.*/

```           do j=1  for #;   t.j=word(y, j)      /*construct the towers,                */
_=j-1;           L.j=max(t._, L._)   /*    "      "  left-most tallest tower*/
end   /*j*/
R.=0
do b=#  by -1  for #;  _=b+1;  R.b=max(t._, R._)  /*right-most tallest tower*/
end   /*b*/
w.=0                                                       /*rainwater collected.*/
do f=1  for #;  if t.f>=L.f | t.f>=R.f  then iterate  /*rain between towers?*/
w.f=min(L.f, R.f) - t.f;      w.00=w.00+w.f           /*rainwater collected.*/
end   /*f*/
say right(w.00,9) 'units of rainwater collected for: '  y  /*display water units.*/
return</lang>
```

output

```        2 units of rainwater collected for:  1 5 3 7 2
14 units of rainwater collected for:  5 3 7 2 6 4 5 9 1 2
35 units of rainwater collected for:  2 6 3 5 2 8 1 4 2 2 5 3 5 7 4 1
0 units of rainwater collected for:  5 5 5 5
0 units of rainwater collected for:  5 6 7 8
0 units of rainwater collected for:  8 7 7 6
0 units of rainwater collected for:  6 7 10 7 6
```

### version 3

This REXX version shows a scale and a representation of the towers and water collected. <lang rexx>/*REXX program calculates and displays the amount of rainwater collected between towers.*/ call tower 1 5 3 7 2 call tower 5 3 7 2 6 4 5 9 1 2 call tower 2 6 3 5 2 8 1 4 2 2 5 3 5 7 4 1 call tower 5 5 5 5 call tower 5 6 7 8 call tower 8 7 7 6 call tower 6 7 10 7 6 exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ tower: procedure; arg y; #=words(y); t.=0; L.=0 /*the T. array holds the tower heights.*/

```           do j=1  for #;  t.j=word(y,j); _=j-1 /*construct the towers;  max height.   */
L.j=max(t._, L._); t.0=max(t.0, t.j) /*left-most tallest tower; build scale.*/
end   /*j*/
R.=0
do b=#  by -1  for #;  _=b+1;  R.b=max(t._, R._)  /*right-most tallest tower*/
end   /*b*/
w.=0                                                       /*rainwater collected.*/
do f=1  for #;  if t.f>=L.f | t.f>=R.f  then iterate  /*rain between towers?*/
w.f=min(L.f, R.f) - t.f;      w.00=w.00+w.f           /*rainwater collected.*/
end   /*f*/
if w.00==0  then w.00='no'                /*pretty up wording for "no rainwater".*/
p.=                                       /*P.  stores plot versions of towers.  */
do c=0  to #                         /*construct the plot+scale for display.*/
do h=1  for t.c+w.c;     glyph='█' /*maybe show a floor of some tower(s). */
if h>t.c then glyph='~'            /*  "     "  rainwater between towers. */
if c==0  then p.h=overlay(right(h, 9), p.h,  1  )  /*place the tower scale*/
else p.h=overlay(glyph      , p.h, 10+c)  /*build the tower.     */
end   /*h*/
end     /*c*/
p.1=overlay(w.00  'units of rainwater collected', p.1, 15+#)
do z=t.0  by -1  to 0;     say p.z   /*display the various floors of towers.*/
end     /*z*/
return</lang>
```

output

```        7    █
6    █
5  █~█
4  █~█
3  ███
2  ████
1 █████    2 units of rainwater collected

9        █
8        █
7   █~~~~█
6   █~█~~█
5 █~█~█~██
4 █~█~████
3 ███~████
2 ████████~█
1 ██████████    14 units of rainwater collected

8      █
7      █~~~~~~~█
6  █~~~█~~~~~~~█
5  █~█~█~~~~█~██
4  █~█~█~█~~█~███
3  ███~█~█~~█████
2 ██████~████████
1 ████████████████    35 units of rainwater collected

5 ████
4 ████
3 ████
2 ████
1 ████    no units of rainwater collected

8    █
7   ██
6  ███
5 ████
4 ████
3 ████
2 ████
1 ████    no units of rainwater collected

8 █
7 ███
6 ████
5 ████
4 ████
3 ████
2 ████
1 ████    no units of rainwater collected

10   █
9   █
8   █
7  ███
6 █████
5 █████
4 █████
3 █████
2 █████
1 █████    no units of rainwater collected
```

## zkl

<lang zkl>fcn waterCollected(walls){

```    // compile max wall heights from left to right and right to left
// then each pair is left/right wall of that cell.
// Then the min of each wall pair == water height for that cell
scanl(walls,(0).max)     // scan to right, f is max(0,a,b)
.zipWith((0).MAX.min,     // f is MAX.min(a,b) == min(a,b)
scanl(walls.reverse(),(0).max).reverse()) // right to left
// now subtract the wall height from the water level and add 'em up
.zipWith('-,walls).filter('>(0)).sum(0);
```

} fcn scanl(xs,f,i=0){ // aka reduce but save list of results

```  xs.reduce('wrap(s,x,a){ s=f(s,x); a.append(s); s },i,ss:=List());
ss
```

} // scanl((1,5,3,7,2),max,0) --> (1,5,5,7,7)</lang> <lang zkl>T( T(1, 5, 3, 7, 2), T(5, 3, 7, 2, 6, 4, 5, 9, 1, 2),

```  T(2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1),
T(5, 5, 5, 5), T(5, 6, 7, 8),T(8, 7, 7, 6),
T(6, 7, 10, 7, 6) )
```

.pump(List, waterCollected).println();</lang>

Output:
```L(2,14,35,0,0,0,0)
```