#!/usr/bin/perl

sub intersection {
    my ( $i, $sizei ) = ( 0, scalar keys %{ $_[0] } );
    my ( $j, $sizej );

    # Find the smallest hash to start.
    for ( $j = 1; $j < @_; $j++ ) {
        $sizej = keys %{ $_[ $j ] };
        ( $i, $sizei ) = ( $j, $sizej ) if $sizej < $sizei;
    }

    # Reduce the list of possible elements by each hash in turn.
    my @intersection = keys %{ splice @_, $i, 1 };
    my $set;
    while ( $set = shift ) {
        @intersection = grep { exists $set->{ $_ } } @intersection;
    }

    my %intersection;
    @intersection{ @intersection } = ( );

    return \%intersection;
}

@Cats{    qw(cat lion tiger)  } = ( );
@Asian{   qw(tiger panda yak) } = ( );
@Striped{ qw(zebra tiger)     } = ( );

$Cats_Asian_Striped = intersection( \%Cats, \%Asian, \%Striped );

print join(" ", keys %{ $Cats_Asian_Striped }), "\n";
