in reply to merging two arrays with OR operation
Late to the party again but here's a solution that uses vec to construct bitstrings from the arrays that can be binary ORed to produce a result. The vector and the length of the original array are held in a hashref so that problems with reconstructing the array when the vector extends to a byte boundary can be avoided.
use 5.026;
use warnings;
my @array1 = ( 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 );
my @array2 = ( 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1 );
my @arrayResult = vec2array(
vecORvec( array2vec( @array1 ), array2vec( @array2 ) )
);
say join q{, }, @arrayResult;
sub array2vec
{
my $rhVec = {};
$rhVec->{ len } = scalar @_;
$rhVec->{ vec } = q{};
vec( $rhVec->{ vec }, $_, 1 ) = $_[ $_ ]
for 0 .. $rhVec->{ len } - 1;
return $rhVec;
}
sub vec2array
{
my @array = map {
vec $_[ 0 ]->{ vec }, $_, 1
} 0 .. $_[ 0 ]->{ len } - 1;
return @array;
}
sub vecORvec
{
my( $rhVec1, $rhVec2 ) = @_;
my $rhNewVec;
$rhNewVec->{ len } = $rhVec1->{ len };
$rhNewVec->{ vec } = $rhVec1->{ vec } | $rhVec2->{ vec };
return $rhNewVec;
}
The result.
0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1
I hope this is of interest.
Update: Added some sanity checking and confined the conversion of array to vector to the rule of false/true corresponding to bit values of 0 or 1 respectively. I also added AND and XOR routines, which along with OR will cope with vectors of differing length, and borrowed and adapted AnomalousMonk's test data.
use 5.026;
use warnings;
use Test::More qw{ no_plan };
my @ORtests = (
q{degenerate case},
[ [], [], [], ],
q{simple cases},
[ [ 0 ], [ 0 ], [ 0 ], ],
[ [ 0 ], [ 1 ], [ 1 ], ],
[ [ 1 ], [ 0 ], [ 1 ], ],
[ [ 1 ], [ 1 ], [ 1 ], ],
[ [ 5 ], [ 0 ], [ 1 ], ],
[ [ q{x} ], [ 44 ], [ 1 ], ],
q{complex cases},
[ [ 0, 1, 0, 1, ],
[ 0, 0, 1, 1, ],
[ 0, 1, 1, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
],
q{differing length cases},
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, ],
[ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
],
);
say qq{\nOR tests\n};
foreach my $ORtest ( @ORtests )
{
do { say $ORtest; next } unless ref $ORtest eq q{ARRAY};
my( $raT1, $raT2, $raExpected ) = @$ORtest;
my @got =
vec2array( vecORvec( array2vec( @$raT1 ), array2vec( @$raT2 ) )
+ );
is_deeply
\ @got,
$raExpected,
qq{OR result - @got};
}
my @ANDtests = (
q{degenerate case},
[ [], [], [], ],
q{simple cases},
[ [ 0 ], [ 0 ], [ 0 ], ],
[ [ 0 ], [ 1 ], [ 0 ], ],
[ [ 1 ], [ 0 ], [ 0 ], ],
[ [ 1 ], [ 1 ], [ 1 ], ],
[ [ 5 ], [ 0 ], [ 0 ], ],
[ [ q{x} ], [ 44 ], [ 1 ], ],
q{complex cases},
[ [ 0, 1, 0, 1, ],
[ 0, 0, 1, 1, ],
[ 0, 0, 0, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
],
q{differing length cases},
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, ],
[ 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, ],
],
);
say qq{\nAND tests\n};
foreach my $ANDtest ( @ANDtests )
{
do { say $ANDtest; next } unless ref $ANDtest eq q{ARRAY};
my( $raT1, $raT2, $raExpected ) = @$ANDtest;
my @got =
vec2array( vecANDvec( array2vec( @$raT1 ), array2vec( @$raT2 )
+) );
is_deeply
\ @got,
$raExpected,
qq{AND result - @got};
}
my @XORtests = (
q{degenerate case},
[ [], [], [], ],
q{simple cases},
[ [ 0 ], [ 0 ], [ 0 ], ],
[ [ 0 ], [ 1 ], [ 1 ], ],
[ [ 1 ], [ 0 ], [ 1 ], ],
[ [ 1 ], [ 1 ], [ 0 ], ],
[ [ 5 ], [ 0 ], [ 1 ], ],
[ [ q{x} ], [ 44 ], [ 0 ], ],
q{complex cases},
[ [ 0, 1, 0, 1, ],
[ 0, 0, 1, 1, ],
[ 0, 1, 1, 0, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, ],
],
q{differing length cases},
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, ],
[ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, ],
],
);
say qq{\nXOR tests\n};
foreach my $XORtest ( @XORtests )
{
do { say $XORtest; next } unless ref $XORtest eq q{ARRAY};
my( $raT1, $raT2, $raExpected ) = @$XORtest;
my @got =
vec2array( vecXORvec( array2vec( @$raT1 ), array2vec( @$raT2 )
+) );
is_deeply
\ @got,
$raExpected,
qq{XOR result - @got};
}
sub array2vec
{
my $rhVec = {};
$rhVec->{ len } = scalar @_;
$rhVec->{ vec } = q{};
return $rhVec unless $rhVec->{ len };
vec( $rhVec->{ vec }, $_, 1 ) = $_[ $_ ] ? 1 : 0
for 0 .. $rhVec->{ len } - 1;
return $rhVec;
}
sub vec2array
{
return () unless $_[ 0 ]->{ len };
my @array = map {
vec $_[ 0 ]->{ vec }, $_, 1
} 0 .. $_[ 0 ]->{ len } - 1;
return @array;
}
sub vecANDvec
{
my( $rhVec1, $rhVec2 ) = @_;
my $rhNewVec = { len => 0, vec => q{} };
if ( $rhVec1->{ len } == $rhVec2->{ len } )
{
return $rhNewVec unless $rhVec1->{ len };
$rhNewVec->{ len } = $rhVec1->{ len };
$rhNewVec->{ vec } = $rhVec1->{ vec } & $rhVec2->{ vec };
}
elsif ( $rhVec1->{ len } > $rhVec2->{ len } )
{
$rhNewVec->{ len } = $rhVec1->{ len };
vec( $rhVec2->{ vec }, $rhVec1->{ len } - 1, 1 ) = 0;
$rhNewVec->{ vec } = $rhVec1->{ vec } & $rhVec2->{ vec };
}
else
{
$rhNewVec->{ len } = $rhVec2->{ len };
vec( $rhVec1->{ vec }, $rhVec2->{ len } - 1, 1 ) = 0;
$rhNewVec->{ vec } = $rhVec1->{ vec } & $rhVec2->{ vec };
}
return $rhNewVec;
}
sub vecORvec
{
my( $rhVec1, $rhVec2 ) = @_;
my $rhNewVec = { len => 0, vec => q{} };
if ( $rhVec1->{ len } == $rhVec2->{ len } )
{
return $rhNewVec unless $rhVec1->{ len };
$rhNewVec->{ len } = $rhVec1->{ len };
$rhNewVec->{ vec } = $rhVec1->{ vec } | $rhVec2->{ vec };
}
elsif ( $rhVec1->{ len } > $rhVec2->{ len } )
{
$rhNewVec->{ len } = $rhVec1->{ len };
vec( $rhVec2->{ vec }, $rhVec1->{ len } - 1, 1 ) = 0;
$rhNewVec->{ vec } = $rhVec1->{ vec } | $rhVec2->{ vec };
}
else
{
$rhNewVec->{ len } = $rhVec2->{ len };
vec( $rhVec1->{ vec }, $rhVec2->{ len } - 1, 1 ) = 0;
$rhNewVec->{ vec } = $rhVec1->{ vec } | $rhVec2->{ vec };
}
return $rhNewVec;
}
sub vecXORvec
{
my( $rhVec1, $rhVec2 ) = @_;
my $rhNewVec = { len => 0, vec => q{} };
if ( $rhVec1->{ len } == $rhVec2->{ len } )
{
return $rhNewVec unless $rhVec1->{ len };
$rhNewVec->{ len } = $rhVec1->{ len };
$rhNewVec->{ vec } = $rhVec1->{ vec } ^ $rhVec2->{ vec };
}
elsif ( $rhVec1->{ len } > $rhVec2->{ len } )
{
$rhNewVec->{ len } = $rhVec1->{ len };
vec( $rhVec2->{ vec }, $rhVec1->{ len } - 1, 1 ) = 0;
$rhNewVec->{ vec } = $rhVec1->{ vec } ^ $rhVec2->{ vec };
}
else
{
$rhNewVec->{ len } = $rhVec2->{ len };
vec( $rhVec1->{ vec }, $rhVec2->{ len } - 1, 1 ) = 0;
$rhNewVec->{ vec } = $rhVec1->{ vec } ^ $rhVec2->{ vec };
}
return $rhNewVec;
}
The test results.
OR tests
degenerate case
ok 1 - OR result -
simple cases
ok 2 - OR result - 0
ok 3 - OR result - 1
ok 4 - OR result - 1
ok 5 - OR result - 1
ok 6 - OR result - 1
ok 7 - OR result - 1
complex cases
ok 8 - OR result - 0 1 1 1
ok 9 - OR result - 0 1 1 1 0 1 1 1 1 1 1 1
differing length cases
ok 10 - OR result - 0 1 1 1 0 1 1 1 1 1 1 1
ok 11 - OR result - 0 1 1 1 0 1 1 1 1 1 1 1
AND tests
degenerate case
ok 12 - AND result -
simple cases
ok 13 - AND result - 0
ok 14 - AND result - 0
ok 15 - AND result - 0
ok 16 - AND result - 1
ok 17 - AND result - 0
ok 18 - AND result - 1
complex cases
ok 19 - AND result - 0 0 0 1
ok 20 - AND result - 0 0 0 1 0 1 0 1 0 1 1 1
differing length cases
ok 21 - AND result - 0 0 0 1 0 1 0 1 0 1 0 0
ok 22 - AND result - 0 0 0 1 0 1 0 1 0 1 0 0
XOR tests
degenerate case
ok 23 - XOR result -
simple cases
ok 24 - XOR result - 0
ok 25 - XOR result - 1
ok 26 - XOR result - 1
ok 27 - XOR result - 0
ok 28 - XOR result - 1
ok 29 - XOR result - 0
complex cases
ok 30 - XOR result - 0 1 1 0
ok 31 - XOR result - 0 1 1 0 0 0 1 0 1 0 0 0
differing length cases
ok 32 - XOR result - 0 1 1 0 0 0 1 0 1 0 1 1
ok 33 - XOR result - 0 1 1 0 0 0 1 0 1 0 1 1
1..33
Possibly a waste of time but feeping creaturism can be fun :-)
Update 2: Took repetitive code out of the three comparison routines, (vecANDvec(), vecORvec(), vecXORvec()), and moved it into vecANYvec() which is passed a coderef telling it which operation to do. All tests still pass.
use 5.026;
use warnings;
use Test::More qw{ no_plan };
my @ORtests = (
q{degenerate case},
[ [], [], [], ],
q{simple cases},
[ [ 0 ], [ 0 ], [ 0 ], ],
[ [ 0 ], [ 1 ], [ 1 ], ],
[ [ 1 ], [ 0 ], [ 1 ], ],
[ [ 1 ], [ 1 ], [ 1 ], ],
[ [ 5 ], [ 0 ], [ 1 ], ],
[ [ q{x} ], [ 44 ], [ 1 ], ],
q{complex cases},
[ [ 0, 1, 0, 1, ],
[ 0, 0, 1, 1, ],
[ 0, 1, 1, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
],
q{differing length cases},
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, ],
[ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
],
);
say qq{\nOR tests\n};
foreach my $ORtest ( @ORtests )
{
do { say $ORtest; next } unless ref $ORtest eq q{ARRAY};
my( $raT1, $raT2, $raExpected ) = @$ORtest;
my @got =
vec2array( vecORvec( array2vec( @$raT1 ), array2vec( @$raT2 ) )
+ );
is_deeply
\ @got,
$raExpected,
qq{OR result - @got};
}
my @ANDtests = (
q{degenerate case},
[ [], [], [], ],
q{simple cases},
[ [ 0 ], [ 0 ], [ 0 ], ],
[ [ 0 ], [ 1 ], [ 0 ], ],
[ [ 1 ], [ 0 ], [ 0 ], ],
[ [ 1 ], [ 1 ], [ 1 ], ],
[ [ 5 ], [ 0 ], [ 0 ], ],
[ [ q{x} ], [ 44 ], [ 1 ], ],
q{complex cases},
[ [ 0, 1, 0, 1, ],
[ 0, 0, 1, 1, ],
[ 0, 0, 0, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
],
q{differing length cases},
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, ],
[ 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, ],
],
);
say qq{\nAND tests\n};
foreach my $ANDtest ( @ANDtests )
{
do { say $ANDtest; next } unless ref $ANDtest eq q{ARRAY};
my( $raT1, $raT2, $raExpected ) = @$ANDtest;
my @got =
vec2array( vecANDvec( array2vec( @$raT1 ), array2vec( @$raT2 )
+) );
is_deeply
\ @got,
$raExpected,
qq{AND result - @got};
}
my @XORtests = (
q{degenerate case},
[ [], [], [], ],
q{simple cases},
[ [ 0 ], [ 0 ], [ 0 ], ],
[ [ 0 ], [ 1 ], [ 1 ], ],
[ [ 1 ], [ 0 ], [ 1 ], ],
[ [ 1 ], [ 1 ], [ 0 ], ],
[ [ 5 ], [ 0 ], [ 1 ], ],
[ [ q{x} ], [ 44 ], [ 0 ], ],
q{complex cases},
[ [ 0, 1, 0, 1, ],
[ 0, 0, 1, 1, ],
[ 0, 1, 1, 0, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, ],
],
q{differing length cases},
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, ],
[ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, ],
],
[ [ 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, ],
[ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, ],
[ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, ],
],
);
say qq{\nXOR tests\n};
foreach my $XORtest ( @XORtests )
{
do { say $XORtest; next } unless ref $XORtest eq q{ARRAY};
my( $raT1, $raT2, $raExpected ) = @$XORtest;
my @got =
vec2array( vecXORvec( array2vec( @$raT1 ), array2vec( @$raT2 )
+) );
is_deeply
\ @got,
$raExpected,
qq{XOR result - @got};
}
sub array2vec
{
my $rhVec = {};
$rhVec->{ len } = scalar @_;
$rhVec->{ vec } = q{};
return $rhVec unless $rhVec->{ len };
vec( $rhVec->{ vec }, $_, 1 ) = $_[ $_ ] ? 1 : 0
for 0 .. $rhVec->{ len } - 1;
return $rhVec;
}
sub vec2array
{
return () unless $_[ 0 ]->{ len };
my @array = map {
vec $_[ 0 ]->{ vec }, $_, 1
} 0 .. $_[ 0 ]->{ len } - 1;
return @array;
}
sub vecANYvec
{
my( $rhVec1, $rhVec2, $rcOper ) = @_;
my $rhNewVec = { len => 0, vec => q{} };
if ( $rhVec1->{ len } == $rhVec2->{ len } )
{
return $rhNewVec unless $rhVec1->{ len };
$rhNewVec->{ len } = $rhVec1->{ len };
}
elsif ( $rhVec1->{ len } > $rhVec2->{ len } )
{
$rhNewVec->{ len } = $rhVec1->{ len };
vec( $rhVec2->{ vec }, $rhVec1->{ len } - 1, 1 ) = 0;
}
else
{
$rhNewVec->{ len } = $rhVec2->{ len };
vec( $rhVec1->{ vec }, $rhVec2->{ len } - 1, 1 ) = 0;
}
$rhNewVec->{ vec } = $rcOper->( $rhVec1->{ vec }, $rhVec2->{ vec }
+ );
return $rhNewVec;
}
sub vecANDvec
{
my( $rhVec1, $rhVec2 ) = @_;
return vecANYvec(
$rhVec1,
$rhVec2,
sub { return $_[ 0 ] & $_[ 1 ] }
);
}
sub vecORvec
{
my( $rhVec1, $rhVec2 ) = @_;
return vecANYvec(
$rhVec1,
$rhVec2,
sub { return $_[ 0 ] | $_[ 1 ] }
);
}
sub vecXORvec
{
my( $rhVec1, $rhVec2 ) = @_;
return vecANYvec(
$rhVec1,
$rhVec2,
sub { return $_[ 0 ] ^ $_[ 1 ] }
);
}
|
|