use strict; use warnings; if (!@ARGV) { print < q" I will deduce the correct conclusion to be made using basic logic and the chain rule. - may be used for negation q's can not be duplicated HELP exit; } LHCC(parse(@ARGV)); sub LHCC { my (%statements) = @_; my \$NumberOfStatements = keys (%statements) / 2; my %Contrapositives; for my \$StatementNumber (1 .. \$NumberOfStatements) { \$Contrapositives{"P\$StatementNumber"} = \$statements{"Q\$StatementNumber"}; \$Contrapositives{"Q\$StatementNumber"} = \$statements{"P\$StatementNumber"}; } for my \$Element (keys %Contrapositives) { if ('-' eq substr \$Contrapositives{\$Element}, 0, 1) { \$Contrapositives{\$Element} = substr \$Contrapositives{\$Element}, 1; } else { \$Contrapositives{\$Element} = "-\$Contrapositives{\$Element}"; } } for my \$Element (1 .. \$NumberOfStatements) { \$statements{\$statements{"P\$Element"}} = \$statements{"Q\$Element"}; delete \$statements{"Q\$Element"}; delete \$statements{"P\$Element"}; } for my \$Element (1 .. \$NumberOfStatements) { \$Contrapositives{\$Contrapositives{"P\$Element"}} = \$Contrapositives{"Q\$Element"}; delete \$Contrapositives{"Q\$Element"}; delete \$Contrapositives{"P\$Element"}; } my @Conclusion; my @OtherConclusion; foreach my \$checkKey (keys %statements) { my @PossibleConclusion = (\$checkKey, \$statements{\$checkKey}); CHECKPOINT: foreach my \$key (keys %statements) { if (exists \$statements{\$checkKey} && \$key eq \$statements{\$checkKey}) { die "No statement \$key" if ! exists \$statements{\$key}; push @PossibleConclusion, \$statements{\$key}; \$checkKey = \$key; } } foreach my \$key (keys %Contrapositives) { if (exists \$statements{\$checkKey} && \$key eq \$statements{\$checkKey}) { die "No statement \$key" if ! exists \$statements{\$key}; push @PossibleConclusion, \$statements{\$key}; \$checkKey = \$key; goto CHECKPOINT; } } if (scalar @PossibleConclusion > scalar @Conclusion) { @Conclusion = @PossibleConclusion; } elsif (scalar @PossibleConclusion == scalar @Conclusion) { @OtherConclusion = @PossibleConclusion; } } foreach my \$checkKey (keys %Contrapositives) { die "No statement \$checkKey" if ! exists \$statements{\$checkKey}; my @PossibleConclusion = (\$checkKey, \$statements{\$checkKey}); CHECKPOINT2: foreach my \$key (keys %statements) { next if \$key ne \$Contrapositives{\$checkKey}; die "No statement \$key" if ! exists \$statements{\$key}; push @PossibleConclusion, \$statements{\$key}; \$checkKey = \$key; } foreach my \$key (keys %Contrapositives) { next if \$key ne \$Contrapositives{\$checkKey}; die "No statement \$key" if ! exists \$statements{\$key}; push @PossibleConclusion, \$statements{\$key}; \$checkKey = \$key; goto CHECKPOINT2; } if (scalar @PossibleConclusion > scalar @Conclusion) { @Conclusion = @PossibleConclusion; } elsif (scalar @PossibleConclusion == scalar @Conclusion) { @OtherConclusion = @PossibleConclusion; } } print join ' => ', @Conclusion; print "\n\nor \n\n"; print join ' => ', @OtherConclusion; print < \$Conclusion[(scalar @Conclusion) - 1] or \$OtherConclusion[0] => \$OtherConclusion[(scalar @Conclusion) - 1] RESULT } sub parse { my %statements; my \$n = 1; for my \$statement (@_) { my (\$p, \$q) = \$statement =~ /(\S+)\s*->\s*(\S+)/; \$statements{"P\$n"} = \$p; \$statements{"Q\$n"} = \$q; ++\$n; } return %statements; }