Rozwiąż równanie liniowe

12

To wyzwanie, ale z lepszą specyfikacją.

Spec

Twój program weźmie równanie liniowe zawierające jedną zmienną xi wyświetli wartość x.

Wejście / parsowanie

  • Dane wejściowe będą zawierać tylko liczby, operatory, nawiasy ( ()) xi =znak (oznacza to brak białych znaków).
  • Nawiasy zawsze będą zrównoważone.
  • Zawsze będzie co najmniej 1 x. xMoże być poprzedzona numerem.
  • Wszystkie równania będą miały dokładnie jeden wynik.

Liczba może być zdefiniowana przez następujące kroki. Wiele może być określony przez regex: -?(\d+(\.\d+)?|\.\d+).


Jeśli nie mówisz wyrażenia regularnego: cyfra jest zdefiniowana jako 0-9

  1. Na początku może mieć wartość -ujemną
  2. Wtedy mogą być jakieś cyfry. Jeśli nie są to żadne cyfry, będzie kropka dziesiętna
  3. Jeśli istnieje przecinek dziesiętny, za nim podąża co najmniej jedna cyfra

Największa liczba / wartość będzie określona przez możliwości twojego języka.


Operator jest którykolwiek z: +-*/, zawsze będą pojawiać się między numerami, i czy nawias

oznacza (5)(5)to, że nie jest to poprawny wkład ze względu na prostotę.


Nawias zawsze będzie zawierał prawidłowe wyrażenie (poprawną kombinację liczb i / lub operatorów). Nawias „zrównoważony” jest zdefiniowany, ponieważ każdy (będzie miał powiązane zamknięcie)

Ocena

  • Kolejność operacji powinna być przestrzegana, a priorytety są (od najwyższego do najniższego):
    • Nawias (najpierw najgłębiej zagnieżdżony)
    • Mnożenie i dzielenie
    • Dodawanie odejmowanie
  • Jeśli wystąpią dwa operatory o tym samym priorytecie, powinieneś woli iść w lewo -> w prawo

Wynik

Powinieneś w jakiś sposób wypisać wynik. Jeśli nie podajesz tylko wyniku liczbowego, wyjaśnij w swojej odpowiedzi, w jaki sposób generowany jest wynik. Twój format wyjściowy powinien być spójny. Dane wyjściowe mogą być dziesiętne, ale zawsze będą racjonalne, precyzja jest ograniczona do precyzji twojego języka. Tylko jeśli twój język nie obsługuje arytmetyki zmiennoprzecinkowej, nie musisz jej obsługiwać.

Zasady

  • Wbudowane trywializujące to zadanie są dozwolone, ale należy wyraźnie dodać [uses built-in]wyraźnie nagłówek odpowiedzi. To zwalnia twoją odpowiedź od wygranej
  • „Wbudowane trywializujące to zadanie” to:
    • Coś, co przyjmuje równanie i wyświetla wartość dla zmiennej /
    • Coś, co całkowicie uprości równanie
    • Użycie evallub powiązanej funkcji do wykonania znacznej ilości parsowania. Korzystanie z evalfunkcji pokrewnych jest niedozwolone, jeśli są one używane (przy minimalnej modyfikacji danych wejściowych) do rozwiązywania równań liniowych.
    • Jeśli masz wątpliwości, po prostu zapytaj w komentarzu.
  • Dozwolone są wbudowane parsujące równanie

Przykłady

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

NIEPRAWIDŁOWE Wejścia:

(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
źródło
8
Mówisz, że wbudowane dyskietki dyskwalifikują twoje przesłanie, ale wyjaśnij to, aby odnosić się tylko do operacji, które rozwiązują równanie i parsują i tym podobne. Myślę, że łatwiej byłoby użyć innego terminu, ponieważ każdą nazwaną operację uważam za wbudowaną.
xnor
Jak dokładne muszą być odpowiedzi?
flawr
@MrPublic Twój program przyjmie równanie liniowe zawierające jedną zmienną ...
Luis Mendo
Czy JavaScript również evaluważa się za trywializujący wyzwanie? Czy również formy new Function(...)liczenia?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ zależy od tego, do czego go używasz. Ale zakładając, że używasz JavaScript, nie wiem, jak to trywializuje wyzwanie, więc pewne
Downgoat

Odpowiedzi:

3

JavaScript ES6, 246 bajtów

Jeszcze trochę golfa do zrobienia, ale przynajmniej jest to rozwiązanie!

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}

