線形方程式系を解く


12

一連の線形方程式をできるだけ短く解決するプログラムを記述します。任意の数の方程式の問題を解く必要があります。それらは好きなように入力できますが、拡張行列の係数がおそらく最も簡単です。プログラムは、整数以外の係数やソリューションを処理する必要はありません。退化したケースや無効なケースはテストされません。プログラムは、各変数の値または縮小された行の階層形式を出力する必要があります。

方程式解法ライブラリ、行列関数、または自動解法は許可されていません。配列またはリストを使用して行列をシミュレートできます。

入力例(または同等のもの):

m={{2,1,-1,8},{-3,-1,2,-11},{-2,1,2,-3}}

これは 2x+y-z=8, -3x-y+2z=-11, -2x+y+2z=-3

出力例(または同等のもの):

{2,3,-1}

これは x=2, y=3, z=-1


2
変数の係数と定数項を入力で2つの配列に分離できますか?
user12205 2014年

@aceはい、それで結構です
qwr 2014年

1
縮退したケースで正確に何を言っているのですか?あなたはそれらすべてのケースを参照していると思います:1)不正な入力; 2)0x=0またはのようなもの0x=5; 4)方程式の数が変数の数と異なる場合。5)のような矛盾するケースx+5y=7, x+5y=8; 6)のような線形独立性のないケースx+3y=6, 2x+6y=12。私は正しいですか?
Victor Stafusa 2014年

@Victorはい、すべてのあいまいさがある、または解決できない入力。
qwr 2014年

退化していないが悪条件であるケースについてはどうですか?(または、言い換えれば、どのようなピボットが必要ですか?)
Peter Taylor

回答:


3

Pythonの169 166

実装

def s(a):
 if a:b=a[0];r=s([[x-1.*y*b[0]/r[0]for x,y in zip(b[1:],r[1:])]for r in a[1:]]);return[round((b[-1]-sum(x*y for x,y in zip(b[1:-1],r)))/b[0])]+r
 return[]

デモ

>>> arr=[[2, 1, -1, 8], [-3, -1, 2, -11], [-2, 1, 2, -3]]
>>> s(arr)
[2.0, 3.0, -1.0]

注意

float近似に問題がない場合は、ラウンド関数呼び出しを削除して、159文字までゴルフできます。


9

APL、1文字

(改訂された)要件に適合しないことはわかっていますが、投稿しないのは良いことです。

シンボル「ドミノ」÷長方形内の除算)は行列除算を実行するため、線形方程式の任意のシステムを解くことができます。定数項のベクトルと他の項の行列の間に置くだけです。

      8 ¯11 ¯3 ⌹ ⊃(2 1 ¯1)(¯3 ¯1 2)(¯2 1 2)
2 3 ¯1

