/
ch-2.pl
executable file
·177 lines (148 loc) · 5.35 KB
/
ch-2.pl
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env -S perl -CSDA
=pod
--------------------------------------------------------------------------------------------------------------
COLOPHON:
This is a 110-character-wide Unicode UTF-8 Perl-source-code text file with hard Unix line breaks ("\x0A").
¡Hablo Español! Говорю Русский. Björt skjöldur. ॐ नमो भगवते वासुदेवाय. 看的星星,知道你是爱。麦藁雪、富士川町、山梨県。
--------------------------------------------------------------------------------------------------------------
TITLE BLOCK:
Solutions in Perl for The Weekly Challenge 248-2.
Written by Robbie Hatley on Sat Dec 23, 2023.
--------------------------------------------------------------------------------------------------------------
PROBLEM DESCRIPTION:
Task 248-2: Submatrix Sum
Submitted by: Jorg Sommrey
Rephrased by: Robbie Hatley
Given a NxM matrix A of real numbers, write a script to construct
an (N-1)x(M-1) matrix B having elements that are the sum over the
2x2 submatrices of A,
b[i,k] = a[i,k] + a[i,k+1] + a[i+1,k] + a[i+1,k+1]
Example 1:
Input: [1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
Output: [14, 18, 22],
[30, 34, 38]
Example 2:
Input: [1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
Output: [2, 1, 0],
[1, 2, 1],
[0, 1, 2]
--------------------------------------------------------------------------------------------------------------
PROBLEM NOTES:
The solution to task 248-2 is similar to that of 248-1, because we need only make an array of matrices
of numbers, then iterate over each mxn matrix with nested 3-part loops to make the smaller m-1xn-1 matrix
of the sums of the 2x2 subarrays of the original matrix.
--------------------------------------------------------------------------------------------------------------
IO NOTES:
Input is via either built-in variables or via @ARGV. If using @ARGV, provide one argument which must be a
single-quoted array of arrays of real numbers, in proper Perl syntax, like so:
./ch-2.pl "([[-42.1,17.3,-0.13],[7,14.4,-3.2],[-1.1,-2.2,-3.3]],[[-1,2],[-3,4],[-5,6]])"
Output is to STDOUT and will be each input matrix followed by the corresponding output matrix.
=cut
# ------------------------------------------------------------------------------------------------------------
# PRAGMAS AND MODULES USED:
use v5.38;
use strict;
use warnings;
use utf8;
use warnings FATAL => 'utf8';
use Sys::Binmode;
use Time::HiRes 'time';
use Scalar::Util 'looks_like_number';
# ------------------------------------------------------------------------------------------------------------
# GLOBAL VARIABLES:
our $db = 0 ; # Debug? Set to 1 for yes, 0 for no.
our $t0 ; # Starting time.
# ------------------------------------------------------------------------------------------------------------
# START TIMER:
BEGIN {$t0 = time}
# ------------------------------------------------------------------------------------------------------------
# SUBROUTINES:
# Check for errors:
sub error ($aref) {
'ARRAY' ne ref($aref) and return 'Error: $aref is not a reference to an array.';
my $m = scalar(@$aref);
$db and say "m = $m";
$m < 1 and return 'Error: @$aref is empty.';
for my $row (@$aref) {
'ARRAY' ne ref($row) and return 'Error: @$aref is not an array of arrays.';
}
my $n = scalar(@{$$aref[0]});
$db and say "n = $n";
for my $row (@$aref) {
scalar(@$row != $n) and return 'Error: @$aref is not an mxn matrix.';
}
for my $row (@$aref) {
for my $element (@$row) {
!looks_like_number($element) and return 'Error: @$aref is not a matrix of numbers.';
}
}
return 'ok';
}
# Generate matrix of 2x2 submatrix sums:
sub matrix_of_2x2_submatrix_sums ($aref) {
my @rows;
my $m = scalar(@$aref);
my $n = scalar(@{$$aref[0]});
for ( my $i = 0 ; $i < $m-1 ; ++$i ) {
for ( my $j = 0 ; $j < $n-1 ; ++$j ) {
$rows[$i]->[$j] =
$aref->[$i+0]->[$j+0]
+ $aref->[$i+0]->[$j+1]
+ $aref->[$i+1]->[$j+0]
+ $aref->[$i+1]->[$j+1];
}
}
return @rows;
}
# ------------------------------------------------------------------------------------------------------------
# MAIN BODY OF PROGRAM:
# Inputs:
my @arrays = @ARGV ? eval($ARGV[0]) :
(
# Example 1 Input matrix:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
],
# Expected Output:
# [14, 18, 22],
# [30, 34, 38],
# Example 2 Input matrix:
[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
],
# Expected Output:
# [2, 1, 0],
# [1, 2, 1],
# [0, 1, 2],
);
# Main loop:
for my $aref (@arrays) {
say '';
my $error = error($aref);
$error ne 'ok' and say $error and say 'Moving on to next array.' and next;
my @old_rows = @$aref;
say 'Original matrix:';
for my $old_row (@old_rows) {
say '[', join(', ', @$old_row), ']';
}
my @new_rows = matrix_of_2x2_submatrix_sums($aref);
say 'Matrix of 2x2 submatrix sums:';
for my $new_row (@new_rows) {
say '[', join(', ', @$new_row), ']';
}
}
exit;
# ------------------------------------------------------------------------------------------------------------
# DETERMINE AND PRINT EXECUTION TIME:
END {my $µs = 1000000 * (time - $t0);printf("\nExecution time was %.0fµs.\n", $µs)}
__END__