Nazwij funkcję, n=>{n=n.split("=")...aby z niej skorzystać.

Hiperbola:

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

To wykorzystuje podejście przestawne. (Nie jestem pewien, czy tak się nazywa ten algorytm, tylko nazwa, którą wymyśliłem.) Najpierw zbiera kierunek, którego należy szukać od zera (tj. W którą stronę przecinają się zbocza dwóch boków równań) i szuka wartości. Gdy znajdzie punkt minimalnej różnicy, przechodzi do tego punktu i zmniejsza przyrost wyszukiwania. To ostatecznie daje tak precyzyjne rozwiązanie, jakiego potrzebujemy.

Conor O'Brien
źródło
Myślę, że możesz się dobrze ogolić, używając składni eval + ES6 zamiast Function new
Ven
2

JavaScript (Node.js) , 106 93 bajtów

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

Wypróbuj online!

-13 bajtów dzięki @tsh

Nie golfowany:

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
}

Wyjaśnienie:

To rozwiązanie działa według metody Newtona w celu znalezienia korzeni. Kod odejmuje prawą stronę równania od lewej strony, tak, że kiedy f(x)=0, xbędzie równy wartości, którą rozwiązujemy. Dlatego, gdy znajdziemy źródło tej nowej funkcji, będzie to nasza pożądana xwartość. Następnie znajduje pochodną f'(x), znajdując nachylenie między dwoma punktami funkcji. Następnie wartości te są po prostu włożony do metody Newtona, który stanowi, dla zbliżenia korzenia x, x=x-(f(x)/f'(x))(w kodzie używamy 0 jako początkowej xwartości). Ponieważ znajduje to korzenie, znajduje naszą xwartość. Ponieważ gwarantuje się, że równanie jest liniowe, przybliżenie będzie dokładne.

Logern
źródło
93 bajty
tsh
1

Mathcad, [używa wbudowanego]

wprowadź opis zdjęcia tutaj

Mathcad ma dwie wbudowane metody rozwiązywania takich równań:

  • Solver symboliczny (używa słowa kluczowego rozwiąż)
  • Rozwiąż blok (który działa zarówno w trybie numerycznym, jak i symbolicznym). Blok rozwiązywania zaczyna się od podanego słowa kluczowego, następuje zestaw wyrażeń określających warunki zainteresowania i jest zamykany przez jedno ze słów kluczowych rozwiązywania, takie jak Znajdź (który znajduje dokładne rozwiązanie) lub MinErr (co minimalizuje błąd między celem a dowolne rozwiązanie).

Solver symboliczny jest całkiem zadowolony z y = x i zwraca rozwiązanie x = y.

Dla tych, którzy nie znają Mathcada, poniższe zdjęcie pochodzi bezpośrednio ze skoroszytu WYSIWYGish Mathcad 15. Zmiana dowolnego wyrażenia, w którym są zapisane, spowoduje, że Mathcad ponownie oceni odpowiedź i odpowiednio zaktualizuje wyświetlacz.

Stuart Bruff
źródło
Z bezczynnej ciekawości, dlaczego głosy przegłosowane? Rozumiem, że jego prostota może być u podstaw, ale wydaje się, że zasadniczo nie różni się od rozwiązania TI Basic, które jedynie dodaje niewielką ilość przetwarzania danych wejściowych przed wywołaniem wbudowanego solvera, a jednak to nie był doceniony.
Stuart Bruff
1
Jaka jest rzeczywista liczba bajtów tego programu?
Jo King
Negatywne opinie są prawdopodobne, ponieważ twoje rozwiązanie jest trywialne - patrz „Co to jest trywialne rozwiązanie?” na meta.
0

Axiom, 214 bajtów [wykorzystuje wbudowany]

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)

W przypadku niektórych błędów zwraca% i, w przypadku innych błędów funkcja jest zatrzymywana z systemu, coś innego jak 1--2 wydaje się nie na języku ... 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
źródło