Lösen Sie eine lineare Gleichung

12

Diese Herausforderung aber mit einer besseren Spezifikation.

Spec

Ihr Programm nimmt eine lineare Gleichung, die eine einzelne Variable enthält, xund gibt den Wert von aus x.

Eingabe / Analyse

  • Die Eingabe enthält nur Zahlen, Operatoren, Klammern ( ()) xund ein =Vorzeichen (dh kein Leerzeichen).
  • Klammern werden immer ausgeglichen sein.
  • Es wird immer mindestens 1 geben x. An xkann eine Zahl vorangestellt werden.
  • Alle Gleichungen haben genau ein Ergebnis.

Eine Nummer kann folgendermaßen definiert werden. Eine Zahl kann durch den regulären Ausdruck definiert werden: -?(\d+(\.\d+)?|\.\d+).


Wenn Sie kein Regex sprechen: Eine Ziffer ist definiert als 0-9

  1. Es kann ein -am Anfang stehen, was negativ bedeutet
  2. Dann kann es einige Ziffern geben. Wenn es sich nicht um Ziffern handelt, wird ein Dezimalpunkt angezeigt
  3. Wenn ein Dezimalpunkt vorhanden ist, folgt ihm mindestens eine Ziffer

Die größte Zahl / der größte Wert wird durch die Fähigkeiten Ihrer Sprache definiert.


Ein Operator ist einer von:, +-*/sie werden immer zwischen Zahlen und / oder Klammern angezeigt

Dies bedeutet, dass (5)(5)der Einfachheit halber keine gültige Eingabe ist.


Klammern enthalten immer einen gültigen Ausdruck (eine gültige Kombination von Zahlen und / oder Operatoren). "Ausgewogene" Klammern sind definiert, da jeder Klammer (eine Schließung zugeordnet ist)

Auswertung

  • Die Reihenfolge der Operationen sollte eingehalten werden und die Prioritäten lauten (von der höchsten zur niedrigsten):
    • Klammer (am tiefsten verschachtelt zuerst)
    • Multiplikation & Division
    • Addition Subtraktion
  • Wenn zwei Operatoren mit der gleichen Priorität auftreten, sollten Sie lieber nach links -> rechts gehen

Ausgabe

Sie sollten das Ergebnis auf irgendeine Weise ausgeben. Wenn Sie nicht nur Zahlenergebnisse ausgeben, erläutern Sie in Ihrer Antwort, wie die Ausgabe erfolgt. Ihr Ausgabeformat sollte konsistent sein. Die Ausgabe kann eine Dezimalzahl sein, ist jedoch immer rational. Die Genauigkeit ist auf die Genauigkeit Ihrer Sprache beschränkt. Nur wenn Ihre Sprache keine Gleitkomma-Arithmetik unterstützt, müssen Sie sie nicht unterstützen.

Regeln

  • Built-In diese Aufgabe Trivialisierung sind erlaubt aber , müssen Sie deutlich hinzufügen , [uses built-in]eindeutig auf die Header der Antwort. Dies befreit Ihre Antwort vom Gewinn
  • Ein "Built-In, das diese Aufgabe trivialisiert", ist eines von:
    • Etwas, das eine Gleichung aufnimmt und den Wert für eine / die Variable ausgibt
    • Etwas, das eine Gleichung völlig vereinfacht
    • Verwenden evaloder einer verwandten Funktion, um einen wesentlichen Teil des Parsings durchzuführen. Die Verwendung von evalund verwandte Funktionen sind nicht zulässig, wenn sie zum Lösen von linearen Gleichungen (mit minimaler Änderung der Eingabe) verwendet werden.
    • Wenn Sie Zweifel haben, fragen Sie einfach in einem Kommentar.
  • Eingebaute, die die Gleichung analysieren, sind erlaubt

Beispiele

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

UNGÜLTIGE Eingänge:

(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
quelle
8
Sie sagen, dass integrierte Funktionen Ihre Übermittlung disqualifizieren, dies jedoch klarstellen, um nur auf Operationen zu verweisen, die das Lösen und Parsen von Gleichungen und dergleichen ausführen. Ich denke, es wäre klarer, einen anderen Begriff zu verwenden, da ich jede benannte Operation als eingebaute Operation betrachte.
Xnor
Wie genau müssen die Antworten sein?
Fehler
@ MrPublic Ihr Programm wird eine lineare Gleichung mit einer einzelnen Variablen nehmen ...
Luis Mendo
Zählt auch JavaScript evalals Trivialisierung der Herausforderung? Würden auch Formen new Function(...)zählen?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ hängt davon ab, wofür du es verwendest. Aber wenn Sie JavaScript verwenden, kann ich nicht erkennen, wie es die Herausforderung so sicher trivialisieren wird
Downgoat

Antworten:

3

JavaScript ES6, 246 Bytes

Es bleibt noch ein bisschen Golf zu spielen, aber es ist zumindest eine Lösung!

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}

