aboutsummaryrefslogtreecommitdiff
path: root/challenge-073/colin-crain/perl/ch-2.pl
blob: 20e2066a771a6cebcb388e23842eecf51165a4cd (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
#! /opt/local/bin/perl
#
#       smallest_smaller_neighbor.pl
#
#         TASK #2 › Smallest (Smaller) Neighbour
#         Submitted by: Mohammad S Anwar
#         You are given an array of integers @A.
# 
#         Write a script to create an array that represents the
#         smallest element to the left of each corresponding
#         index. If none found then use 0.
# 
#         Example 1
#         Input: @A = (7, 8, 3, 12, 10)
#         Output: (0, 7, 0, 3, 3)
# 
#         For index 0, the smallest number to the left of $A[0]      
#             is none, so we put 0.
#         For index 1, the smallest number to the left of $A[1] 
#             in (7), is 7 so we put 7.
#         For index 2, the smallest number to the left of $A[2] 
#             in (7, 8) is none, so we put 0.
#         For index 3, the smallest number to the left of $A[3] 
#             in (7, 8, 3) is 3, so we put 3.
#         For index 4, the smallest number to the left of $A[4] 
#             is (7, 8, 3, 12) is 3, so we put 3 again.
# 
#         Example 2
#         Input: @A = (4, 6, 5)
#         Output: (0, 4, 4)
# 
#         For index 0, the smallest number to the left of $A[0] 
#             is none, so we put 0.
#         For index 1, the smallest number to the left of $A[1] 
#             in (4) is 4, so we put 4.
#         For index 2, the smallest number to the left of $A[2] 
#             in (4, 6) is 4, so we put 4 again.
# 
#         method:
#         smallest neighbor is a confusing title, as we are not
#         looking for the smallest element to the left of a
#         given index, but rather the smallest element to the
#         left of the index that is smaller than that element.
#         Or stated another way, the minimum item of the slice
#         A[0..$i-1] that is less than A[$i]. When we put it
#         like that the challenge really resembles the
#         previous, only the size of the window is dynamic and
#         there is some additional comparison going on. But the
#         process is very similar: iterate acrosss the field,
#         selecting a slice for each index, and determine the
#         minimum value within that slice. Instead of just
#         taking the minimum value, though, in the case we can
#         add some additional processing in the function
#         called.
# 
#         As there are never any elements to the left of index
#         0, the first digit will always be 0 and hence can be
#         inserted from the get-go. After that, starting at
#         index 1, the slice from 0 to the current index is
#         passed to our smallest_neighbor function, where the
#         indexed value immediately popped off the end. The
#         minimum of the remaining slice is found, and if that
#         value is less than the index value it is returned,
#         else 0. There is no need to make more than one pass
#         over the list, as the minimum will be the minimum no
#         matter its value.
# 
#         As 0 is a real value that is right in the middle of
#         the potential range (as negative values are not
#         disallowed), using it to label a target miss could be
#         a bit confusing. With that in mind i have taken the
#         liberty to substitute the null set sign '∅' instead,
#         which looks a lot like '0' in my preferred font, but
#         isn't, as it makes understanding what's happening
#         just a little bit easier.
# 
#       2020 colin crain
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##



use warnings;
use strict;
use feature ":5.26";

## ## ## ## ## MAIN:

my @input = @ARGV;
@input = (7, 8, -3, 12, -10);
my @output = ('∅');

for (1..@input-1) {
    my @slice = @input[0..$_];
    my $smallest = smallest_neighbor( @slice );
    push @output, $smallest;
}

say "Input:  @input";
say "Output: ", join ', ', @output;

## ## ## ## ## SUBS:

sub smallest_neighbor {
## find the minimum value to the left and return it if 
## min < given value, else 0
    my $value = pop @_;
    my $min = "inf";
    $_ < $min and $min = $_ for @_;
    $min < $value ? $min : '∅';
}