Решить систему линейных уравнений


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
Можно ли разделить коэффициенты переменных и постоянных членов на два массива на входе?
user12205

@ да, это нормально
14:08

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

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]

Запись

Если у вас все в порядке с приближением с плавающей точкой, вы можете убрать вызов функции раунда и еще один гольф до 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

Вместо 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 чаевые)
Майкл М.

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). Кроме того, ~и *являются операторами , а не функциями.


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

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 с одной инструкцией в теле не нуждаются в фигурных скобках.
Виктор Стафуса

Я думаю, что это 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 Спасибо, я внес эти и другие изменения.
Wally

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.