Bir Doğrusal Denklem Sistemini Çözme


12

Mümkün olduğunca kısa bir dizi doğrusal denklemi çözmek için bir program yazın. Rasgele sayıdaki denklem problemlerini çözmelidir. İstediğiniz gibi girebilirler, artırılmış matris katsayıları muhtemelen en kolayıdır. Program, tamsayı olmayan katsayıları veya çözümleri işlemek zorunda değildir. Hiçbir dejenere veya geçersiz vaka test edilmeyecektir. Program, her değişkenin veya azaltılmış satır kademeli formunun değerini çıktılamalıdır.

Hiçbir denklem çözme kütüphanesi, matris fonksiyonu veya herhangi bir şekilde otomatik olarak çözmeye izin verilmez. Dizileri veya listeleri içeren matrisleri simüle edebilirsiniz.

Örnek giriş (veya eşdeğeri):

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

Bu temsil eder 2x+y-z=8, -3x-y+2z=-11, -2x+y+2z=-3

Örnek çıktı (veya eşdeğeri):

{2,3,-1}

Bu temsil eder x=2, y=3, z=-1


2
Girdilerde değişkenlerin katsayıları ve sabit terimler iki diziye ayrılabilir mi?
user12205

@ace evet, sorun değil
qwr

1
Dejenere vakalarla tam olarak ne diyorsun? Sanırım tüm bu vakalara atıfta bulunuyorsunuz: 1) Hatalı biçimlendirilmiş girdi; 2) 0x=0veya gibi şeyler 0x=5; 4) Denklem sayısının değişken sayısından farklı olduğu durumlar; 5) Çelişkili durumlar x+5y=7, x+5y=8; 6) Doğrusal bağımsızlığı olmayan vakalar x+3y=6, 2x+6y=12. Haklı mıyım?
Victor Stafusa

@Victor Evet, herhangi bir belirsizliği olan veya çözülemeyen girdiler.
qwr

Dejenere olmayan, ancak şartlı olmayan vakalara ne olacak? (Ya da başka bir deyişle, ne tür bir dönme gerekir?)
Peter Taylor

Yanıtlar:


3

Python 169 166

uygulama

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[]

gösteri

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

Not

Şamandıra yaklaşımı ile tamamsanız, yuvarlak işlev çağrısını kaldırabilir ve 159 karaktere kadar golf oynayabilirsiniz.


9

APL, 1 karakter

(Revize edilmiş) gereksinimlere uymadığını biliyorum, ancak yayınlamamak için çok iyi:

Sembol "domino" ( ÷bir dikdörtgen içindeki bölüm ) matris bölünmesi gerçekleştirir, bu nedenle herhangi bir doğrusal denklem sistemini çözebilir. Sadece sabit terim vektörü ve diğer terimlerle matris arasına koymanız gerekir:

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

(TryApl üzerinde denemek istiyorsanız, is )


4

Javascript ( 284181 ) - Gauss Eliminasyon yöntemi

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}

Ölçek

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]]

Döndürülen dizi, kimlik matrisini ve çözümü birleştirir.


Birkaç karakter daha kaydedebilirsiniz.
MarcinJuraszek

Yerine l=A.length;for(i=0;i<l;i++)kullanımı for(i=0;i<l=A.length;i++).
Victor Stafusa

Yerine for(i=l-1;i>=0;i--)kullanımı for(i=l;--i;).
Victor Stafusa

Ayrıca içeri w=A[j][i]girip for()atlayabilirsiniz {}.
MarcinJuraszek

Herkese teşekkürler, ileri ve geri adımları tek bir adımda birleştirmeyi başardım, yüz karakter kaydettim ve ipuçlarınızdan bazıları artık geçerli değil. (@MarcinJuraszek bahşiş hariç)
Michael

3

Bu yanıt kural değişikliği sonrasında bir matris işlevi kullandığından artık soruya uymuyor. *

Adaçayı , 32

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

Örnek giriş:

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

Örnek çıktı:

(2, 3, -1)

* Muhtemelen, matrix()bir typecast değil, bir fonksiyon (çalışır durumda import types; isinstance(matrix, types.FunctionType)verir False). Ayrıca, ~ve *olan operatörler , değil işlev görür.


Kuralları güncelledim. Kod farklı sayıda denklemi işlemelidir ve artık matris fonksiyonlarını kullanamazsınız.
qwr

3

Java - 522 434 228 213 karakter

Çalışır bir tane bulunana kadar olası tüm tamsayı n-tuples'lerini doğrudan çarparak sistematik olarak kontrol ederek çözer.

Fonksiyon artırılmış matris, A, deneme solüsyonu vektörü, x ve boyut, n, girdi - çıktılar solüsyon vektörü, x olarak alınır. X vektörünün aslında olası çözümlere adım atmaya yardımcı olmak için boyuttan daha büyük olduğunu unutmayın. (A, x, n, j, k, s değişkenlerini örnek değişkenler olarak bildirirsem, işlev 31 karakter daha kısa olurdu - toplam 182 için, ancak bu kuralların çok fazla bükülmesi gibi geliyor.)

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;}}}

Test programı (biraz ungolfed):

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;
            }
        }
    }
}

Program stdin'den boşlukla ayrılmış tamsayılar olarak girdi alır: birincisi, problemin boyutu, ikincisi, artırılmış matrisin satır satır girişleri.

Örnek çalışma:

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

Victor'un döngüler ve "herkese açık" hakkındaki tavsiyelerini izleyerek, RHS'yi ayrı olarak değil artırılmış matriste saklayarak ve her yeni deneme çözümünün oluşturulmasını basitleştirmek için deneme çözümüme ekstra bir giriş ekleyerek birkaç karakter traş ettim. OP ayrıca bir fonksiyonun yeterli olduğunu söyledi - tüm programı saymaya gerek yok.


while(true){f=0;for(j=0;j<n;j++)ile değiştirilebilir while(true){for(f=j=0;j<n;j++). Dahası, sınıfınızın halka açık olması gerekmez. Vücutta sadece bir talimat içeren döngüler, kıvırcık parantezlere ihtiyaç duymaz.
Victor Stafusa

Bence bu for(j=0;j<n;j++){for(k=0;k<n;k++){A[j][k]=p.nextInt();}b[j]=p.nextInt();}değiştirilebilirfor(j=0;j<n;b[j++]=p.nextInt())for(k=0;k<n;)A[j][k++]=p.nextInt();
Victor Stafusa

@Victor Teşekkürler, bunları ve diğer değişiklikleri yaptım.
Wally

while(true)değiştirilebilirfor(;;)
user12205

@ace teşekkürler - bunu ve birkaç şey değiştirdi ve 15 karakter traş.
Wally

1

JavaScript (ES6),  152  151 bayt

Cramer kuralının uygulanması .

(m)(v)Nereden girdi alır?mv

m=>v=>m.map((_,i)=>(D=m=>m+m?m.reduce((s,[v],i)=>s+(i&1?-v:v)*D(m.map(([,...r])=>r).filter(_=>i--)),0):1)(m.map((r,y)=>r.map((k,x)=>x-i?k:v[y])))/D(m))

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.