http://qs321.pair.com?node_id=1068370

slinky773 has asked for the wisdom of the Perl Monks concerning the following question:

OK, here goes:

I'm making this final exam study guide program for my Geometry Honors class in perl as a command line script because I'm too lazy to figure out how to make a GUI. I was on Unit 3, which is logic. We had a lot of assignments where you had to use the chain rule and law of detachment (take all the contrapositives of the statements, basically) to take, say, 4 statements like '~c->~f', 'g->b', 'p->f', and 'c->~b' and you had to derive that ultimately 'p->~g' was the correct conclusion. So I typed this subroutine up in a module:

```sub LHCC {
DECISION: print "
Hi. This is the Lee-Hardy Conclusion Calculator.\n
Given a series of statements using the syntax\n
'p -> q', I will deduce the correct conclusion\n
to be made using basic logic and the chain rule.\n
Type 'quit' to exit the LHCC.\n\n";
my \$decision = <STDIN>;
chomp \$decision;
if(\$decision =~ /quit/i) {if(! &Unit3()) {return 0;}}
else {print "\nCould not interpret, try again.\n"; goto DECISION;}
print "\nHow many statements will be used?\n\n";
my \$NumberOfStatements = <STDIN>;
chomp \$NumberOfStatements;
if(\$NumberOfStatements !~ /^-?\d+\.?\d*\$/) {print "\nCould not int
+erpret, try again.\n"; goto DECISION;}
print "\nOnly a hypen will be accepted for 'not'.\n
BTW, with many statements with syntax p -> q, you can't\n
have duplicate q's. Sorry. Hey, I only had a week to make\n
this thing.\n\n";
print "Given the statements ";
my \$StatementNumber = 0;
my \$P = 0;
my \$Q = 0;
my %Statements = ();
for \$StatementNumber (1..\$NumberOfStatements)
{
if (\$StatementNumber != \$NumberOfStatements) {print "P\$Stateme
+ntNumber -> Q\$StatementNumber, ";}
elsif (\$StatementNumber == \$NumberOfStatements) {print "and P\$
+StatementNumber -> Q\$StatementNumber,\n\n";}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
for \$StatementNumber (1..(\$NumberOfStatements*2))
{
if(\$StatementNumber % 2 == 0)
{
my \$TrueStatementNumber = \$StatementNumber/2;
print "Q\$TrueStatementNumber = ";
\$Q = <STDIN>;
chomp \$Q;
if (! \$Q) {print "\nCould not interpret, try again\n"; got
+o DECISION;}
print "\n";
\$Statements{"Q\$TrueStatementNumber"} = \$Q;
}
elsif(\$StatementNumber % 2 != 0)
{
my \$TrueStatementNumber = int(\$StatementNumber/2) + 1;
print "P\$TrueStatementNumber = ";
\$P = <STDIN>;
chomp \$P;
if (! \$P) {print "\nCould not interpret, try again\n"; got
+o DECISION;}
print "\n";
\$Statements{"P\$TrueStatementNumber"} = \$P;
}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
my %Contrapositives = ();
for \$StatementNumber (1..\$NumberOfStatements)
{
\$Contrapositives{"P\$StatementNumber"} = \$Statements{"Q\$Stateme
+ntNumber"};
\$Contrapositives{"Q\$StatementNumber"} = \$Statements{"P\$Stateme
+ntNumber"};
}
my @ContrapositivesKeys = keys %Contrapositives;
for my \$Element (@ContrapositivesKeys)
{
my \$ToTildeOrNotToTilde = substr \$Contrapositives{\$Element}, 0
+, 1;
my \$RestOfStatement = substr \$Contrapositives{\$Element}, 1;
if(\$ToTildeOrNotToTilde eq '-')
{
\$Contrapositives{\$Element} = \$RestOfStatement;
}
elsif(\$ToTildeOrNotToTilde ne '-')
{
\$Contrapositives{\$Element} = "-" . \$Contrapositives{\$Eleme
+nt};
}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
@ContrapositivesKeys = keys %Contrapositives;
my @StatementsKeys = keys %Statements;
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"}} = \$Contraposit
+ives{"Q\$Element"};
delete \$Contrapositives{"Q\$Element"};
delete \$Contrapositives{"P\$Element"};
}
my @Conclusion = ();
my @OtherConclusion = ();
my \$KeyValueToCheck = 0;
my \$key = 0;
foreach \$KeyValueToCheck (keys %Statements)
{
if(!\$KeyValueToCheck) {die "Whut? Something weird just happene
+d.";}
my @PossibleConclusion = (\$KeyValueToCheck, \$Statements{\$KeyVa
+lueToCheck});
CHECKPOINT: foreach \$key (keys %Statements)
{
if(!\$key) {die "Whut? Something weird just happened.";}
if(\$key eq \$Statements{\$KeyValueToCheck})
{
push @PossibleConclusion, \$Statements{\$key};
\$KeyValueToCheck = \$key;
}
elsif(\$key ne \$Statements{\$KeyValueToCheck}) {}
else {die "Whut? Something weird just happened, you aren't
+ supposed to be able to see this. Run again and if the error persists
+, email me at yflee7\@students.d125.org.\n";}
}
foreach \$key (keys %Contrapositives)
{
if(\$key eq \$Statements{\$KeyValueToCheck})
{
push @PossibleConclusion, \$Statements{\$key};
\$KeyValueToCheck = \$key;
goto CHECKPOINT;
}
elsif(\$key ne \$Statements{\$KeyValueToCheck}) {}
else {die "Whut? Something weird just happened, you aren't
+ supposed to be able to see this. Run again and if the error persists
+, email me at yflee7\@students.d125.org.\n";}
}
if (scalar @PossibleConclusion > scalar @Conclusion) {@Conclus
+ion = @PossibleConclusion;}
elsif (scalar @PossibleConclusion == scalar @Conclusion) {@Oth
+erConclusion = @PossibleConclusion;}
elsif (scalar @PossibleConclusion < scalar @Conclusion) {}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
foreach \$KeyValueToCheck (keys %Contrapositives)
{
if(!\$KeyValueToCheck) {die "Whut? Something weird just happene
+d.";}
my @PossibleConclusion = (\$KeyValueToCheck, \$Statements{\$KeyVa
+lueToCheck});
CHECKPOINT2: foreach \$key (keys %Statements)
{
if(\$key eq \$Contrapositives{\$KeyValueToCheck})
{
if(!\$key) {die "Whut? Something weird just happened.";
+}
push @PossibleConclusion, \$Statements{\$key};
\$KeyValueToCheck = \$key;
}
elsif(\$key ne \$Contrapositives{\$KeyValueToCheck}) {}
else {die "Whut? Something weird just happened, you aren't
+ supposed to be able to see this. Run again and if the error persists
+, email me at yflee7\@students.d125.org.\n";}
}
foreach \$key (keys %Contrapositives)
{
if(\$key eq \$Contrapositives{\$KeyValueToCheck})
{
if(!\$key) {die "Whut? Something weird just happened.";
+}
push @PossibleConclusion, \$Statements{\$key};
\$KeyValueToCheck = \$key;
goto CHECKPOINT2;
}
elsif(\$key ne \$Contrapositives{\$KeyValueToCheck}) {}
else {die "Whut? Something weird just happened, you aren't
+ supposed to be able to see this. Run again and if the error persists
+, email me at yflee7\@students.d125.org.\n";}
}
if (scalar @PossibleConclusion > scalar @Conclusion) {@Conclus
+ion = @PossibleConclusion;}
elsif (scalar @PossibleConclusion == scalar @Conclusion) {@Oth
+erConclusion = @PossibleConclusion;}
elsif (scalar @PossibleConclusion < scalar @Conclusion) {}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
foreach my \$ScalarNumber (0..((scalar @Conclusion)-1))
{
if (\$ScalarNumber != scalar @Conclusion) {print "\$Conclusion[\$
+ScalarNumber] => ";}
elsif (\$ScalarNumber == scalar @Conclusion) {print "\$Conclusio
+n[\$ScalarNumber]";}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
print "\n\nor \n\n";
foreach my \$ScalarNumber (0..((scalar @OtherConclusion)-1))
{
if (\$ScalarNumber != (scalar @OtherConclusion)-1) {print "\$Oth
+erConclusion[\$ScalarNumber] => ";}
elsif (\$ScalarNumber == (scalar @OtherConclusion)-1) {print "\$
+OtherConclusion[\$ScalarNumber]";}
else {die "Whut? Something weird just happened, you aren't sup
+posed to be able to see this. Run again and if the error persists, em
+ail me at yflee7\@students.d125.org.\n";}
}
print "\n\nIn other words, " . \$Conclusion[0] . " => " . \$Conclusi
+on[(scalar @Conclusion)-1] . " or " . \$OtherConclusion[0] . " => " .
+\$OtherConclusion[(scalar @Conclusion)-1] . "\n";
goto DECISION;
}

It's a lot of foreach \$scalar (keys %Hash) sort of stuff, but that's the best way I could think of to do this. However, every time I run it, I always get an error akin to this:

```Use of uninitialized value in print at Unit3.pm line 142, <STDIN> line
+ 12.
Use of uninitialized value in string eq at Unit3.pm line 144, <STDIN>
+line 12.
Use of uninitialized value in string ne at Unit3.pm line 149, <STDIN>
+line 12.
Use of uninitialized value in print at Unit3.pm line 142, <STDIN> line
+ 12.
Use of uninitialized value in string eq at Unit3.pm line 144, <STDIN>
+line 12.
Use of uninitialized value in string ne at Unit3.pm line 149, <STDIN>
+line 12.

and that generally drags on for, say, 75 lines or so. The errors start around when my CHECKPOINT label shows up. Every time I try something and I think I've fixed it, this always changes a tiny bit, but still shows up. To make matters worse, it doesn't even work at the end:

```Use of uninitialized value \$Conclusion[2] in concatenation (.) or stri
+ng at Unit3.pm line 203, <STDIN> line 12.
c => -b =>  =>

or

Use of uninitialized value \$OtherConclusion[1] in concatenation (.) or
+ string at Unit3.pm line 210, <STDIN> line 12.
Use of uninitialized value \$Conclusion[2] in concatenation (.) or stri
+ng at Unit3.pm line 214, <STDIN> line 12.
f =>  => -b

In other words, c =>  or f => -b