UpTide UpTide - 4 years ago 144
Perl Question

Simplifying Conditional Statement [Perl]

I have a 3d matrix and I need to check if several elements equals a value (target value could be different for each element in the future).

Is there any way to simplify the if conditional at the end? I am hoping there would be some way to setup a 'conditional' matrix and compare them while ignoring elements that don't matter in the condition.

Any hints?

currently my code is:

use warnings;
use strict;

#fancy matrix
my @matrix;

#set to a blank 3d test matrix
for my $i (0 .. 6) {
for my $j (0 .. 6) {
for my $k (0 .. 2) {
$matrix[$i][$j][$k] = 0;
}
}
}

#set some values for matrix

for my $j (0..2, 4..6) {
my $i = 4;
for my $k (0 .. 2) {
$matrix[$i][$j][$k] = 1;
}
}
for my $i (0..2, 4..6) {
my $j = 4;
for my $k (0 .. 2) {
$matrix[$i][$j][$k] = 1;
}
}

#the conditional problem child
if ($matrix[0][4][0] == 1 and $matrix[0][4][1] == 1 and $matrix[0][4][2] == 1 and $matrix[1][4][0] == 1 and $matrix[1][4][1] == 1 and $matrix[1][4][2] == 1 and $matrix[2][4][0] == 1 and $matrix[2][4][1] == 1 and $matrix[2][4][2] == 1 and $matrix[4][4][0] == 1 and $matrix[4][4][1] == 1 and $matrix[4][4][2] == 1 and $matrix[5][4][0] == 1 and $matrix[5][4][1] == 1 and $matrix[5][4][2] == 1 and $matrix[6][4][0] == 1 and $matrix[6][4][1] == 1 and $matrix[6][4][2] == 1 and $matrix[4][0][0] == 1 and $matrix[4][0][1] == 1 and $matrix[4][0][2] == 1 and $matrix[4][1][0] == 1 and $matrix[4][1][1] == 1 and $matrix[4][1][2] == 1 and $matrix[4][2][0] == 1 and $matrix[4][2][1] == 1 and $matrix[4][2][2] == 1 and $matrix[4][4][0] == 1 and $matrix[4][4][1] == 1 and $matrix[4][4][2] == 1 and $matrix[4][5][0] == 1 and $matrix[4][5][1] == 1 and $matrix[4][5][2] == 1 and $matrix[4][6][0] == 1 and $matrix[4][6][1] == 1 and $matrix[4][6][2] == 1) {
print "it worked";
}

<stdin>;


edit note: If the way I'm approaching it is the best (doubt it), is there at least a way to make the if condition readable (not 36 compares on a single line)?

Answer Source

I suggest that you build an array of references to all the matrix elements in the subset. Then you can both set and test them in simple for loops

Here my array of references is called @cells. I've also used the all function from List::Util, which allows all the tests to be made in a single call, and will short-circuit as soon as any test fails

use strict;
use warnings 'all';

use List::Util 'all';

my @matrix;
my @cells;

# Initialise the matrix to all zeroes

for my $i (0 .. 6) {
    for my $j (0 .. 6) {
        for my $k  (0 .. 2) {
            $matrix[$i][$j][$k] = 0;
        }
    }
}

# Build an array of references to a subset of the cells
#
for my $i ( 0 .. 2, 4 .. 6 ) {
    push @cells, \$matrix[$i][4][$_] for 0 .. 2;
}

for my $j ( 0 .. 2, 4 .. 6 ) {
    push @cells, \$matrix[4][$j][$_] for 0 .. 2;
}

$$_ = 1 for @cells; # Set all the cells in the subset to 1

# Test that all cells in the subset are == 1
#
if ( all { $$_ == 1 } @cells ) {
    print "It worked\n";
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download