in reply to Difference arrays.

Fun with DDT!

use Test::More; my $r1 = {}; my $r2 = []; my @tests = ( { in1 => [ 43, 43, 44 ], in2 => [ 43, 43 ], out => [ 44 ], }, { in1 => [ 1,1,1,1,1,2,2,2,3,3,4,5,6 ], in2 => [ 1,2,3,4,5,6 ], out => [ 1,1,1,1,2,2,3 ], }, { in1 => [ $r1, $r1, $r2 ], in2 => [ $r1, $r1 ], out => [ $r2 ], }, ); my %solutions = ( Skeeve => \&skeeve, moritz => \&moritz, moritz2 => \&moritz2, kyle => \&kyle, betterworld => \&betterworld, ); plan 'tests' => scalar keys( %solutions ) * scalar @tests; while ( my ( $name, $code ) = each %solutions ) { my $n = 0; foreach my $t ( @tests ) { $n++; is_deeply( $code->( $t->{in1}, $t->{in2} ), $t->{out}, "$name +$n" ); } } sub kyle { my ( $ref1, $ref2 ) = @_; my %h; $h{$_}++ for @{$ref1}; $h{$_}-- for @{$ref2}; my %x; return [ grep { $x{$_}++ < $h{$_} } @{$ref1} ]; } sub skeeve { my ($a, $b)= @_; my %d; ++$d{$_} foreach @$a; --$d{$_} foreach @$b; my $d= (); return [ map { ($_) x abs $d{$_} } keys %d ]; } sub moritz { my ( $ref1, $ref2 ) = @_; my @p = @{$ref1}; my @q = @{$ref2}; my ($px, $qx) = (0, 0); my @diff; while (1) { if ($qx >= @q){ push @diff, @p[$px .. @p-1]; last; } elsif ( $p[$px] == $q[$qx] ) { $px++; $qx++; } else { push @diff, $p[$px++]; } } return \@diff; } sub moritz2 { my ( $ref1, $ref2 ) = @_; my @p = @{$ref1}; my @q = @{$ref2}; my ($px, $qx) = (0, 0); my @diff; while ($qx < @q) { if ( $p[$px] == $q[$qx] ) { $px++; $qx++; } else { push @diff, $p[$px++]; } } push @diff, @p[$px .. @p-1]; return \@diff; } sub betterworld { my ( $ref1, $ref2 ) = @_; my @p = @{$ref1}; my @q = @{$ref2}; my %q; $q{$_}++ for @q; my @r = grep { --$q{$_} < 0; } @p; return \@r; }

My own solution pulled out of the <readmore>:

sub kyle { my ( $ref1, $ref2 ) = @_; my %h; $h{$_}++ for @{$ref1}; $h{$_}-- for @{$ref2}; my %x; return [ grep { $x{$_}++ < $h{$_} } @{$ref1} ]; }

I notice that Skeeve's has the bug mine had before I tested it.

I'm happily surprised at how many don't have the bug I was expecting when I wrote the [ $r1, ... ] test.

I, for one, wasn't shooting to optimize memory usage. I just wrote the first thing I thought of.

Replies are listed 'Best First'.
Re^2: Difference arrays.
by Skeeve (Parson) on Sep 04, 2008 at 21:22 UTC

    Okay… Mine has the bug that it stringifies the keys. agreed.

    yours has a bug too! It doesn't work in this case:

    kyle( \@q, \@p );

    No! Mine has the bug in that it doesn't care for what BrowserUK asked for!


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

      (OK, so as I was writing this, the node I'm replying to was updated. I'll post anyway...)

      I don't know what you mean. You've passed in the input arrays in the opposite order?

      The OP specifies that the second array is to be a proper subset of the first. If you reverse them, that violates this condition. So what would you expect to get back in that case? Mine returns (a reference to) an empty array. The solution from betterworld gets the same thing. The two solutions that moritz posted go into an infinite loop (apparently—I didn't exactly wait that long). The only other working solution, pjotrik's, gets something else.

      Anyway, here's an updated test script...