A friend was reviewing precalculus (in preparation to return to school after a decade off and place into a real math class), and was working through some maxtrix determinant problems. I wrote this to help her catch arithmetic errors when calculating minors of a larger matrix. I only spent about 15 minutes, so its kind of rough, but I'm pretty satisfied, especially with how the input code handles
errors.
#!/usr/bin/perl
use strict;
use warnings;
sub getmatrix {
my $m = [];
my $cols;
rand()<.85 ? print "Enter matrix:\n" : print "tell me your matrix
+and I'll tell you no lies:\n";
while (!$cols || @$m != $cols) {
# print "enter row:\n";
my @row = split ' ', <>;
if (@row < 2 || $cols && @row != $cols || grep /.\D|^[^\d-]/s,
+ @row) {
print "try that row again:\n";
@row = split ' ', <>;
goto &getmatrix
if @row < 2 || $cols && @row != $cols || grep /.\D|^[^
+\d-]/s, @row;
}
$cols ||= @row;
push @$m, \@row;
}
# use Data::Dumper;
# print Dumper $m;
$m;
}
sub determine {
my $m = shift;
my $det = 0;
if (@$m == 2) {
$det = $m->[0][0] * $m->[1][1] - $m->[0][1] * $m->[1][0];
} else {
my @subm = map [@$_[1..$#$_]], @$m;
for (0..$#$m) {
if ($_ & 1) {
$det -= $m->[$_][0] * determine([@subm[0..$_-1,$_+1..$#subm]])
+;
} else {
$det += $m->[$_][0] * determine([@subm[0..$_-1,$_+1..$
+#subm]]);
}
}
}
$det
}
while (1) {
my $m = getmatrix();
my $det = determine($m) || (rand()<.333 ? 0 : rand() < .5 ? 'zippo
+' : 'zilch');
print "got: $det\n";
}