Benennen Sie die n=>{n=n.split("=")...zu verwendende Funktion .

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

Dies verwendet einen Pivot-Ansatz. (Ich bin mir nicht sicher, ob der Algorithmus so heißt, nur ein Name, den ich erfunden habe.) Zunächst wird erfasst, nach welcher Richtung von Null aus gesucht werden soll (dh auf welche Weise sich die Steigungen der beiden Seiten der Gleichungen schneiden) und sucht den Wert. Sobald ein Punkt mit minimaler Differenz gefunden wurde, wird dieser Punkt erreicht und das Suchinkrement verringert. Dies ergibt schließlich eine so genaue Lösung, wie wir sie brauchen.

Conor O'Brien
quelle
Ich denke, Sie könnten sich ein bisschen rasieren, wenn Sie eval + ES6-Syntax anstelle von Function new verwenden
Ven
2

JavaScript (Node.js) , 106 93 Byte

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

Probieren Sie es online!

-13 Bytes dank @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
}

Erklärung:

Diese Lösung funktioniert nach Newtons Methode zum Finden von Wurzeln. Der Code subtrahiert die rechte Seite der Gleichung von der linken Seite, so dass , wenn f(x)=0, xwird der Wert gleich , für die wir zu lösen. Wenn wir also die Wurzel dieser neuen Funktion finden, wird dies unser gewünschter xWert sein. Dann findet es die Ableitung, f'(x)indem es die Steigung zwischen zwei Punkten auf der Funktion findet. Dann werden die Werte einfach eingefügt in Newton-Verfahren , die für eine Annäherung der Wurzel heißt x, x=x-(f(x)/f'(x))(im Code verwenden wir 0 als xAnfangswert). Da dies die Wurzeln findet, findet es unseren xWert. Und da die Gleichung garantiert linear ist, ist die Approximation genau.

Logern
quelle
93 Bytes
tsh
1

Mathcad, [verwendet eingebaute]

Bildbeschreibung hier eingeben

Mathcad verfügt über zwei integrierte Methoden zum Lösen solcher Gleichungen:

  • Symbolischer Löser (verwendet das Schlüsselwort solve)
  • Löse Block (funktioniert sowohl im numerischen als auch im symbolischen Modus). Ein Lösungsblock beginnt mit dem Schlüsselwort Given, gefolgt von einer Reihe von Ausdrücken, die die relevanten Bedingungen definieren, und wird durch eines der Lösungsschlüsselwörter geschlossen, z irgendeine Lösung).

Der symbolische Löser ist sehr zufrieden mit y = x und gibt die Lösung x = y zurück.

Für diejenigen, die mit Mathcad nicht vertraut sind, wird das folgende Bild direkt aus der WYSIWYGish Mathcad 15-Arbeitsmappe entnommen. Wenn Sie die Ausdrücke ändern, in denen sie geschrieben sind, bewertet Mathcad die Antwort neu und aktualisiert die Anzeige entsprechend.

Stuart Bruff
quelle
Warum aus müßiger Neugier die Downvotes? Ich kann verstehen, dass die Einfachheit möglicherweise die Wurzel ist, aber es scheint im Wesentlichen nichts anderes zu sein als die TI Basic-Lösung, die lediglich einen kleinen Teil der Eingabeverarbeitung hinzufügt, bevor der eingebaute Solver aufgerufen wird, und dennoch das wurde nicht herabgestimmt.
Stuart Bruff
1
Was ist die tatsächliche Byteanzahl dieses Programms?
Jo King
Die Abstimmungen sind wahrscheinlich, weil Ihre Lösung trivial ist - siehe 'Was ist eine triviale Lösung?' auf meta.
0

Axiom, 214 Bytes [verwendet eingebaute]

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)

Bei einem Fehler würde% i zurückgegeben, bei einem anderen Fehlertyp wird die Funktion vom System gestoppt, etwas anderes wie 1-2 scheint nicht in der Sprache zu sein ... 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
quelle