This is my response to the Perl Weekly Challenge #087.
@N
.
Input: @N = (100, 4, 50, 3, 2)
Output: (2, 3, 4)
Example 2
Input: @N = (20, 30, 10, 40, 50)
Output: 0
Example 3
Input: @N = (20, 19, 9, 11, 10)
Output: (9, 10, 11)
#! /usr/bin/env raku
unit sub MAIN (*@N where @N.elems && all(@N) ~~ Int); # [1]
my @sorted = @N.sort.squish; # [2]
my @longest; # [3]
my $longest = 0; # [4]
my @current = @sorted.shift; # [5]
my $current = @current[0]; # [6]
for @sorted -> $num # [7]
{
if $num == $current + 1 # [8]
{
@current.push: $num; # [8a]
$current = $num; # [8b]
}
else # [9]
{
if (@current.elems > $longest) # [9a]
{
@longest = @current; # [9b]
$longest = @longest.elems; # [9c]
}
$current = $num; # [10]
@current = ($num); # [11]
}
}
say @longest.elems > 1 # [12]
?? "({ @longest.join(", ") })" # [12a]
!! "0"; # [12b]
[1] Ensure that the values are integers, and that there is at least one of them.
[2]
Sort the integers, and remove any duplicates with
squish
(that relies on a sorted list; use unique
instead
if the list is unsorted).
[3] The longest list, so far.
[4] The number of elements (numbers really) in the longest list.
[5] The working list, starting with one element.
[6] The value of the highest value in the current list.
[7] Iterate through the list.
[8] If we have the next number (current +1), add it to the list [8a] and record the new number as the highest.
[9] If not (the current number is not one above the previous one), check if the new list is longer than the old one [9a]. If so, save the new list [9b] and length [9c].
[10] We are starting a new sequence here. Record the start value,
[11] and put the value in the list.
[12] Do we have at least two elements? If so, print them [12a]. If not, print zero [12b].
See
docs.raku.org/routine/squish
for more information about squish
.
See
docs.raku.org/routine/unique
for more information about unique
.
Running it on the examples:
$ ./longest-consecutive-sequence 100 4 50 3 2
(2, 3, 4)
$ ./longest-consecutive-sequence 20 30 10 40 50
0
$ ./longest-consecutive-sequence 20 19 9 11 10
(9, 10, 11)
#! /usr/bin/env perl
use strict;
use feature 'say';
use List::Util qw(all uniq);
die "At least 1 value" unless @ARGV;
die "Integers only" unless all { $ ~= /^\-?\d+$/ } @ARGV;
my @sorted = uniq sort { $a <=> $b } @ARGV; # [1]
my @longest;
my $longest = 0;
my @current = shift(@sorted);
my $current = $current[0];
for my $num (@sorted)
{
if ($num == $current + 1)
{
push(@current, $num);
$current = $num;
}
else
{
if (@current > $longest)
{
@longest = @current;
$longest = @longest;
}
$current = $num;
@current = ($num);
}
}
say @longest > 1
? "(" . join(", ", @longest) . ")"
: "0";
[1] Make sure that we sort the values numerically (with <=>
),
and not as texts (as we do not want the third example sorted as
«10 11 19 20 9»).
Running it gives the same result as the Raku version:
$ ./longest-consecutive-sequence-perl 100 4 50 3 2
(2, 3, 4)
$ ./longest-consecutive-sequence-perl 20 30 10 40 50
0
$ ./longest-consecutive-sequence-perl 20 19 9 11 10
(9, 10, 11)
m x n
with 0
and
1
.
1
.
Print 0
if none found.
Input:
[ 0 0 0 1 0 0 ]
[ 1 1 1 0 0 0 ]
[ 0 0 1 0 0 1 ]
[ 1 1 1 1 1 0 ]
[ 1 1 1 1 1 0 ]
Output:
[ 1 1 1 1 1 ]
[ 1 1 1 1 1 ]
Example 2
Input:
[ 1 0 1 0 1 0 ]
[ 0 1 0 1 0 1 ]
[ 1 0 1 0 1 0 ]
[ 0 1 0 1 0 1 ]
Output: 0
Example 3
Input:
[ 0 0 0 1 1 1 ]
[ 1 1 1 1 1 1 ]
[ 0 0 1 0 0 1 ]
[ 0 0 1 1 1 1 ]
[ 0 0 1 1 1 1 ]
Output:
[ 1 1 1 1 ]
[ 1 1 1 1 ]
it follows from the second example that a single «1» does not form a rectangle. It is not clear if two «1»s on a row (or column) form a rectangle, so I have chosen to disregard rectangles with 1 row or column.
The first problem is how to specify the matrices to the program. I have chosen to place them in their own (text) files, like this:
File: example1.txt
[ 0 0 0 1 0 0 ]
[ 1 1 1 0 0 0 ]
[ 0 0 1 0 0 1 ]
[ 1 1 1 1 1 0 ]
[ 1 1 1 1 1 0 ]
Reading a matrix from a file is a repetition of what I did in the second part of Four Corners with Raku, my response to the Perl Weekly Challenge #084. (Except that I have added the brackets this time, as introduced in the second part of A Different Puzzle with Raku and Perl, my response to the Perl Weekly Challenge #086.)
File: largest-rectangle (partial)
#! /usr/bin/env raku
subset BinaryDigit where /^<[01]>$/; # [1]
unit sub MAIN ($rectangle where $rectangle.IO.f && $rectangle.IO.r # [2]
= 'sample1.txt',
:v(:$verbose), :s(:$show), :h($html)); # [3]
my @rectangle =
$rectangle.IO.lines.map( *.words.grep(BinaryDigit) )>>.Array; # [4]
my $rows = @rectangle.elems; # [5]
my $cols = @rectangle[0].elems; # [6]
die "All rows must have the same length"
unless [==] @(@rectangle)>>.elems; # [7]
my $col-blue = "\e[44m"; # [3a]
my $col-green = "\e[42m";
my $col-red = "\e[101m";
my $col-stop = "\e[0m";
if ($html) # [3b]
{
$col-blue = '<span class="text-primary">';
$col-green = '<span class="text-success">';
$col-red = '<span class="text-danger">';
$col-stop = '';
}
[1] We allow 0
and 1
in the matrix,
so we set up a custom type (with code>subset) to make validation easier.
[2] Ensure that we get a filename as parameter.
[3] I'll get back to these later on.
[4] Read the matrix, split it into a list of list, and assign it to a two-dimentional array.
[5] Get the number of rows (for use in loops, later on).
[6] Get the number of columns (ditto), for the top row.
[7] Ensure that all the rows have the same number of columns.
See
docs.raku.org/language/typesystem#index-entry-subset-subset
for more information about subset
.
I have chosen to iterate through all the cells, and generate all the possible rectangles. Note the upper limit, so that we have at elast two rows and columns for the rectangles.
(We'll sort the list of rectangles later on, by size, and pick the first one we
encounter with only 1
s.)
my @partials;
for 0 .. $rows -1 -> $start-row # [8]
{
for 0 .. $cols -1 -> $start-col # [9]
{
if @rectangle[$start-row][$start-col] == 0 # [10]
{
say ": [$start-row,$start-col] skipped (is 0)" if $verbose;
next;
}
for $start-row +1 .. $rows -1 -> $stop-row # [11]
{
for $start-col +1 .. $cols -1 -> $stop-col # [12]
{
@partials.push(partial.new(:$start-row, :$stop-row,
:$start-col, :$stop-col)); # [13]
@partials[*-1].debug-output.say if $verbose; # [14]
}
}
}
}
4 loops inside each other is not very efficient, but it does not really matter as long as the matrices are small. As the examples are. (The short circuit filter in [10] helps somewhat.)
[8] For each row (except the last one).
[9] For each column (excpet the last one).
[10] Skip the cell (with next
) if it is 0
. This is a
quick optimisation, as the rectangles must contain nothing but 1
s.
The rest is harder to check, so we do that later on.
[11] [8] and [9] gave us the start position, and this one gives the end position (row).
[12] End column if the end position.
[13] Generate a «partial» object (explained in the next section) and save it.
[14] Verbose output, if requested. This is done with a method on the object.
The [*-1]
syntax gives the last element in the array, which is the
one we just added (in [13] with push
).
class partial # [15]
{
has $.start-row; # [15a]
has $.start-col; # [15b]
has $.stop-row; # [15c]
has $.stop-col; # [15d]
method size # [16]
{
return (self.stop-row - self.start-row + 1) *
(self.stop-col - self.start-col + 1);
}
method all-one # [17]
{
for self.start-row .. self.stop-row -> $row
{
for self.start-col .. self.stop-col -> $col
{
return False if @rectangle[$row][$col] == 0;
}
}
return True;
}
method debug-output # [18]
{
return ": [{ self.start-row },{ self.start-col } -> \
{ self.stop-row },{ self.stop-col }] -> \
{ self.size } -> { self.all-one }";
}
method show # [19]
{
for self.start-row .. self.stop-row -> $row
{
print "[ ";
for self.start-col .. self.stop-col -> $col
{
print @rectangle[$row][$col] ~ " ";
}
say "]";
}
}
}
[15] The class, with four variables; the upper left corner ([15a] and [15b]), and the lower right corner ([15c] and [16d]) of the rectangle.
[16] A method calculating the size of the rectangle. We need this, as the challenge wanted the largest one.
[17] Does the rectangle contain 1
s only?
[18] Used by Verbose mode only.
[19] Show the rectangle. This is used to print the answer to the challenge.
File: largest-rectangle (partial)
say "" if $verbose;
my @sorted = @partials.sort({ $^b.size <=> $^a.size }); # [20]
for @sorted -> $candidate # [21]
{
$candidate.debug-output.say if $verbose; # [22]
if $candidate.all-one # [23]
{
coloured-matrix($candidate.start-row, $candidate.start-col, # [24]
$candidate.stop-row, $candidate.stop-col) if $show;
say "" if $verbose || $show;
$candidate.show; # [25]
exit; # [25a]
}
}
sub coloured-matrix ($start-row, $start-col, $stop-row, $stop-col) # [27]
{
for ^$rows -> $row
{
print "[ ";
for ^$cols -> $col
{
print $start-row <= $row <= $stop-row &&
$start-col <= $col <= $stop-col
?? ( $col-green ~ @rectangle[$row][$col] ~ $col-stop ~ " " )
!! ( @rectangle[$row][$col] ~ " " );
}
say "]";
}
}
say 0; # [26]
[20] Sort the rectangles, by the size, with the largest first (as we have swapped the placeholders).
[21] Iterate over the (sorted) rectangles.
[22] The same verbose output as in [14], but this time sorted by rectangle size.
[23] The first one we encounter with only 1
s is the answer,
[24] Show the original matrix, with the rectangle highlighted, if requested.
[25] Print the rectangle and exit, as we are done.
[26] No rectangles with only 1
s? Then print 0
.
[27] Print the matrix, with the values inside the spcified rectangle coloured.
Running it on the examples:
$ ./largest-rectangle example1.txt
[ 1 1 1 1 1 ]
[ 1 1 1 1 1 ]
$ ./largest-rectangle example2.txt
0
$ ./largest-rectangle example3.txt
[ 1 1 1 1 ]
[ 1 1 1 1 ]
With «show» enabled, to see where the rectangles come from:
$ ./largest-rectangle -s example1.txt
[ 0 0 0 1 0 0 ]
[ 1 1 1 0 0 0 ]
[ 0 0 1 0 0 1 ]
[ 1 1 1 1 1 0 ]
[ 1 1 1 1 1 0 ]
[ 1 1 1 1 1 ]
[ 1 1 1 1 1 ]
$ ./largest-rectangle -s example2.txt
0
$ ./largest-rectangle -s example3.txt
[ 0 0 0 1 1 1 ]
[ 1 1 1 1 1 1 ]
[ 0 0 1 0 0 1 ]
[ 0 0 1 1 1 1 ]
[ 0 0 1 1 1 1 ]
[ 1 1 1 1 ]
[ 1 1 1 1 ]
With Verbose mode:
$ ./largest-rectangle -v example1.txt
: [0,0] skipped (is 0)
: [0,1] skipped (is 0)
: [0,2] skipped (is 0)
: [0,3 -> 1,4] -> 4 -> False
: [0,3 -> 1,5] -> 6 -> False
: [0,3 -> 2,4] -> 6 -> False
: [0,3 -> 2,5] -> 9 -> False
: [0,3 -> 3,4] -> 8 -> False
: [0,3 -> 3,5] -> 12 -> False
: [0,3 -> 4,4] -> 10 -> False
: [0,3 -> 4,5] -> 15 -> False
…
The first three lines are for the first 3 cells on the top row. They have a
0
, so we can skip creating rectangles starting there (as they
cannot contain only 1
s).
The rest is for the 4th cell (with index 3). The values inside the brackets
are the cooridinates for the upper left and the lower right corner of the
rectangle. The next value is the size (number of cells), and finally we
see if the rectangle contains only 1
s. (None of them does.)
The illustrations shows the 8 different rectanges we got starting at [0,3]:
Cells with 1
are shown as green,
and cells with 0
are shown as red.
The rest of the output:
: [0,4] skipped (is 0)
: [0,5] skipped (is 0)
: [1,0 -> 2,1] -> 4 -> False
: [1,0 -> 2,2] -> 6 -> False
: [1,0 -> 2,3] -> 8 -> False
: [1,0 -> 2,4] -> 10 -> False
: [1,0 -> 2,5] -> 12 -> False
: [1,0 -> 3,1] -> 6 -> False
: [1,0 -> 3,2] -> 9 -> False
: [1,0 -> 3,3] -> 12 -> False
: [1,0 -> 3,4] -> 15 -> False
: [1,0 -> 3,5] -> 18 -> False
: [1,0 -> 4,1] -> 8 -> False
: [1,0 -> 4,2] -> 12 -> False
: [1,0 -> 4,3] -> 16 -> False
: [1,0 -> 4,4] -> 20 -> False
: [1,0 -> 4,5] -> 24 -> False
: [1,1 -> 2,2] -> 4 -> False
: [1,1 -> 2,3] -> 6 -> False
: [1,1 -> 2,4] -> 8 -> False
: [1,1 -> 2,5] -> 10 -> False
: [1,1 -> 3,2] -> 6 -> False
: [1,1 -> 3,3] -> 9 -> False
: [1,1 -> 3,4] -> 12 -> False
: [1,1 -> 3,5] -> 15 -> False
: [1,1 -> 4,2] -> 8 -> False
: [1,1 -> 4,3] -> 12 -> False
: [1,1 -> 4,4] -> 16 -> False
: [1,1 -> 4,5] -> 20 -> False
: [1,2 -> 2,3] -> 4 -> False
: [1,2 -> 2,4] -> 6 -> False
: [1,2 -> 2,5] -> 8 -> False
: [1,2 -> 3,3] -> 6 -> False
: [1,2 -> 3,4] -> 9 -> False
: [1,2 -> 3,5] -> 12 -> False
: [1,2 -> 4,3] -> 8 -> False
: [1,2 -> 4,4] -> 12 -> False
: [1,2 -> 4,5] -> 16 -> False
: [1,3] skipped (is 0)
: [1,4] skipped (is 0)
: [1,5] skipped (is 0)
: [2,0] skipped (is 0)
: [2,1] skipped (is 0)
: [2,2 -> 3,3] -> 4 -> False
: [2,2 -> 3,4] -> 6 -> False
: [2,2 -> 3,5] -> 8 -> False
: [2,2 -> 4,3] -> 6 -> False
: [2,2 -> 4,4] -> 9 -> False
: [2,2 -> 4,5] -> 12 -> False
: [2,3] skipped (is 0)
: [2,4] skipped (is 0)
: [3,0 -> 4,1] -> 4 -> True
: [3,0 -> 4,2] -> 6 -> True
: [3,0 -> 4,3] -> 8 -> True
: [3,0 -> 4,4] -> 10 -> True
: [3,0 -> 4,5] -> 12 -> False
: [3,1 -> 4,2] -> 4 -> True
: [3,1 -> 4,3] -> 6 -> True
: [3,1 -> 4,4] -> 8 -> True
: [3,1 -> 4,5] -> 10 -> False
: [3,2 -> 4,3] -> 4 -> True
: [3,2 -> 4,4] -> 6 -> True
: [3,2 -> 4,5] -> 8 -> False
: [3,3 -> 4,4] -> 4 -> True
: [3,3 -> 4,5] -> 6 -> False
: [3,4 -> 4,5] -> 4 -> False
: [3,5] skipped (is 0)
: [4,5] skipped (is 0)
: [1,0 -> 4,5] -> 24 -> False
: [1,0 -> 4,4] -> 20 -> False
: [1,1 -> 4,5] -> 20 -> False
: [1,0 -> 3,5] -> 18 -> False
: [1,0 -> 4,3] -> 16 -> False
: [1,1 -> 4,4] -> 16 -> False
: [1,2 -> 4,5] -> 16 -> False
: [0,3 -> 4,5] -> 15 -> False
: [1,0 -> 3,4] -> 15 -> False
: [1,1 -> 3,5] -> 15 -> False
: [0,3 -> 3,5] -> 12 -> False
: [1,0 -> 2,5] -> 12 -> False
: [1,0 -> 3,3] -> 12 -> False
: [1,0 -> 4,2] -> 12 -> False
: [1,1 -> 3,4] -> 12 -> False
: [1,1 -> 4,3] -> 12 -> False
: [1,2 -> 3,5] -> 12 -> False
: [1,2 -> 4,4] -> 12 -> False
: [2,2 -> 4,5] -> 12 -> False
: [3,0 -> 4,5] -> 12 -> False
: [0,3 -> 4,4] -> 10 -> False
: [1,0 -> 2,4] -> 10 -> False
: [1,1 -> 2,5] -> 10 -> False
: [3,0 -> 4,4] -> 10 -> True
[ 1 1 1 1 1 ]
[ 1 1 1 1 1 ]
We can optimize the program a little bit, by moving the «.all-one» check to the
construction phase, so that we can sort only the rectangles that have 1
s
only, and not all of them (with 1
in the upper left corner).
for $start-col +1 .. $cols -1 -> $stop-col
{
my $partial = partial.new(:$start-row, :$stop-row,
:$start-col, :$stop-col);
$partial.debug-output.say if $verbose;
@partials.push: $partial if $partial.all-one;
}
}
}
}
say "" if $verbose;
my @sorted = @partials.sort({ $^b.size <=> $^a.size });
if @sorted
{
@sorted>>.debug-output>>.say if $verbose; # [1]
my $candidate = @sorted[0];
coloured-matrix($candidate.start-row, $candidate.start-col,
$candidate.stop-row, $candidate.stop-col) if $show;
[1] This calls the «.debug-output» method on all the elements (objects) in the array,
and then .say
on each one so that we get a newline after each line.
Running it shows the difference in Verbose mode. The original program shows all the rectangles
sorted by decreasing size until we find a match (all 1
s). This one shows all
the rectangles that are 1
s only, also sorted by decreasing size.
$ ./largest-rectangle2 -v example3.txt
: [0,0] skipped (is 0)
: [0,1] skipped (is 0)
: [0,2] skipped (is 0)
: [0,3 -> 1,4] -> 4 -> True
: [0,3 -> 1,5] -> 6 -> True
: [0,3 -> 2,4] -> 6 -> False
: [0,3 -> 2,5] -> 9 -> False
: [0,3 -> 3,4] -> 8 -> False
: [0,3 -> 3,5] -> 12 -> False
: [0,3 -> 4,4] -> 10 -> False
: [0,3 -> 4,5] -> 15 -> False
: [0,4 -> 1,5] -> 4 -> True
: [0,4 -> 2,5] -> 6 -> False
: [0,4 -> 3,5] -> 8 -> False
: [0,4 -> 4,5] -> 10 -> False
: [1,0 -> 2,1] -> 4 -> False
: [1,0 -> 2,2] -> 6 -> False
: [1,0 -> 2,3] -> 8 -> False
: [1,0 -> 2,4] -> 10 -> False
: [1,0 -> 2,5] -> 12 -> False
: [1,0 -> 3,1] -> 6 -> False
: [1,0 -> 3,2] -> 9 -> False
: [1,0 -> 3,3] -> 12 -> False
: [1,0 -> 3,4] -> 15 -> False
: [1,0 -> 3,5] -> 18 -> False
: [1,0 -> 4,1] -> 8 -> False
: [1,0 -> 4,2] -> 12 -> False
: [1,0 -> 4,3] -> 16 -> False
: [1,0 -> 4,4] -> 20 -> False
: [1,0 -> 4,5] -> 24 -> False
: [1,1 -> 2,2] -> 4 -> False
: [1,1 -> 2,3] -> 6 -> False
: [1,1 -> 2,4] -> 8 -> False
: [1,1 -> 2,5] -> 10 -> False
: [1,1 -> 3,2] -> 6 -> False
: [1,1 -> 3,3] -> 9 -> False
: [1,1 -> 3,4] -> 12 -> False
: [1,1 -> 3,5] -> 15 -> False
: [1,1 -> 4,2] -> 8 -> False
: [1,1 -> 4,3] -> 12 -> False
: [1,1 -> 4,4] -> 16 -> False
: [1,1 -> 4,5] -> 20 -> False
: [1,2 -> 2,3] -> 4 -> False
: [1,2 -> 2,4] -> 6 -> False
: [1,2 -> 2,5] -> 8 -> False
: [1,2 -> 3,3] -> 6 -> False
: [1,2 -> 3,4] -> 9 -> False
: [1,2 -> 3,5] -> 12 -> False
: [1,2 -> 4,3] -> 8 -> False
: [1,2 -> 4,4] -> 12 -> False
: [1,2 -> 4,5] -> 16 -> False
: [1,3 -> 2,4] -> 4 -> False
: [1,3 -> 2,5] -> 6 -> False
: [1,3 -> 3,4] -> 6 -> False
: [1,3 -> 3,5] -> 9 -> False
: [1,3 -> 4,4] -> 8 -> False
: [1,3 -> 4,5] -> 12 -> False
: [1,4 -> 2,5] -> 4 -> False
: [1,4 -> 3,5] -> 6 -> False
: [1,4 -> 4,5] -> 8 -> False
: [2,0] skipped (is 0)
: [2,1] skipped (is 0)
: [2,2 -> 3,3] -> 4 -> False
: [2,2 -> 3,4] -> 6 -> False
: [2,2 -> 3,5] -> 8 -> False
: [2,2 -> 4,3] -> 6 -> False
: [2,2 -> 4,4] -> 9 -> False
: [2,2 -> 4,5] -> 12 -> False
: [2,3] skipped (is 0)
: [2,4] skipped (is 0)
: [3,0] skipped (is 0)
: [3,1] skipped (is 0)
: [3,2 -> 4,3] -> 4 -> True
: [3,2 -> 4,4] -> 6 -> True
: [3,2 -> 4,5] -> 8 -> True
: [3,3 -> 4,4] -> 4 -> True
: [3,3 -> 4,5] -> 6 -> True
: [3,4 -> 4,5] -> 4 -> True
: [4,0] skipped (is 0)
: [4,1] skipped (is 0)
: [3,2 -> 4,5] -> 8 -> True
: [0,3 -> 1,5] -> 6 -> True
: [3,2 -> 4,4] -> 6 -> True
: [3,3 -> 4,5] -> 6 -> True
: [0,3 -> 1,4] -> 4 -> True
: [0,4 -> 1,5] -> 4 -> True
: [3,2 -> 4,3] -> 4 -> True
: [3,3 -> 4,4] -> 4 -> True
: [3,4 -> 4,5] -> 4 -> True
[ 1 1 1 1 ]
[ 1 1 1 1 ]
The idea was to start by removing the 1
s (i.e. replacing them with
0
s) that could not be part of a rectangle, to make it easier to identify
the possible rectangles later on.
It does the removal by inspecting the four 2x2 rectangles the current cell can be
part of, and keeping the value if at least one of them has 1
s only.
#! /usr/bin/env raku
subset BinaryDigit where /^<[01]>$/;
unit sub MAIN ($rectangle where $rectangle.IO.f && $rectangle.IO.r
= 'sample1.txt',
:v(:$verbose));
my @rectangle = $rectangle.IO.lines.map( *.words.grep(BinaryDigit) )>>.Array;
my $rows = @rectangle.elems;
my $cols = @rectangle[0].elems;
die "All rows must have the same length" unless [==] @(@rectangle)>>.elems;
my $pass = 1;
my $sum = @rectangle>>.sum.sum;
LOOP: loop
{
say ": Pass: { $pass++ }" if $verbose;
for ^$rows -> $row
{
for ^$cols -> $col
{
next if @rectangle[$row][$col] == 0;
next if box4($row -1, $col -1) || box4($row, $col -1) ||
box4($row -1, $col ) || box4($row, $col );
@rectangle[$row][$col] = 0;
}
}
my $new-sum = @rectangle>>.sum.sum;
last if $new-sum == $sum;
$sum = $new-sum;
}
say @$_ for @rectangle;
sub box4 ($row, $col)
{
say ": box4($row, $col)" if $verbose;
my $a = @rectangle[$row ][$col ] // return False;
my $b = @rectangle[$row+1][$col ] // return False;
my $c = @rectangle[$row ][$col+1] // return False;
my $d = @rectangle[$row+1][$col+1] // return False;
if $a + $b + $c + $d == 4
{
say ": - ok" if $verbose;
return True;
}
return False;
}
Running it on the examples:
$ ./largest-rectangle-cleanup ../example1.txt
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[1 1 1 1 1 0]
[1 1 1 1 1 0]
$ ./largest-rectangle-cleanup ../example2.txt
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
$ ./largest-rectangle-cleanup ../example3.txt
[0 0 0 1 1 1]
[0 0 0 1 1 1]
[0 0 0 0 0 0]
[0 0 1 1 1 1]
[0 0 1 1 1 1]
I stopped there. This approach had a «brute force»-ish feel, whithout actually solving the challenge. The third example shows that we have two candidates, and the task of picking one of them remains. So I decided to go for brute force instead, from scratch.
And that's it.