aboutsummaryrefslogtreecommitdiff
path: root/challenge-163/colin-crain/perl/ch-2.pl
blob: 038e97f6a4b7461cd595b5859aca2368c3980326 (plain)
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();