Object-Oriented Perl
package Set;

sub new
{
      my ($type) = shift;
      my ($self, $other, $index, @args, %seen);

      if (@_)
      {
           foreach (@_) {$seen{$_} = 1}
           @$self = sort {$a <=> $b} keys %seen; 
           return bless $self, 'Set';    #  Forget about inheritance.
      }
      elsif (ref $type)   #  Clone the set.
      {
           @$other = @$type;
           return bless $other, 'Set';
      }
      else  #  No args.
      {
           return bless [], 'Set';
      }
} 



sub PrintSet
{
      my ($self) = shift;
   
      print "@$self\n";
}



sub AddMembers
{
      my ($self, @members) = @_;
      my ($member, @addset, %seen);


      foreach $member (@members) {
           push(@addset, (ref $member) ? @$member : $member);
      } 

      foreach $member (@$self) {$seen{$member} = 1}

      foreach $member (@addset) {
            push(@$self, $member) if !$seen{$member};
            $seen{$member} = 1;
      }

      @$self = sort {$a <=> $b} @$self;
}
sub RemoveMembers
{
    my ($self, @remove) = @_;
    my ($member, %seen);

    foreach $member (@remove) {$seen{$member} = 1}
    @$self = grep {!$seen{$_}} @$self; 
#    foreach $member (@remove)
#    {
#        next if !$self->IsMember($member);
#        for ($i = 0 ; $i < @$self; $i++)
#        {
#              splice(@$self, $i, 1) if $member == $self->[$i];
#        }
#    }
} 



sub GetMembers
{
     my ($self) = @_;
     return @$self;
}





sub IsMember
{
      my ($self, $wannabee) = @_;
      my $member;

      foreach $member (@$self)
      {
           return 1 if $wannabee == $member;
      }
      return 0;
}






sub IsSubset
{
      my ($self, $other) = @_;
      my $index;

      return 1 if @$other == 0;  # Empty set is a subset of everything! 
      return 0 if @$self == 0;    # Nothing is a subset of the empty set!

      foreach $index (0..@$other - 1)
      {
           return 0 if !$self->IsMember($other->[$index]);
      }
      return 1;
}
sub intersection
{
      my ($self, $other) = @_;
      my ($member, %seen, $intersect);

      foreach $member (@$self, @$other)
      {
           $seen{$member}++;
           push(@$intersect, $member) if $seen{$member} == 2;
      }
      return bless $intersect;
}

      




sub union
{
      my ($self, $other) = @_;
      my $union;

      $union = Set->new(@$self, @$other);
      return $union; 
}



sub Differences
{
     my ($self, $other) = @_;
     my ($diffs, $isect);

     $diffs = $self->union($other); 
     $isect = $self->intersection($other);
     $diffs->RemoveMembers(@$isect);
     return bless $diffs, 'Set';
}



#sub Differences
#{
#     my ($self, $other) = @_;
#     my ($num, %seen, $diffs);
#
#     foreach $num (@$self, @$other) {$seen{$num}++}
#     
#     foreach $num (sort {$a <=> $b} keys %seen) {
#        push @$diffs, $num if $seen{$num} == 1;
#     }
#     return bless $diffs, 'Set';
#}
1;