(TryAplで試してみたい場合は、


4

Javascript(284 181)- ガウス消去法

function f(A){l=A.length;d=1;for(i=0;i+1;i+=d){v=A[i][i];for(k=0;k<l+1;k++)A[i][k]/=v;for(j=i+d;A[j];j+=d)for(k=0,w=A[j][i];k<l+1;k++)A[j][k]-=w*A[i][k];if(i==l-d)d=-1,i=l}return A}

テスト

f([[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]);

=> [[1,0,0,2],[0,1,0,3],[-0,-0,1,-1]]

返される配列は、単位行列と解を組み合わせたものです。


さらに数文字を保存できます。
MarcinJuraszek 2014年

l=A.length;for(i=0;i<l;i++)使用する代わりにfor(i=0;i<l=A.length;i++)
Victor Stafusa 2014年

for(i=l-1;i>=0;i--)使用する代わりにfor(i=l;--i;)
Victor Stafusa 2014年

に移動w=A[j][i]for()てスキップすることもでき{}ます。
MarcinJuraszek 2014年

皆さんに感謝します。順方向と逆方向の手順を1つの手順でマージし、100文字を節約できました。また、ヒントのいくつかは無効になっています。(@MarcinJuraszekのヒントを除く)
Michael M.

3

この回答は、マトリックス関数を使用しているため、ルール変更後の質問には適合しません。*

セージ、32

~matrix(input())*vector(input())

入力例:

[[2, 1, -1], [-3, -1, 2], [-2, 1, 2]]
[8, -11, -3]

出力例:

(2, 3, -1)

*おそらく、matrix()型キャストではなく、機能(ランニングはimport types; isinstance(matrix, types.FunctionType)できますFalse)。また、~and *は関数ではなく演算子です。


ルールを更新しました。コードは異なる数の方程式を処理する必要があり、行列関数を使用できなくなります。
qwr 2014年

3

Javaの- 522の 434 228 213文字

機能するものが見つかるまで、直接乗算によってすべての可能な整数nタプルを体系的にチェックして解決します。

関数は、拡張行列A、試行解ベクトルx、および次元nを入力として取り、解ベクトルxを出力します。ベクトルxは実際には次元よりも1大きいことに注意してください。(変数A、x、n、j、k、sをインスタンス変数として宣言した場合、関数は31文字短くなります-合計で182ですが、これは規則を曲げすぎているように感じます。)

int[]Z(int[][]A,int[]x,int n){int j,k,s;for(;;){for(j=0;j<n;j++){for(k=s=0;k<n;s+=A[j][k]*x[k++]);if(s!=A[j][n])j+=n;}if(j==n)return x;for(j=0;j<=n;j++)if(x[j]!=x[n]||j==n){x[j]++;for(k=0;k<j;x[k++]=-x[n]);j=n;}}}

テスト用プログラム(やや手に負えない):

import java.util.*;
class MatrixSolver{
    public MatrixSolver() {
        Scanner p=new Scanner(System.in); //initialize everything from stdin
        int j,k,n=p.nextInt(),A[][]=new int[n][n+1],x[]=new int[n+1];
        for(j=0;j<n;j++)for(k=0;k<=n;A[j][k++]=p.nextInt());
        x=Z(A,x,n); //call the magic function
        for(j=0;j<n;j++) System.out.print(x[j]+" "); //print the output
    }
    public static void main(String[]args){
        new MatrixSolver();
    } 

    int[]Z(int[][]A,int[]x,int n){
        int j,k,s;
        for(;;){
            for(j=0;j<n;j++){ //multiply each row of matrix by trial solution and check to see if it is correct
                for(k=s=0;k<n;s+=A[j][k]*x[k++]);
                if(s!=A[j][n])j+=n;
            }
            if(j==n)return x; //if it is correct return the trial solution
            for(j=0;j<=n;j++)if(x[j]!=x[n]||j==n){//calculate the next trial solution
                x[j]++;
                for(k=0;k<j;x[k++]=-x[n]);
                j=n;
            }
        }
    }
}

プログラムは、次のように、スペースで区切られた整数としてstdinから入力を受け取ります。最初に、問題の次元、2番目に、行ごとの拡張行列のエントリ。

サンプルの実行:

$java -jar MatrixSolver.jar
3 2 1 -1 8 -3 -1 2 -11 -2 1 2 -3
2 3 -1 

ループと「パブリック」に関するビクターのアドバイスに従い、RHSを個別ではなく拡張マトリックスに保存し、トライアルソリューションにエントリを追加して新しいトライアルソリューションの生成を簡略化することで、いくつかのキャラクターを剃りました。OPは、関数で十分であると述べました-プログラム全体を数える必要はありません。


while(true){f=0;for(j=0;j<n;j++)で置き換えることができますwhile(true){for(f=j=0;j<n;j++)。さらに、クラスを公開する必要はありません。本文に1つの命令しかないforループでは、中括弧は必要ありません。
Victor Stafusa 2014年

私はそれfor(j=0;j<n;j++){for(k=0;k<n;k++){A[j][k]=p.nextInt();}b[j]=p.nextInt();}を置き換えることができると思いますfor(j=0;j<n;b[j++]=p.nextInt())for(k=0;k<n;)A[j][k++]=p.nextInt();
Victor Stafusa 14年

@Victorおかげで、私はそれらとその他の変更を行いました。
Wally

while(true)変更可能for(;;)
user12205

@ace thanks-それといくつか他のものを変更し、15文字を削った。
Wally

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.