#!/usr/bin/perl # setOperation: # This script performs a set-theory operation on two sets of data. # (see http://en.wikipedia.org/wiki/Set) # The first command-line argument should be one of the following strings: # A_and_B intersection of sets A and B # A_or_B union of sets A and B # A_and_not_B relative complement of B in A (elements in A but not in B) # B_and_not_A relative complement of A in B (elements in B but not in A) # The second and third command-line arguments should be the names of files # containing the data for the sets A and B respectively. # These files should have one data-element per line. # Leading and trailing whitespace on each line will be ignored. # Empty lines in the files will be ignored. # # Cameron Hayne (macdev@hayne.net) December 2006 use strict; use warnings; my $scriptname = "setOperation"; die "Usage: $scriptname operation fileA fileB\n" unless scalar(@ARGV) == 3; # Function declarations sub createHash($); sub printHashKeys($); sub A_and_B($$); sub A_or_B($$); sub A_and_not_B($$); sub B_and_not_A($$); my %operations = ( 'A_and_B' => \&A_and_B, 'A_or_B' => \&A_or_B, 'A_and_not_B' => \&A_and_not_B,, 'B_and_not_A' => \&B_and_not_A,, ); my $operation = shift @ARGV; unless ($operations{$operation}) { my $availOps = join(", ", sort keys %operations); die "Invalid operation ($operation)\nAvailable operations: $availOps\n"; } my $fileA = shift @ARGV; die "No such file ($fileA)\n" unless -e $fileA; my $fileB = shift @ARGV; die "No such file ($fileB)\n" unless -e $fileB; my $hashRefA = createHash($fileA); my $hashRefB = createHash($fileB); my $sub = $operations{$operation}; my $result = &$sub($hashRefA, $hashRefB); printHashKeys($result); exit; # -------------------- # Functions # -------------------- sub createHash($) { my ($filepath) = @_; my %result = (); open(FILE, "<$filepath") or die "Can't open file \"filepath\": $!\n"; while () { chomp; s/^\s+//; # remove leading whitespace s/\s+$//; # remove trailing whitespace $result{$_} = 1 unless $_ eq ""; } close(FILE); return \%result; } sub printHashKeys($) { my ($hashRef) = @_; foreach my $key (sort keys %$hashRef) { print "$key\n"; } } sub A_and_B($$) { my ($hashRefA, $hashRefB) = @_; my %result = (); foreach my $key (keys %$hashRefA) { $result{$key} = 1 if exists $hashRefB->{$key}; } return \%result; } sub A_or_B($$) { my ($hashRefA, $hashRefB) = @_; my %result = (); foreach my $key (keys %$hashRefA) { $result{$key} = 1; } foreach my $key (keys %$hashRefB) { $result{$key} = 1; } return \%result; } sub A_and_not_B($$) { my ($hashRefA, $hashRefB) = @_; my %result = (); foreach my $key (keys %$hashRefA) { $result{$key} = 1 unless exists $hashRefB->{$key}; } return \%result; } sub B_and_not_A($$) { my ($hashRefA, $hashRefB) = @_; my %result = (); foreach my $key (keys %$hashRefB) { $result{$key} = 1 unless exists $hashRefA->{$key}; } return \%result; }