Résoudre une équation linéaire

12

Ce défi mais avec une meilleure spécification.

Spec

Votre programme prendra une équation linéaire contenant une seule variable xet affichera la valeur de x.

Entrée / analyse

  • L'entrée ne contiendra que des nombres, des opérateurs, des parenthèses ( ()) xet un =signe (cela signifie qu'il n'y a pas d'espaces).
  • Les parenthèses seront toujours équilibrées.
  • Il y en aura toujours au moins 1 x. Un xpeut être précédé d'un nombre.
  • Toutes les équations auront exactement un résultat.

Un nombre peut être défini en suivant ces étapes. Un certain nombre peut être défini par l'expression rationnelle: -?(\d+(\.\d+)?|\.\d+).


Si vous ne parlez pas d'expression régulière: un chiffre est défini comme 0-9

  1. Il peut y avoir -au début un signe négatif
  2. Ensuite, il peut y avoir quelques chiffres. S'il n'y a pas de chiffres, il y aura un point décimal
  3. S'il existe un point décimal, au moins un chiffre le suivra

Le plus grand nombre / valeur sera défini par les capacités de votre langue.


Un opérateur est l'un des:, +-*/ils apparaîtront toujours entre les nombres et ou entre parenthèses

cela signifie que ce (5)(5)n'est pas une entrée valide pour des raisons de simplicité.


Les parenthèses contiendront toujours une expression valide (une combinaison valide de nombres et / ou d'opérateurs) à l'intérieur. La parenthèse "équilibrée" est définie comme chaque (aura une fermeture associée)

Évaluation

  • L'ordre des opérations doit être suivi et les priorités sont (du plus élevé au plus bas):
    • Parenthèses (les plus profondément imbriquées en premier)
    • Multiplication et division
    • Addition soustraction
  • Si deux opérateurs avec la même priorité se sont produits, vous devriez préférer aller à gauche -> à droite

Production

Vous devez sortir le résultat d'une manière ou d'une autre. Si vous ne sortez pas simplement le résultat numérique, clarifiez dans votre réponse comment la sortie est sortie. Votre format de sortie doit être cohérent. La sortie peut être une décimale, mais elle sera toujours rationnelle, la précision est limitée à la précision de votre langue. Seulement si votre langue ne prend pas en charge l'arithmétique à virgule flottante, vous n'avez pas besoin de la prendre en charge.

Règles

  • Les fonctions intégrées banalisant cette tâche sont autorisées, mais vous devez clairement ajouter [uses built-in]clairement à l'en-tête de la réponse. Cela exempte votre réponse de gagner
  • Un "Built-ins banalisant cette tâche" est l'un des:
    • Quelque chose qui prend une équation et génère la valeur pour une / la variable
    • Quelque chose qui simplifiera complètement une équation
    • Utiliser evalou une fonction associée pour effectuer une quantité importante d'analyse. L'utilisation evalet les fonctions associées sont interdites si elles sont utilisées (avec une modification minimale de l'entrée) pour résoudre des équations linéaires.
    • En cas de doute, il suffit de demander dans un commentaire.
  • Les éléments intégrés qui analysent l'équation sont autorisés

Exemples

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

Entrées non valides :

(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
la source
8
Vous dites que les éléments intégrés disqualifient votre soumission, mais clarifiez cela pour ne faire référence qu'aux opérations qui effectuent la résolution et l'analyse des équations, etc. Je pense qu'il serait plus clair d'utiliser un terme différent, car je pense à toute opération nommée comme intégrée.
xnor
Quelle doit être la précision des réponses?
flawr
@MrPublic Votre programme prendra une équation linéaire contenant une seule variable ...
Luis Mendo
De plus, est-ce que JavaScript evalcompte pour banaliser le défi? En outre, les formes de new Function(...)comptage seraient- elles
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ dépend de l'utilisation que vous en faites. Mais en supposant que vous utilisez JavaScript, je ne vois pas comment cela banalisera le défi si sûr
Downgoat

Réponses:

3

JavaScript ES6, 246 octets

Encore du golf à faire, mais au moins c'est une solution!

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}

Nommez la fonction n=>{n=n.split("=")...pour l'utiliser.

Hyper-non golfé:

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

Cela utilise une approche pivot. (Je ne sais pas si c'est ainsi que s'appelle l'algorithme, juste un nom que j'ai inventé.) Il recueille d'abord la direction à rechercher à partir de zéro (c'est-à-dire, de quelle manière les pentes des deux côtés des équations vont se croiser) et recherche la valeur. Une fois qu'il trouve un point de différence minimale, il va à ce point et diminue l'incrément de recherche. Cela donne finalement aussi précis d'une solution dont nous avons besoin.

Conor O'Brien
la source
Je pense que vous pourriez vous raser un peu en utilisant la syntaxe eval + ES6 au lieu de Function new
Ven
2

JavaScript (Node.js) , 106 93 octets

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

Essayez-le en ligne!

-13 octets grâce à @tsh

Non golfé:

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
}

Explication:

Cette solution fonctionne selon la méthode de Newton pour trouver des racines. Le code soustrait le côté droit de l'équation du côté gauche, de telle sorte que, quand f(x)=0, xsera égal à la valeur pour laquelle nous résolvons. Par conséquent, lorsque nous trouverons la racine de cette nouvelle fonction, ce sera notre xvaleur souhaitée . Il trouve ensuite la dérivée f'(x)en trouvant la pente entre deux points sur la fonction. Ensuite, les valeurs sont simplement insérées dans la méthode de Newton qui indique pour une approximation de la racine x, x=x-(f(x)/f'(x))(dans le code, nous utilisons 0 comme xvaleur initiale ). Puisque cela trouve ses racines, il trouve notre xvaleur. Et puisque l'équation est garantie d'être linéaire, l'approximation sera exacte.

Logern
la source
93 octets
tsh
1

Mathcad, [utilise intégré]

entrez la description de l'image ici

Mathcad a deux méthodes intégrées pour résoudre de telles équations:

  • Solveur symbolique (utilise le mot-clé résoudre)
  • Résoudre le bloc (qui fonctionne à la fois en mode numérique et symbolique). Un bloc de résolution commence par le mot-clé Given, suivi d'un ensemble d'expressions définissant les conditions d'intérêt, et fermé par l'un des mots-clés de résolution, tels que Find (qui trouve une solution exacte) ou MinErr (qui minimise l'erreur entre la cible et Toute solution).

Le solveur symbolique est assez satisfait de y = x et renvoie la solution x = y.

Pour ceux qui ne connaissent pas Mathcad, l'image ci-dessous est prise directement à partir du classeur WYSIWYGish Mathcad 15. Si vous modifiez l'une des expressions où elles sont écrites, Mathcad réévaluera sa réponse et mettra à jour l'affichage en conséquence.

Stuart Bruff
la source
Par simple curiosité, pourquoi les votes négatifs? Je peux comprendre que sa simplicité peut être à la racine de celle-ci, mais elle ne semble pas être essentiellement différente de la solution TI Basic, qui ajoute simplement une petite quantité de traitement d'entrée avant d'appeler le solveur intégré et pourtant que n'a pas été rétrogradé.
Stuart Bruff
1
Quel est le nombre d'octets réel de ce programme?
Jo King
Les votes négatifs sont probablement dus au fait que votre solution est triviale - voir «Qu'est-ce qu'une solution triviale? sur meta.
0

Axiom, 214 octets [utilise intégré]

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)

Pour une erreur qui retournerait% i, pour un autre type d'erreur, la fonction est arrêtée par le système, autre chose comme 1--2 semble hors de la langue ... 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
la source