Cramer's rule: Difference between revisions

From Rosetta Code
Content added Content deleted
m (modified the task to solve for 4 unknown variables and updated the examples)
m (Added Perl)
Line 26: Line 26:


solve for <math>w</math>, <math>x</math>, <math>y</math> and <math>z</math>, using Cramer's rule.
solve for <math>w</math>, <math>x</math>, <math>y</math> and <math>z</math>, using Cramer's rule.

=={{header|Perl}}==
<lang perl>use Math::Matrix;

sub cramers_rule {
my ($A, $terms) = @_;
my @solutions;
my $det = $A->determinant;
foreach my $i (0 .. $#{$A}) {
my $Ai = $A->clone;
foreach my $j (0 .. $#{$terms}) {
$Ai->[$j][$i] = $terms->[$j];
}
push @solutions, $Ai->determinant / $det;
}
@solutions;
}

my $matrix = Math::Matrix->new(
[2, -1, 5, 1],
[3, 2, 2, -6],
[1, 3, 3, -1],
[5, -2, -3, 3],
);

my $free_terms = [-3, -32, -47, 49];
my ($w, $x, $y, $z) = cramers_rule($matrix, $free_terms);

print "w = $w\n";
print "x = $x\n";
print "y = $y\n";
print "z = $z\n";</lang>
{{out}}
<pre>
w = 2
x = -12
y = -4
z = 1
</pre>


=={{header|Perl 6}}==
=={{header|Perl 6}}==

Revision as of 16:24, 28 January 2016

Cramer's rule is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

In linear algebra, Cramer's rule is an explicit formula for the solution of a system of linear equations with as many equations as unknowns, valid whenever the system has a unique solution. It expresses the solution in terms of the determinants of the (square) coefficient matrix and of matrices obtained from it by replacing one column by the vector of right hand sides of the equations.


Given

which in matrix format is

Then the values of and can be found as follows:

Task

Given the following system of equations:

solve for , , and , using Cramer's rule.

Perl

<lang perl>use Math::Matrix;

sub cramers_rule {

   my ($A, $terms) = @_;
   my @solutions;
   my $det = $A->determinant;
   foreach my $i (0 .. $#{$A}) {
       my $Ai = $A->clone;
       foreach my $j (0 .. $#{$terms}) {
           $Ai->[$j][$i] = $terms->[$j];
       }
       push @solutions, $Ai->determinant / $det;
   }
   @solutions;

}

my $matrix = Math::Matrix->new(

   [2, -1,  5,  1],
   [3,  2,  2, -6],
   [1,  3,  3, -1],
   [5, -2, -3,  3],

);

my $free_terms = [-3, -32, -47, 49]; my ($w, $x, $y, $z) = cramers_rule($matrix, $free_terms);

print "w = $w\n"; print "x = $x\n"; print "y = $y\n"; print "z = $z\n";</lang>

Output:
w = 2
x = -12
y = -4
z = 1

Perl 6

<lang perl6>sub det(@matrix) {

   my @a = @matrix.map: { [|$_] };
   my $sign = +1;
   my $pivot = 1;
   for ^@a -> $k {
     my @r = ($k+1 .. @a.end);
     my $previous-pivot = $pivot;
     if 0 == ($pivot = @a[$k][$k]) {
       (my $s = @r.first: { @a[$_][$k] != 0 }) // return 0;
       (@a[$s],@a[$k]) = (@a[$k], @a[$s]);
       my $pivot = @a[$k][$k];
       $sign = -$sign;
     }
     for @r X @r -> ($i, $j) {
       ((@a[$i][$j] *= $pivot) -= @a[$i][$k]*@a[$k][$j]) /= $previous-pivot;
     }
   }
   $sign * $pivot

}

sub cramers_rule(@A, @terms) {

   gather for ^@A -> $i {
       my @Ai = @A.map: { [|$_] };
       for ^@terms -> $j {
           @Ai[$j][$i] = @terms[$j];
       }
       take det(@Ai);
   } »/» det(@A);

}

my @matrix = (

   [2, -1,  5,  1],
   [3,  2,  2, -6],
   [1,  3,  3, -1],
   [5, -2, -3,  3],

);

my @free_terms = (-3, -32, -47, 49); my ($w, $x, $y, $z) = |cramers_rule(@matrix, @free_terms);

say "w = $w"; say "x = $x"; say "y = $y"; say "z = $z";</lang>

Output:
w = 2
x = -12
y = -4
z = 1

Sidef

<lang ruby>func det(a) {

   a = a.map{.map{_}}
   var sign = +1
   var pivot = 1
   a.range.each { |k|
     var r = (k+1 .. a.end)
     var previous_pivot = pivot
     if ((pivot = a[k][k]) == 0) {
       a.swap(r.first_by {|i| a[i][k] != 0 } \\ (return 0), k)
       pivot = a[k][k]
       sign = -sign
     }
     r ~X r -> each { |p|
       var(i, j) = p...
       ((a[i][j] *= pivot) -= a[i][k]*a[k][j]) /= previous_pivot
     }
   }
   sign * pivot

}

func cramers_rule(A, terms) {

   gather {
       A.each_index { |i|
           var Ai = A.map{.map{_}}
           terms.each_index { |j|
               Ai[j][i] = terms[j]
           }
           take(det(Ai))
       }
   } »/» det(A)

}

var matrix = [

   [2, -1,  5,  1],
   [3,  2,  2, -6],
   [1,  3,  3, -1],
   [5, -2, -3,  3],

]

var free_terms = [-3, -32, -47, 49] var (w, x, y, z) = cramers_rule(matrix, free_terms)...;

say "w = #{w}" say "x = #{x}" say "y = #{y}" say "z = #{z}"</lang>

Output:
w = 2
x = -12
y = -4
z = 1