1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#!/usr/bin/env raku
#
# Perl Weekly Challenge - 079
#
# Task #2: Trapped Rain Water
#
# https://perlweeklychallenge.org/blog/perl-weekly-challenge-079
#
use Test;
subset PositiveInt of Int where * >= 0;
is trapped-rain-water(0, 1, 2, 3, 4, 5),
0, "testing: 0, 1, 2, 3, 4, 5";
is trapped-rain-water(3, 1, 3, 1, 1, 5),
6, "testing: 3, 1, 3, 1, 1, 5";
is trapped-rain-water(2, 1, 4, 1, 2, 5),
6, "testing: 2, 1, 4, 1, 2, 5";
is trapped-rain-water(0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1),
6, "testing: 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1";
done-testing;
#
#
# SUBROUTINES
sub trapped-rain-water(*@array where .all ~~ PositiveInt) {
my @a = ();
my $p = 0;
my $trw = 0;
for @array -> $n {
if $p == 0 || $p >= $n {
$p = $n if @a == 0 || ($p == 0 && $n > $p);
@a.push: $n;
}
else {
@a.push: $n;
$trw += fetch-trapped-water(@a);
@a = $n;
$p = $n if $p < $n;
}
}
# are there any left over to be processed?
if @a.elems > 1 {
$trw += fetch-trapped-water(@a);
}
return $trw;
}
sub fetch-trapped-water(*@array where .all ~~ PositiveInt) {
# remove any smaller tower from the start
repeat {
if @array[0] == 0 {
@array.shift;
}
} until @array[0] > 0;
# remove any smaller tower from the end
repeat {
if @array[*-1] < @array[*-2] {
@array.pop;
}
}
until @array[*-1] > @array[*-2];
my $max = (@array[0], @array[*-1]).min * (@array.elems - 2);
$max -= @array[$_] for 1..@array.elems - 2;
return $max;
}
|