Cramer's rule: Difference between revisions

Rename Perl 6 -> Raku, alphabetize, minor clean-up
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
Line 288:
-4.000
1.000</pre>
 
=={{header|C sharp}}==
Instead of copying a bunch of arrays, I made a class with an indexer that simply accesses the correct items in the original matrix.
<lang csharp>using System;
using System.Collections.Generic;
using static System.Linq.Enumerable;
 
public static class CramersRule
{
public static void Main() {
var equations = new [] {
new [] { 2, -1, 5, 1, -3 },
new [] { 3, 2, 2, -6, -32 },
new [] { 1, 3, 3, -1, -47 },
new [] { 5, -2, -3, 3, 49 }
};
var solution = SolveCramer(equations);
Console.WriteLine(solution.DelimitWith(", "));
}
 
public static int[] SolveCramer(int[][] equations) {
int size = equations.Length;
if (equations.Any(eq => eq.Length != size + 1)) throw new ArgumentException($"Each equation must have {size+1} terms.");
int[,] matrix = new int[size, size];
int[] column = new int[size];
for (int r = 0; r < size; r++) {
column[r] = equations[r][size];
for (int c = 0; c < size; c++) {
matrix[r, c] = equations[r][c];
}
}
return Solve(new SubMatrix(matrix, column));
}
 
private static int[] Solve(SubMatrix matrix) {
int det = matrix.Det();
if (det == 0) throw new ArgumentException("The determinant is zero.");
 
int[] answer = new int[matrix.Size];
for (int i = 0; i < matrix.Size; i++) {
matrix.ColumnIndex = i;
answer[i] = matrix.Det() / det;
}
return answer;
}
 
//Extension method from library.
static string DelimitWith<T>(this IEnumerable<T> source, string separator = " ") =>
string.Join(separator ?? " ", source ?? Empty<T>());
 
private class SubMatrix
{
private int[,] source;
private SubMatrix prev;
private int[] replaceColumn;
 
public SubMatrix(int[,] source, int[] replaceColumn) {
this.source = source;
this.replaceColumn = replaceColumn;
this.prev = null;
this.ColumnIndex = -1;
Size = replaceColumn.Length;
}
 
private SubMatrix(SubMatrix prev, int deletedColumnIndex = -1) {
this.source = null;
this.prev = prev;
this.ColumnIndex = deletedColumnIndex;
Size = prev.Size - 1;
}
 
public int ColumnIndex { get; set; }
public int Size { get; }
 
public int this[int row, int column] {
get {
if (source != null) return column == ColumnIndex ? replaceColumn[row] : source[row, column];
return prev[row + 1, column < ColumnIndex ? column : column + 1];
}
}
 
public int Det() {
if (Size == 1) return this[0, 0];
if (Size == 2) return this[0, 0] * this[1, 1] - this[0, 1] * this[1, 0];
SubMatrix m = new SubMatrix(this);
int det = 0;
int sign = 1;
for (int c = 0; c < Size; c++) {
m.ColumnIndex = c;
int d = m.Det();
det += this[0, c] * d * sign;
sign = -sign;
}
return det;
}
 
public void Print() {
for (int r = 0; r < Size; r++) {
Console.WriteLine(Range(0, Size).Select(c => this[r, c]).DelimitWith(", "));
}
Console.WriteLine();
}
}
 
}</lang>
{{out}}
<pre>
2, -12, -4, 1
</pre>
 
=={{header|C++}}==
Line 430 ⟶ 539:
{{out}}
<pre>[2, -12, -4, 1]</pre>
 
=={{header|C sharp}}==
Instead of copying a bunch of arrays, I made a class with an indexer that simply accesses the correct items in the original matrix.
<lang csharp>using System;
using System.Collections.Generic;
using static System.Linq.Enumerable;
 
public static class CramersRule
{
public static void Main() {
var equations = new [] {
new [] { 2, -1, 5, 1, -3 },
new [] { 3, 2, 2, -6, -32 },
new [] { 1, 3, 3, -1, -47 },
new [] { 5, -2, -3, 3, 49 }
};
var solution = SolveCramer(equations);
Console.WriteLine(solution.DelimitWith(", "));
}
 
public static int[] SolveCramer(int[][] equations) {
int size = equations.Length;
if (equations.Any(eq => eq.Length != size + 1)) throw new ArgumentException($"Each equation must have {size+1} terms.");
int[,] matrix = new int[size, size];
int[] column = new int[size];
for (int r = 0; r < size; r++) {
column[r] = equations[r][size];
for (int c = 0; c < size; c++) {
matrix[r, c] = equations[r][c];
}
}
return Solve(new SubMatrix(matrix, column));
}
 
private static int[] Solve(SubMatrix matrix) {
int det = matrix.Det();
if (det == 0) throw new ArgumentException("The determinant is zero.");
 
int[] answer = new int[matrix.Size];
for (int i = 0; i < matrix.Size; i++) {
matrix.ColumnIndex = i;
answer[i] = matrix.Det() / det;
}
return answer;
}
 
//Extension method from library.
static string DelimitWith<T>(this IEnumerable<T> source, string separator = " ") =>
string.Join(separator ?? " ", source ?? Empty<T>());
 
private class SubMatrix
{
private int[,] source;
private SubMatrix prev;
private int[] replaceColumn;
 
public SubMatrix(int[,] source, int[] replaceColumn) {
this.source = source;
this.replaceColumn = replaceColumn;
this.prev = null;
this.ColumnIndex = -1;
Size = replaceColumn.Length;
}
 
private SubMatrix(SubMatrix prev, int deletedColumnIndex = -1) {
this.source = null;
this.prev = prev;
this.ColumnIndex = deletedColumnIndex;
Size = prev.Size - 1;
}
 
public int ColumnIndex { get; set; }
public int Size { get; }
 
public int this[int row, int column] {
get {
if (source != null) return column == ColumnIndex ? replaceColumn[row] : source[row, column];
return prev[row + 1, column < ColumnIndex ? column : column + 1];
}
}
 
public int Det() {
if (Size == 1) return this[0, 0];
if (Size == 2) return this[0, 0] * this[1, 1] - this[0, 1] * this[1, 0];
SubMatrix m = new SubMatrix(this);
int det = 0;
int sign = 1;
for (int c = 0; c < Size; c++) {
m.ColumnIndex = c;
int d = m.Det();
det += this[0, c] * d * sign;
sign = -sign;
}
return det;
}
 
public void Print() {
for (int r = 0; r < Size; r++) {
Console.WriteLine(Range(0, Size).Select(c => this[r, c]).DelimitWith(", "));
}
Console.WriteLine();
}
}
 
}</lang>
{{out}}
<pre>
2, -12, -4, 1
</pre>
 
=={{header|Common Lisp}}==
Line 1,725:
print "y = $y\n";
print "z = $z\n";</lang>
{{out}}
<pre>
w = 2
x = -12
y = -4
z = 1
</pre>
 
=={{header|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>
{{out}}
<pre>
Line 1,968 ⟶ 1,915:
 
<pre>'#(2 -12 -4 1)</pre>
 
=={{header|Raku}}==
(formerly 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>
{{out}}
<pre>
w = 2
x = -12
y = -4
z = 1
</pre>
 
=={{header|REXX}}==
10,333

edits