Set - simple integer set handling class
my @array = ( 1..10 ); Set->new(@array);
This is Set version 0.3, alpha quality and still in construction. Most basic set operators are missing. May break your computer or burn your coffee. Use at your own risk!
A simple object oriented class for integer sets providing basic set operators and iteration functionality as methods. Set is a linked list.
new(@array)
Creates a new set object. Takes as a parameter an array or a list of scalars. Does not do any type checking but forces parameters to integers.
=head2 to_string( )
Returns set as a string.
=head2 elements( )
Returns an array containing the elements of the set.
=head2 rewind( )
Rewinds the set pointer to the first element.
=head2 current( )
Returns the current element in the set.
=head2 next( )
Returns the current element or undef if at the end of the set. Sets the pointer to the next element if not at the end of the set, 0 otherwise.
=head2 prev( )
Returns the current element or undef if at the beginning of the set. Sets the pointer to the previous element if not at the beginning of the set, 0 otherwise.
=head2 size( )
Returns the size of the set.
=head2 min( )
Returns the smallest integer in the set or undef if set is emtpy.
=head2 max( )
Returns the largest integer in the set or undef if set is empty.
=head2 remove($int)
Removes the given integer from the set and returns the removed integer or undef if nothing was removed.
=head2 add($int)
Adds the given integer to the set if set doesn't yet contain it and returns the given integer or undef if nothing was added.
=head2 contains($int)
Returns 1 if set contains the given integer, otherwise 0.
=head2 union($set)
Performs an union of self and given set object.
=head1 AUTHOR
Set by Marko Vihoma <marko (dot) vihoma (at) pp1 (dot) inet (dot) fi>
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Many thanks go to the llama book, which I have read recently. Thanks also to my brother who has given me insights to Perl. Method naming conventions from Set::IntSpan by Steven McDougall, and discrete math course in Kuopio university.
package Set; # We need perl 5.* use 5; # Pragmas use integer; use strict; use warnings; # Version string our $VERSION = "0.3"; ## no critic # Should I buy Perl Best Practices? sub new { my $class = shift; # How do I unpack @_ first? See page 178 of PBP. my $set = []; if (@_) { $set = [ @_ ]; # Or is it this? } my $self = { pos => 0, set => $set }; bless($self, ref $class || $class); return $self; } ## use critic sub to_string { my $self = shift; my @set = $self->elements(); my $ret = ""; for my $i (0..$#set) { if ($i == $#set) { $ret .= $set[$i]; } else { $ret .= "$set[$i], "; } } return $ret; } sub elements { my $self = shift; my @set = @{ $self->{'set'} }; return @set; } sub rewind { my $self = shift; $self->{'pos'} = 0; return 1; } sub is_empty { my $self = shift; my @set = @{ $self->{'set'} }; if (@set) { return 0; } else { return 1; } } sub position { my $self = shift; my $prevpos = $self->{'pos'}; if (@_) { my $position = shift; if ($position <= $self->size()) { $self->{'pos'} = $position; return $position; } else { return undef; } } return $prevpos; } sub current { my $self = shift; return $self->{'set'}->[$self->position()]; } sub next { my $self = shift; my $position = $self->position(); if ($position == $self->size()) { $self->position(0); return undef; } else { my $current = $self->current(); $self->position(++$position); return $current; } } sub prev { my $self = shift; my $position = $self->position(); if ($position < 0) { $self->position($self->size() - 1); return undef; } else { my $current = $self->current(); $self->position(--$position); return $current; } } sub size { my $self = shift; return $#{ $self->{'set'} } + 1; } sub min { my $self = shift; # min is undef if set is empty my $min = undef; # We'll find min only if set is not empty if(not $self->is_empty) { # Save current position my $position = $self->position(); # Rewind position to 0 $self->rewind(); $min = $self->next(); # Let's iterate through self while (my $element = $self->next()) { $min = $element if ($element < $min); } # Restore old position $self->position($position); } return $min; } sub max { my $self = shift; my $max = undef; # We'll find max only if set is not empty if (not $self->is_empty()) { # Save current position my $position = $self->position(); # Rewind position to 0 $self->rewind(); $max = $self->next(); # Let's iterate through self while (my $element = $self->next()) { $max = $element if ($element > $max); } # Restore old position $self->position($position); } # Return undef if set is emtpy return $max; } sub clear { my $self = shift; $self->{'set'} = \(); return; } sub remove { my ($self, $element) = @_; my $s = new Set (); if ($self->contains($element)) { # Save the sets position my $position = $self->position(); # We'll start from the beginning of the set $self->rewind(); # Let's iterate through current set while (my $cell = $self->next()) { # Add all elements except the one to be removed to the new set $s->add($cell) unless ($cell == $element); } # Go back to old position $self->position($position); # self's set gets only $s's elements $self->{'set'} = [ $s->elements() ]; # Return the removed element return $element; } else { # If nothing was removed, return undef return undef; } } sub add { my ($self, $new) = @_; # Add element only if we don't have it already unless ($self->contains($new)) { $self->{'set'}->[$self->size()] = $new; return $new; } else { return undef; } } sub contains { my ($self, $other) = @_; # Return value is false by default my $ret = 0; # Save sets position my $position = $self->position(); # rewind position to 0 $self->rewind(); # Let's iterate through self while (my $element = $self->next()) { # Exit loop if set contains the given element if (int($other) == $element) { $ret = 1; last; } } # Restore old position $self->position($position); return $ret; } sub union { my ($self, $s) = @_; # Complain if parameter is not a reference if (not ref $s) { print STDERR "Parameter must be an object reference!\n"; return 0; } bless($s); # Save $s's position my $position = $s->position(); # Rewind position to 0 $s->rewind(); # Let's iterate through $s while (my $cell = $s->next()) { $self->add($cell); } # Restore old position $s->position($position); return 1; } 1; __END__