in reply to Re: Testing the Uniformity of an Array by its Elements
in thread Testing the Uniformity of an Array by its Elements

Not the fastest? Let's see what we can do about it.

That's tail-end recursion, so it can be optimized:

sub equal { return 1 if @_ < 2; return 0 if $_[0] ne $_[1]; shift; goto(&equal); }

And the recursive call can be eliminated completely:

sub equal { while (@_ >= 2) { return 0 if $_[0] ne $_[1]; shift; } return 1; }

Benchmarks:

use strict; use warnings; use Benchmark qw( cmpthese ); my @list = ('1')x10; sub equal_pm {@_ < 2 || $_[0] eq $_[1] && equal_pm(@_[1..$#_])} sub equal_i { return 1 if @_ < 2; return 0 if $_[0] ne $_[1]; shift; goto(&equal_i); } sub equal_i2 { while (@_ >= 2) { return 0 if $_[0] ne $_[1]; shift; } return 1; } cmpthese(-3, { equal_pm => sub { my $rv = equal_pm(@list) ?1:0; 1; }, equal_i => sub { my $rv = equal_i (@list) ?1:0; 1; }, equal_i2 => sub { my $rv = equal_i2(@list) ?1:0; 1; }, });
Rate equal_pm equal_i equal_i2 equal_pm 17854/s -- -51% -74% equal_i 36454/s 104% -- -46% equal_i2 67523/s 278% 85% --

Replies are listed 'Best First'.
Re^3: Testing the Uniformity of an Array by its Elements
by tirwhan (Abbot) on Nov 02, 2005 at 17:54 UTC

    Oh well, if we're going for speed:

    #!/usr/bin/perl use List::MoreUtils; use Perl6::Junction; use strict; use warnings; use Benchmark qw( cmpthese ); my @list = ('1')x10; sub equal_pm {@_ < 2 || $_[0] eq $_[1] && equal_pm(@_[1..$#_])} sub equal_i { return 1 if @_ < 2; return 0 if $_[0] ne $_[1]; shift; goto(&equal_i); } sub equal_i2 { while (@_ >= 2) { return 0 if $_[0] ne $_[1]; shift; } return 1; } sub equal_ti { return 1 if (Perl6::Junction::all(@_) eq $_[0]); return 0; } sub equal_fr { my $first = shift; for(@_) { return 0 unless $_ eq $first; } return 1; } sub equal_pw { return 1 if (List::MoreUtils::all { $_ eq $_[0] } @_); return 0; } sub equal_zx { my %hash; @hash{@_} = (); !(1 - keys %hash); } cmpthese(-3, { pm => sub { my $rv = equal_pm(@list) ?1:0; 1; }, i1 => sub { my $rv = equal_i (@list) ?1:0; 1; }, i2 => sub { my $rv = equal_i2(@list) ?1:0; 1; }, pw => sub { my $rv = equal_pw(@list) ?1:0; 1; }, ti => sub { my $rv = equal_ti(@list) ?1:0; 1; }, fr => sub { my $rv = equal_fr(@list) ?1:0; 1; }, zx => sub { my $rv = equal_zx(@list) ?1:0; 1; }, });
    Which gives:
    Rate pm ti i1 pw i2 fr zx pm 52188/s -- -30% -47% -69% -73% -78% -82% ti 74488/s 43% -- -24% -55% -61% -68% -74% i1 97929/s 88% 31% -- -41% -49% -58% -65% pw 166481/s 219% 123% 70% -- -13% -29% -41% i2 192200/s 268% 158% 96% 15% -- -18% -32% fr 235585/s 351% 216% 141% 42% 23% -- -17% zx 283834/s 444% 281% 190% 70% 48% 20% --
    So friedo's solution (with some slight alterations for performance) wins.

    Update:Included Zaxo's hash solution, all hail the new speed king!


    Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan