Resolver uma equação linear

12

Este desafio, mas com uma especificação melhor.

Spec

Seu programa utilizará uma equação linear contendo uma única variável xe produzirá o valor de x.

Entrada / Análise

  • A entrada conterá apenas números, operadores, parênteses ( ()) xe um =sinal (isso significa que não há espaço em branco).
  • Os parênteses sempre serão equilibrados.
  • Sempre haverá pelo menos 1 x. Um xpode ser precedido por um número.
  • Todas as equações terão exatamente um resultado.

Um número pode ser definido seguindo estas etapas. Um número pode ser definido pela expressão regular: -?(\d+(\.\d+)?|\.\d+).


Se você não fala regex: um dígito é definido como 0-9

  1. Pode ter um -no início significando negativo
  2. Depois, há podem ser alguns dígitos. Se eles não tiverem dígitos, haverá um ponto decimal
  3. Se existir um ponto decimal, pelo menos um dígito o seguirá

O maior número / valor será definido pelos recursos do seu idioma.


Um operador é um dos seguintes: +-*/eles sempre aparecerão entre números e ou parênteses

isso significa que (5)(5)não é uma entrada válida por uma questão de simplicidade.


Os parênteses sempre conterão uma expressão válida (uma combinação válida de números e / ou operadores) dentro deles. Parênteses "equilibrado" é definido, pois todos (terão um fechamento associado)

Avaliação

  • A ordem das operações deve ser seguida e as precedências são (da maior para a menor):
    • Parênteses (mais profundamente aninhado primeiro)
    • Multiplicação e Divisão
    • Adição subtração
  • Se ocorrerem dois operadores com a mesma precedência, você deve preferir ir para a esquerda -> direita

Resultado

Você deve produzir o resultado de alguma maneira. Se você não gerar apenas o resultado numérico, esclareça na sua resposta como a saída é gerada. Seu formato de saída deve ser consistente. A saída pode ser decimal, mas sempre será racional, a precisão é limitada à precisão do seu idioma. Somente se seu idioma não suportar aritmética de ponto flutuante, você não precisará suportá-lo.

Regras

  • Built-ins trivializando esta tarefa são permitidos , mas você deve adicionar [uses built-in]claramente claramente ao cabeçalho da resposta. Isso isenta sua resposta de ganhar
  • Um "Built-ins trivializando esta tarefa" é um dos seguintes:
    • Algo que pega uma equação e gera o valor para uma / a variável
    • Algo que simplificará completamente uma equação
    • Usando evalou uma função relacionada para realizar uma quantidade significativa da análise. O uso de evale funções relacionadas não são permitidas se estiverem acostumadas a (com modificação mínima na entrada) resolver equações lineares.
    • Em caso de dúvida, basta perguntar em um comentário.
  • Built-ins que analisam a equação são permitidos

Exemplos

3+4=x
7

4+x=5
1

3+3*3=x
12

3x-4=7+2x
11

3--1=x
4

3*(2+4x)=7x-4
-2

1.2+2.3x=5.8
2

10=4x
2.5

Entradas INVALID :

(5)(4)=x  no operator between (5) and (4)
5(x+3)=2  no operator 5 and (...)
x=y       the only variable is x
4=3       there is no x
x+3=x-7   no solution
x=x       infinite solutions
+5=x      + is not an unary operator. -5=x would be valid though
1/(x-3)=5 Nonlinear
3/x       Nonlinear
Downgoat
fonte
8
Você diz que os built-ins desqualificam sua submissão, mas esclareça que isso se refere apenas às operações que resolvem e analisam equações e similares. Eu acho que seria mais claro usar um termo diferente, já que penso em qualquer operação nomeada como incorporada.
xnor 24/03
Qual a precisão das respostas?
flawr
@MrPublic Seu programa terá uma equação linear que contém uma única variável ...
Luis Mendo
Além disso, o JavaScript evalconta como trivializando o desafio? Além disso, formas de new Function(...)contagem?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ depende para o que você o usa. Mas supondo que você está usando JavaScript Eu não ver como ele vai banalizar o desafio tanta certeza
Downgoat

Respostas:

3

JavaScript ES6, 246 bytes

Ainda há golfe a ser feito, mas pelo menos é uma solução!

C=a=>new Function("x","return "+a.replace(/(\d)x/g,"$1*x"));n=>{n=n.split("=");t=Math.abs,r=C(n[0]),c=C(n[1]),a=0,i=r(a)-c(a);a++;v=r(a)-c(a);o=t(i)<t(v)?-1:1;for(u=1/0;r(a)!==c(a);)a+=o,e=t(r(a)-c(a)),e>u&&(u=1/0,o/=10),u=Math.min(e,u);return a}

Nomeie a função n=>{n=n.split("=")...para usá-la.

Hyper-ungolfed:

function solveLinear(equation){
    equation = equation.split("=");
    var abs = Math.abs;
    var LHS = convertToFunction(equation[0]), RHS = convertToFunction(equation[1]);
    var pivot = 0;
    var dir;
    var dir1 = LHS(pivot) - RHS(pivot);
    pivot++;
    var dir2 = LHS(pivot) - RHS(pivot);
    if(abs(dir1)<abs(dir2)) dir = -1;
    else dir = 1;
    var dif, minDif = Infinity;
    while(LHS(pivot) !== RHS(pivot)){
        pivot += dir;
        dif = abs(LHS(pivot) - RHS(pivot));
        if(dif > minDif){
            minDif = Infinity;
            dir /= 10;
        }
        minDif = Math.min(dif, minDif);
        console.log(pivot,dir,dif,minDif);
    }
    return {
        x: pivot,
        LHS: LHS,
        RHS: RHS
    };
}

Isso usa uma abordagem dinâmica. (Não tenho certeza se é assim que o algoritmo é chamado, apenas um nome que eu inventei.) Primeiro ele reúne a direção a ser buscada a partir do zero (ou seja, de que maneira as inclinações dos dois lados das equações se cruzam) e procura o valor. Depois de encontrar um ponto de diferença mínima, ele vai para esse ponto e diminui o incremento da pesquisa. Isso acaba gerando a solução mais precisa que precisamos.

Conor O'Brien
fonte
Eu acho que você poderia fazer a barba um bom bocado usando eval + ES6 sintaxe em vez de Função nova
Ven
2

JavaScript (Node.js) , 106 93 bytes

a=>eval(`f=x=>${a[R='replace'](/(\d)x/g,"$1*x")[R]("=","-(")[R](/-/g,"+-")})`)(0)/(f(0)-f(1))

Experimente online!

-13 bytes graças a @tsh

Ungolfed:

var h=a=>{
  a=a.replace(/(\d)x/g,"$1*x").replace("=","-(").replace("--","- -"); //get into an eval-able form
  var f=x=>eval(a+")");
  var df=(f(1)-f(0))/(1-0) //derivative or slope of the function
  var x=0;
  return x-(f(x)/df); //newton's method
}

Explicação:

Esta solução funciona pelo método de Newton para encontrar raízes. O código subtrai o lado direito da equação do lado esquerdo, de tal forma que, quando f(x)=0, xserá igual ao valor que estamos resolvendo para. Portanto, quando encontrarmos a raiz dessa nova função, será o nosso xvalor desejado . Em seguida, encontra a derivada f'(x)encontrando a inclinação entre dois pontos na função. Em seguida, os valores são simplesmente inserido no método de Newton, que indica para uma aproximação da raiz x, x=x-(f(x)/f'(x))(no código, usamos um 0 como primeiro xvalor). Uma vez que isso encontra as raízes, encontra o nosso xvalor. E como a equação é garantida como linear, a aproximação será exata.

Logern
fonte
93 bytes
tsh
1

Mathcad, [usa embutido]

insira a descrição da imagem aqui

O Mathcad possui dois métodos internos para resolver essas equações:

  • Solucionador simbólico (usa a palavra-chave resolver)
  • Solve Block (que funciona nos modos numérico e simbólico). Um bloco de solução começa com a palavra-chave Dada, seguido de um conjunto de expressões que definem as condições de interesse e fechado por uma das palavras-chave de solução, como Localizar (que encontra uma solução exata) ou MinErr (que minimiza o erro entre o destino e qualquer solução).

O solucionador simbólico está bastante satisfeito com y = xe retorna a solução x = y.

Para quem não conhece o Mathcad, a imagem abaixo é tirada diretamente da pasta de trabalho WYSIWYGish Mathcad 15. Alterar qualquer uma das expressões em que estão escritas fará com que o Mathcad reavalie sua resposta e atualize a exibição de acordo.

Stuart Bruff
fonte
Por curiosidade ociosa, por que os votos negativos? Entendo que a simplicidade disso pode estar na raiz dele, mas parece essencialmente não ser diferente da solução TI Basic, que apenas adiciona uma pequena quantidade de processamento de entrada antes de chamar o solucionador embutido e ainda assim não foi votado.
Stuart Bruff 28/03
1
Qual é a contagem de bytes real deste programa?
Jo rei
As votações negativas são prováveis ​​porque sua solução é trivial - consulte 'O que é uma solução trivial?' no meta.
0

Axioma, 214 bytes [usa interno]

q(t:EQ POLY FLOAT):Any==(a:=[variables(lhs t),variables(rhs t)];a.1~=[x]and a.1~=[]=>%i;a.2~=[x]and a.2~=[]=>%i;a.1=[]and a.2=[]=>%i;a.1=[x]and degree(lhs t,x)>1=>%i;a.2=[x]and degree(rhs t,x)>1=>%i;rhs solve(t).1)

Se algum erro retornasse% i, para outros tipos de erros a função é interrompida do sistema, outra coisa como 1--2 parece estar fora do idioma ... test:

(72) -> q(x+3=9)
   (72)  6.0
                                  Type: Complex Fraction Polynomial Float
(73) -> q(3+4=x)
   (73)  7.0
                                  Type: Complex Fraction Polynomial Float
(74) -> q(4+x=5)
   (74)  1.0
                                  Type: Complex Fraction Polynomial Float
(75) -> q(3+3*3=x)
   (75)  12.0
                                  Type: Complex Fraction Polynomial Float
(76) -> q(3*x-4=7+2*x)
   (76)  11.0
                                  Type: Complex Fraction Polynomial Float
(77) -> q(3--1=x)
  Line   1: q(3--1=x)
           .AB
  Error  A: Missing mate.
  Error  B: syntax error at top level
  Error  B: Possibly missing a )
   3 error(s) parsing
(77) -> q(3*(2+4*x)=7*x-4)
   (77)  - 2.0
                                  Type: Complex Fraction Polynomial Float
(78) -> q(1.2+2.3*x=5.8)
   (78)  2.0
                                  Type: Complex Fraction Polynomial Float
(79) -> q(10=4*x)
   (79)  2.5
                                  Type: Complex Fraction Polynomial Float
(80) -> q((5)(4)=x)
   Cannot find a definition or applicable library operation named 5
      with argument type(s)
                           PositiveInteger

  Perhaps you should use "@" to indicate the required return type,
  or "$" to specify which version of the function you need.
(80) -> q(5(x+3)=2 )
   (80)  %i
                                                    Type: Complex Integer
(81) -> q(x=y)
   (81)  %i
                                                    Type: Complex Integer
(82) -> q(4=3)
   (82)  %i
                                                    Type: Complex Integer
(83) -> q(x+3=x-7)
   >> Error detected within library code:
   inconsistent equation
protected-symbol-warn called with (NIL)
(83) -> q(x=x)
   >> Error detected within library code:
   equation is always satisfied
protected-symbol-warn called with (NIL)
RosLuP
fonte