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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#!/Users/colincrain/perl5/perlbrew/perls/perl-5.32.0/bin/perl
#
# triangular-sum-ting.pl
#
# Summations
# Submitted by: Mohammad S Anwar
# You are given a list of positive numbers, @n.
#
# Write a script to find out the summations as described below.
#
# Example 1
#
# Input: @n = (1, 2, 3, 4, 5)
# Output: 42
#
# 1 2 3 4 5
# 2 5 9 14
# 5 14 28
# 14 42
# 42
#
# The nth Row starts with the second element of the (n-1)th row.
# The following element is sum of all elements except first element
# of previous row. You stop once you have just one element in the
# row.
#
# Example 2
#
# Input: @n = (1, 3, 5, 7, 9)
# Output: 70
#
# 1 3 5 7 9
# 3 8 15 24
# 8 23 47
# 23 70
# 70
# opening commentary:
#
# Behold another piece of unusual operation assemblage,
# systematically reducing a list according to the rules of an
# arcane process. Again I can't immediately see a rationale for
# doing this particular task, but that's no mind.
# method:
#
# Let's break it down. At each iteration, we:
# 1. shift off the first value from the list
# 2. incrementally sum the list from left to right
# 3. at each position, add the running total to a new list
# 4. after filling the last postion, replace the old list with the new
# 5. repeat until there is only once value in the new list
#
# Well when you put it like that, it doesn't seem so bad.
#
# © 2022 colin
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
use warnings;
use strict;
use utf8;
use feature ":5.26";
use feature qw(signatures);
no warnings 'experimental::signatures';
use constant {VERBOSE => 1};
our @stack;
say trisum( @ARGV ) and exit if @ARGV ;
sub trisum (@list) {
my $sum;
my @new;
@stack = [@list];
while (@list > 1) {
@new = ();
$sum = 0;
shift @list;
for (keys @list) {
$sum += $list[$_];
push @new, $sum;
}
push @stack, [@new];
@list = @new;
}
print_stack_and_flush() if VERBOSE;
return shift @new;
}
sub print_stack_and_flush {
my $elements = @stack;
my $max_digits = length $stack[-1]->[0];
my $fmt = ('%' . ($max_digits + 3) . 's') x $elements;
say "\ntrianglular reduction steps:\n";
for my $row (@stack) {
unshift $row->@*, '' while $row->@* < $elements;
say sprintf $fmt, $row->@*;
}
say "sum $stack[-1]->[-1]\n";
@stack = ();
}
use Test::More;
is trisum(1, 2, 3, 4, 5), 42, 'ex-1';
is trisum(1, 3, 5, 7, 9), 70, 'ex-2';
done_testing();
|