Розв’яжіть систему лінійних рівнянь


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
Чи можна розділити коефіцієнти змінних та постійні доданки на два масиви на вході?
користувач12205

@ace так, це добре
qwr

1
Що саме ви говорите за виродженими випадками? Я думаю, що ви посилаєтесь на всі ці випадки: 1) неправильне введення даних; 2) Такі речі, як 0x=0або 0x=5; 4) випадки, коли кількість рівнянь різна, ніж кількість змінних; 5) суперечливі випадки типу x+5y=7, x+5y=8; 6) Справи без лінійної незалежності, як x+3y=6, 2x+6y=12. Чи правий я?
Віктор Стафуса

@Victor Так, будь-який вхід, який має якусь неоднозначність або не вирішується.
qwr

А як щодо випадків, які не вироджуються, але є поганими умовами? (Або, інакше кажучи, який тип повороту потрібно?)
Пітер Тейлор

Відповіді:


3

Пітон 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]

Примітка

Якщо ви добре з наближенням поплавця, тоді ви можете видалити виклик функції кругової функції та подати гольф до 159 символів


9

APL, 1 char

Я знаю, що він не відповідає (переглянутим) вимогам, але це занадто добре, щоб не публікувати:

Символ "доміно" (ділення ÷всередині прямокутника) виконує матричний поділ, тому може вирішити будь-яку систему лінійних рівнянь. Вам просто потрібно поставити його між вектором постійного терміна та матрицею з іншими членами:

      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

Замість l=A.length;for(i=0;i<l;i++)використання for(i=0;i<l=A.length;i++).
Віктор Стафуса

Замість for(i=l-1;i>=0;i--)використання for(i=l;--i;).
Віктор Стафуса

Ви також можете перейти w=A[j][i]в for()і пропустити {}навколо.
MarcinJuraszek

Дякую всім, мені вдалося об'єднати кроки вперед та назад за один крок, заощадивши сто символів, а деякі ваші поради вже не дійсні. (крім @MarcinJuraszek tip)
Майкл М.

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). Також оператори~ і *є операторами , а не функціями.


Я оновив правила. Код повинен обробляти різну кількість рівнянь, і тепер ви не можете використовувати матричні функції.
qwr

3

Ява - 522 434 228 213 символів

Вирішує шляхом систематичної перевірки всіх можливих цілих n-кортежів шляхом прямого множення, поки не буде знайдено, що працює.

Функція приймає доповнену матрицю, A, вектор пробного рішення, x і розмірність, n, як вхід - виводить вектор рішення, x. Зауважте, що вектор x насправді на один більший, ніж розмірність, щоб допомогти перейти до можливих рішень. (Якби я оголосив змінні 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 як цілі числа, розділені пробілом, так: по-перше, розмірність задачі, по-друге, записи доповненої матриці за рядками.

Проба зразка:

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

Я поголив декількох персонажів, дотримуючись порад Віктора щодо циклів і "загальнодоступних", зберігаючи RHS в доповненій матриці замість окремо, і додав додатковий запис до мого пробного рішення, щоб спростити генерацію кожного нового пробного рішення. ОП також сказала, що функції достатньо - не потрібно рахувати всю програму.


while(true){f=0;for(j=0;j<n;j++)можна замінити на while(true){for(f=j=0;j<n;j++). Далі ваш клас не повинен бути публічним. Для петель із лише однією інструкцією на тілі не потрібні фігурні дужки.
Віктор Стафуса

Я думаю, що 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 Спасибі, я вніс ці та інші зміни.
Уоллі

while(true)можна змінити наfor(;;)
user12205

@ace спасибі - змінив те і ще пару речей і поголив 15 символів.
Уоллі

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.