Jolis polynômes d'impression

38

introduction

Les humains sont une espèce remarquable, mais nous pouvons parfois être très difficiles à comprendre, en particulier pour les ordinateurs. En particulier, il semble que nous aimions écrire des polynômes de manière très compliquée, avec des règles apparemment arbitraires.

Quel est le programme le plus court que vous puissiez écrire pour formater correctement un polynôme en utilisant ces règles?

Défi

Contribution

Liste d'entiers compris entre -1000 et 1000 (inclus), représentant les coefficients d'un polynôme, la dernière entrée étant le coefficient de x ^ 0 (la constante), la dernière dernière étant le coefficient de x ^ 1, etc.

Sortie

Une chaîne représentant ce polynôme dans la notation mathématique humaine correctement formatée.

Règles:

  • Le signe sur le coefficient de début n'apparaît que s'il est négatif.

Right: -x^2+3

Wrong: +x^2+3

  • Les composants dont le coefficient est égal à 0 ne sont pas imprimés (à l'exception du cas où tous les coefficients sont 0 *).

Right: x^5-x^2+3

Wrong: x^5+0x^4+0x^3-x^2+0x+3

  • Les coefficients -1et +1doivent être affichés sans le 1, à moins qu’ils ne soient la constante.

Right: x^5-x^2+1

Wrong: 1x^5-1x^2+1

  • L'exposant n'est affiché que s'il est supérieur à 1 et la variable uniquement si l'exposant est supérieur à 0.

Right: 3x^3-7x^2+2x+1

Wrong: 3x^3-7x^2+2x^1+1x^0

  • * Cas des angles: bien que les valeurs nulles ne génèrent généralement pas ce composant, si tous les coefficients sont nuls, la constante 0 doit être imprimée.

Right: 0

Wrong: 0x+0

Wrong: (nothing)

  • Il s’agit d’un code-golf et le gagnant sera le programme contenant le moins d’octets.

Exemple d'entrée et de sortie

Input:                  Output:
      [0]                      0
      [0,0]                    0
      [0,-1,35,0]             -x^2+35x
      [5,1,7,-9]               5x^3+x^2+7x-9
      [100,0,0,-1]             100x^3-1
      [931,21,-11,1]           931x^3+21x^2-11x+1

J'ai hâte de voir vos solutions. S'amuser!

MODIFIER:

  • Vous pouvez entourer les opérations par des espaces si vous le souhaitez. Donc 3x+5et 3x + 5sont bien tous les deux. 3x+ 5et3x +5 ne sont pas.
  • Si vous voulez produire des caractères d'exposant réels (par exemple en Tex), cela est autorisé car ils sont encore plus proches de la façon dont les humains écrivent.
  • Les coefficients doivent apparaître sans décimales, par exemple, 9x^2est correct, 9.0x^2n'est pas.
Oisín Moran
la source
7
Une question que j’aurais dû poser dans le bac à sable mais n’ai-je pas pu, pouvons-nous imprimer des espaces entre les opérateurs? Alors3x^2 + 4 contre 3x^2+4?
Giuseppe
1
Avons-nous besoin de produire des exposants en utilisant des carets? Ou serait-il permis de produire un caractère en exposant (par exemple, pour une réponse en TeX)?
Tutleman
3
@KevinCruijssen Je ne suis pas l'OP mais je dirais que non, car la plupart des humains n'écrivent pas comme ça.
ShreevatsaR
2
@ManishKundu Ouais, bien sûr, vous pouvez utiliser les entrées sous forme de chaînes.
Oisín Moran
1
@ OisínMoran Rien de génial, juste pour s'assurer qu'un simple 1x-> xremplacement ne se transforme pas 21x^2en 2x^2.
DLosc

Réponses:

10

Retina 0.8.2 , 56 bytes

(?=( \S+)+)
x^$#1
\b0x.\d+ 

\b1x
x
x.1 
x 
 0

 -
-
 
+

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

(?=( \S+)+)
x^$#1

Insérer tous les pouvoirs de x, y compris x^1mais pas x^0.

\b0x.\d+ 

Supprimez toutes les puissances de xcoefficients nuls, mais pas de fin 0(pour le moment).

\b1x
x

Supprimer un multiplicateur de 1 (mais pas une constante 1).

x.1 
x 

Supprimer le ^1 de x^1.

 0

Supprimez une constante 0 sauf si c'est la seule chose qui reste.

 -
-

Supprimer l'espace avant un - .

 
+

Remplacez les espaces restants par +s.

Neil
la source
6

JavaScript (ES6), 107 106 octets

a=>a.map(c=>c?s+=(c>0&&s?'+':_)+(!--e|c*c-1?c:c<0?'-':_)+(e?e-1?'x^'+e:'x':_):e--,e=a.length,_=s='')&&s||0

Essayez-le en ligne!

Comment?

La sortie est construite en appliquant les formules suivantes à chaque coefficient c du tableau d’entrée a [] tout en gardant une trace de l’exposant actuel e .

1ère formule: signe plus

Si le coefficient est strictement positif et qu’il ne s’agit pas du premier terme de l’expression en sortie, on ajoute un + . Sinon, nous n’ajoutons rien.

c > 0 && s ? '+' : _

2ème formule: signe moins et coefficient

Si l'exposant est égal à zéro ou si la valeur absolue du coefficient n'est pas égale à 1, nous ajoutons le coefficient (qui peut inclure un premier -). Sinon, on ajoute soit un- (si le coefficient est négatif) soit rien.

!--e | c * c - 1 ? c : c < 0 ? '-' : _

3ème formule: variable et exposant

Si l'exposant est 0, nous n'ajoutons rien. Si l'exposant est 1, nous annexons x. Sinon, nous annexons x^suivi de l'exposant.

e ? e - 1 ? 'x^' + e : 'x' : _
Arnauld
la source
Cela échoue dans ce cas: [0,1,35,0], cela mènera avec + x ^ 2
Makotosan
2
@ Makotosan Merci d'avoir signalé cela! Ça devrait aller maintenant.
Arnauld
5

Stax , 37 octets

┴₧↕ê♦•Vªâÿσ9s╘dσ■à@@ⁿ■o─╦ñºº┌x╡ER▓ δ¿

Exécuter et déboguer en ligne

Voici la version non compressée et non emballée.

r{          reverse the input and map using block ...
  |c        skip this coefficient if it's falsy (zero)
  0<.+-@    sign char; e.g. '+'
  _|aYv i!+ abs(coeff)!=1 || i>0
    y$      str(abs(coeff)); e.g. '7'
    z       ""
  ?+        if-then-else, concatenate; e.g. '+7'
  "x^`i"    string template e.g. 'x^3' or 'x^0'
  iJ(T+     truncate string at i*i and trim. e.g. 'x^3' or ''
mr$         re-reverse mapped array, and flatten to string
c43=t       if it starts with '+', drop the first character
c0?         if the result is blank, use 0 instead

Exécuter celui-ci

récursif
la source
5

Python 3, 279 277 258 251 octets

k=str.replace
def f(x):
 z=len(x)
 y='--'*(['-1']==[c for c in x if'0'!=c][:1])
 for i,v in enumerate(x):
  p=str(z+~i)
  if v in'-1'and~i+z:y+='+x^'+p
  elif'0'!=v:y+='+'+v+'x^'+p
 return y and k(k(k(k(y[1:],'+-','-'),'^1',''),'x^0',''),'-+','-')or 0

Prend les entrées sous forme de liste de chaînes. Cette solution n'est pas encore très golfée. Cela fonctionne essentiellement en remplaçant des éléments pour les adapter au format de sortie, ce qui augmente considérablement le nombre d'octets.

Essayez-le en ligne!

Un merci spécial aux ovs et NK1406 .

Manish Kundu
la source
Correction de toutes les erreurs.
Manish Kundu
Vous pouvez réorganiser vos contrôles d’égalité pour les faire if'0'!=iet if'-1'==i.
Zacharý
@ovs merci beaucoup
Manish Kundu
4

APL (Dyalog Classic) , 114 113 109 107 106 octets

{{⍵≡'':⍕0⋄⍵↓⍨'+'=⊃⍵}∊⍵{{'1x'≡2↑1↓⍵:¯1⌽1↓1⌽⍵⋄⍵}('-0+'[1+×⍺]~⍕0),∊(U/⍕|⍺),(U←⍺≠0)/(⍵>⍳2)/¨'x'('^',⍕⍵)}¨⌽⍳⍴⍵}

Essayez-le en ligne!

-4 octets grâce à @dzaima!

Cela peut définitivement être joué au golf. Cela nécessite⎕IO←0

Zacharý
la source
J'ai finalement coupé ces deux octets ...
Zacharý
3

Pip , 78 octets

(RV(B."x^"._MERVg)J'+)R[`\b0[^+]+``x.0|\^1|^\++|\++$``\b1x``\++-?`][xx'x_@v]|0

Prend les coefficients comme arguments de ligne de commande. Essayez-le en ligne!

Utilise ME(map-enumerate) et J(join) pour générer quelque chose de la forme 0x^3+-1x^2+35x^1+0x^0, puis un tas de remplacements de regex pour le transformer au format approprié.

DLosc
la source
3

APL (Dyalog Classic) , 79 76 octets

{'^$' '\b1x' '\+?¯' '^\+'r('0x-',⊂⍬)∊⍕¨(0≠⍵)⌿'+',⍵,⊖⍪((⊢↓⍨2≤⊢)↑'x^',⍕)¨⍳≢⍵}

Essayez-le en ligne!

ngn
la source
3

Python 3, 161 162 octets

Correction d'un bug grâce aux ovs.

l=len
lambda p:''.join(['+'*(i>0)*(c>0)+(str(c)[:-1],str(c))[abs(c)!=1or i==l(p)-1]+'x'*(i!=l(p)-1)+('^%d'%(l(p)+~i))*(i<l(p)-2)for i,c in enumerate(p)if c])or'0'

Étendu:

l=len # Alias the len function since we use it a lot
lambda p: ''.join([ # Join a list of strings
    '+'*(i>0)*(c>0) # Prepend a + if this isn't the first term and the coefficient is positive
    + (str(c)[:-1], str(c))[abs(c) != 1 or i == l(p) - 1] # If the coefficient is 1 and this isn't the last term, delete the '1' from the string representation, otherwise just use the string representation
    + 'x' * (i != l(p) - 1) # If this isn't the last term, append an x
    + ('^%d' % (l(p) + ~i)) * (i < l(p) - 2) # If this isn't one of the last two terms, append the exponent
for i, c in enumerate(p) if c]) # Iterating over each coefficient with its index, discarding the term if the coefficient is zero
or '0' # If all of the above resulted in an empty string, replace it with '0'
bkul
la source
3

C # , 237 octets

c=>{var b=1>0;var r="";int l=c.Length;var p=!b;for(int i=0;i<l;i++){int n=c[i];int e=l-1-i;var o=p&&i>0&&n>0?"+":n==-1&&e!=0?"-":"";p=n!=0?b:p;r+=n==0?"":o+(e==0?$"{n}":e==1?$"{n}x":n==1||n==-1?$"x^{e}":$"{n}x^{e}");}return r==""?"0":r;}
Romen
la source
1
Bienvenue chez PPCG!
Martin Ender
3

Propre , 172 octets

import StdEnv,Text
r=reverse
@""="0"
@a|a.[size a-1]<'0'=a+"1"=a
? -1="-"
?1=""
?a=a<+""
$l=join"-"(split"+-"(join"+"(r[?v+e\\v<-r l&e<-["","x":map((<+)"x^")[1..]]|v<>0])))

Essayez-le en ligne!

Οurous
la source
@BMO fixe temporairement en attendant plus de golf.
urous
3

Wolfram Language / Mathematica, 39 octets

TraditionalForm@Expand@FromDigits[#,x]&

Essayez-le en ligne!

Il s'avère qu'il y a une fonction intégrée pour entrer dans le bon ordre.

Solution précédente:

Wolfram Language / Mathematica, 93 octets

StringReplace[StringRiffle[ToString/@InputForm/@MonomialList@FromDigits[#,x],"+"],"+-"->"-"]&

Au moins pour moi, cela est étonnamment long pour un langage conçu pour la manipulation mathématique. Il semble que cela Expand@FromDigits[#,x]&devrait fonctionner, mais l'ordre par défaut pour les polynômes est l'inverse de ce que la question nécessite, ce qui nécessite un peu de travail supplémentaire.

Explication

FromDigits[#,x]               converts input list to polynomial (technically converts to a number in base x)
MonomialList@                 gets list of terms of polynomial
InputForm/@                   converts each term to the form a*x^n
ToString/@                    then to a string version of that
StringRiffle[...,"+"]         joins using +'s
StringReplace[...,"+-"->"-"]& replaces +-'s with -'s
DanTheMan
la source
Ne devrait pas SringReplaceêtre StringReplace?
Scott Milner
@ScottMilner Ça a été une erreur quand je l'ai copié. Merci de l'avoir remarqué!
DanTheMan
3

Python3: 150 146 octets

f=lambda l:''.join('+-'[a<0]+str(a)[a<0:5*((abs(a)!=1)|(1>i))]+'x^'[:i]+str(i)[:i-1]for i,a in zip(range(len(l)-1,-1,-1),l)if a).lstrip('+')or '0'

(implémentations précédentes):

f=lambda l: ''.join('+-'[a<0]+str(a)[a<0:5*((abs(a)!=1)|(1>i))]+'x^'[:i]+str(i)[:i-1] for i,a in zip(range(len(l)-1,-1,-1),l) if a).lstrip('+') or '0'

Vous pouvez l' essayer en ligne

Félicitations à: @Benjamin

Willem Van Onsem
la source
1
Arhg, m'a eu! Vous le réduisez par 4 en supprimant des espaces:f=lambda l:''.join('+-'[a<0]+str(a)[a<0:5*((abs(a)!=1)|(1>i))]+'x^'[:i]+str(i)[:i-1]for i,a in zip(range(len(l)-1,-1,-1),l)if a).lstrip('+')or '0'
Benjamin
3

Perl 5 -a , 94 octets

($_=shift@F)&&push@a,@a*!/-/>0&&'+',@F?s/\b1\b//r:$_,@F>0&&'x',@F>1&&'^'.@F while@F;say@a?@a:0

Essayez-le en ligne!

Xcali
la source
Ne semble pas fonctionner correctement si le coefficient final (constant) est 1 ou -1.
Nwellnhof
Dang. J'ai dû casser ça pendant que je jouais au golf. Fixé avec quelques octets de plus.
Xcali
2

Retina 0.8.2 , 113 octets

\w+
a$'b$&
a( [^b ]*)*?b(\d+)
$2x^$#1
(\^1|x\^0)(?!\d)

(?<= |-|^)(1(?=x)|0[^ -]*)

([ -])*
$1
[ -]$|^ 

^$
0
 
+

Essayez-le en ligne!

Je suis sûr qu'il y a beaucoup à jouer au golf ici ...

ovs
la source
2

Haskell , 166 163 octets

g s|l<-length s,v:w:r<-id=<<["- +"!!(1+signum m):(id=<<[show$abs m|abs m>1||e==0]++["x"|e>0]++['^':show e|e>1])|(e,m)<-zip[l-1,l-2..]s,m/=0]=[v|v>'+']++w:r|1<3="0"

Essayez-le en ligne! Exemple d'utilisation: g [0,-1,35,0]rendements "-x^2+35x".


La solution précédente de 166 octets, qui est légèrement mieux lisible:

0#n=show n
m#n=id=<<[show n|n>1]++"x":['^':show m|m>1]
m%0=""
m%n|n<0='-':m#(-n)|1<3='+':m#n
g s|l<-length s,v:m:r<-id=<<zipWith(%)[l-1,l-2..]s=[v|v>'+']++m:r|1<3="0"

Essayez-le en ligne!

Laikoni
la source
2

Ruby , 111 octets

->a{i=a.size;s=a.map{|x|i-=1;"%+d"%x+[?x,"x^#{i}",""][i<=>1]if x!=0}*'';s[0]?s.gsub(/(?<!\d)1(?=x)|^\+/,""):?0}

Essayez-le en ligne!

Résoudre cela en Ruby s’est avéré un peu frustrant, principalement parce que, contrairement à la plupart des langues, en Ruby (presque), tout est en vérité, y compris les 0-s et les chaînes vides, de sorte que même un simple contrôle de zéro devient nul aussi petit que x? .

J'ai joué avec différentes méthodes de construction de la corde, et finalement j'ai choisi plusieurs approches:

  • Les termes avec 0 coefficients sont supprimés en utilisant un simple conditionnel
  • +et les -signes sont générés par la syntaxe de formatage avec signe forcé:%+d
  • La forme correcte ou x^iest sélectionnée à l'aide de l'indexation d'opérateur de fusée[...][i<=>1]
  • Les + et les 1-s inutiles sont supprimés par les remplacements de regex
Kirill L.
la source
2

Husk , 44 43 41 40 octets

|s0Ψf¤|□ṁ`:'+f¹zμ+↓s²_&ε²¹↑□¹+"x^"s)¹m←ṡ

Essayez-le en ligne!

Cela semble un peu maladroit; Husk n'est pas optimisé pour la manipulation de chaîne. J'ai emprunté quelques idées à la réponse Stax .

Explication

         Implicit input, say L = [2,-3,0,-1].
         First we compute the exponents.
ṡ        Reversed indices: [4,3,2,1]
m←       Decrement each: [3,2,1,0]
         Then we format the individual terms of the polynomial.
zμ...)¹  Zip with L using two-argument lambda:
          Arguments are coefficient and index, say C = -3 and I = 2.
+"x^"s    Convert I to string and concatenate to "x^": "x^2"
↑□¹       Take first I*I characters (relevant when I = 0 or I = 1): "x^2"
_&ε²¹     Check if abs(C) <= 1 and I != 0, negate; returns -1 if true, 0 if false.
↓s²       Convert C to string and drop that many elements (from the end, since negative).
          Result: "-3"
          The drop is relevant if C = 1 or C = -1.
+         Concatenate: "-3x^2"
         Result of zipping is ["2x^3","-3x^2","x","-1"]
f¹       Keep those where the corresponding element of L is nonzero: ["2x^3","-3x^2","-1"]
         Next we join the terms with + and remove extraneous +s.
ṁ        Map and concatenate
`:'+      appending '+': "2x^3+-3x^2+-1+"
Ψf       Adjacent filter: keep those chars A with right neighbor B
¤|□       where at least one of A or B is alphanumeric: "2x^3-3x^2-1"
|s0      Finally, if the result is empty, return "0" instead.
Zgarb
la source
2

Perl 6 , 97 octets

{$!=+$_;.map({('+'x?($_&&$++&$_>0)~.substr(--$!&&2>.abs)~(<<''x>>[$!]//'x^'~$!))x?$_}).join||'0'}

Essayez-le en ligne!

Explication:

$!=+$_;

$! garde la trace de l'exposant actuel.

'+'x?($_&&$++&$_>0)

Ajouter +avant les coefficients positifs, sauf s’il s’agit du premier non nul. Le $_&&court-circuit permet de s'assurer que la variable d'état anonyme $n'est incrémentée que pour des coefficients non nuls. La &jonction est effondrée lorsqu'elle est contrainte à Bool ?.

.substr(--$!&&2>.abs)

Décrémenter $!. Couper le coefficient 1 ou -1 sauf s'il est constant.

<<''x>>[$!]//'x^'~$!

Termes linéaires et constants dans des cas spéciaux. L'utilisation de la << >> construction de protection des guillemets est inférieure d'un octet à l'équivalent ('','x')ou 2>$!??'x'x$!!!'x^'~$!.

x?$_

Cachez les termes nuls, mais évaluez toujours l'expression précédente pour l' --$!effet secondaire.

||'0'

Renvoie 0si tous les coefficients sont nuls.

Nwellnhof
la source
2

Java 8, 202 176 174 173 octets

a->{String r="";int j=a.length;for(int i:a)r+=i==0*j--?"":"+"+i+(j<1?"":j<2?"x":"x^"+j);return r.isEmpty()?"0":r.substring(1).replace("+-","-").replaceAll("(\\D)1x","$1x");}
  • 26 octets grâce à @Nevay .

Explication:

Essayez-le en ligne.

a->{                     // Method with String-array parameter and String return-type
  String r="";           //  Result-String, starting empty
  int j=a.length;        //  Power-integer, starting at the size of the input-array
  for(int i:a)           //  Loop over the array
    r+=i==0              //   If the current item is 0
           *j--?         //   (And decrease `j` by 1 at the same time)
        ""               //    Append the result with nothing
       :                 //   Else:
        "+"              //    Append the result with a "+",
        +i               //    and the current item,
        +(j<1?           //    +If `j` is 0:
           ""            //      Append nothing more
          :j<2?          //     Else-if `j` is 1:
           "x"           //      Append "x"
          :              //     Else:
           "x^"+j);      //      Append "x^" and `j`
  return r.isEmpty()?    //  If `r` is still empty
    "0"                  //   Return "0"
   :                     //  Else:
    r.substring(1)       //   Return the result minus the leading "+",
     .replace("+-","-")  //   and change all occurrences of "+-" to "-",
     .replaceAll("(\\D)1x","$1x");}
                         //   and all occurrences of "1x" to "x"
Kevin Cruijssen
la source
1
176 octets:a->{String r="";int j=a.length;for(int u:a)r+=u==(j^j--)?"":"+"+u+(j<1?"":j<2?"x":"x^"+j);return r.isEmpty()?"0":r.substring(1).replace("+-","-").replaceAll("([+-])1x","$1x");}
Nevay
1
@ Nevay Je réalise seulement maintenant que toutes les entrées sont des entiers. J'ai utilisé une entrée String car je pensais que les entrées décimales étaient également autorisées ..>.> Quoi qu'il en soit, merci pour les -26 octets. Et j'ai été capable de jouer 2 autres en changeant (j^j--)pour 0*j--.
Kevin Cruijssen
2

Python, 165 octets

lambda a:"".join([("+"if c>0 and i+1<len(a)else"")+(str(c)if i==0 or abs(c)!=1 else "")+{0:"",1:"x"}.get(i,"x^"+str(i))for i,c in enumerate(a[::-1])if c][::-1])or"0"
poivré
la source
1

PHP, 213 octets

$p=0;for($i=count($a=array_reverse(explode(',',trim($argv[1],'[]'))))-1;$i>=0;$i--)if(($b=(float)$a[$i])||(!$i&&!$p)){$k=abs($b);echo ($b<0?'-':($p?'+':'')).((($k!=1)||!$i)?$k:'').($i>1?'x^'.$i:($i?'x':''));$p=1;}

Argument de ligne de commande comme demandé par OP (argument unique avec des crochets et des virgules).

Joli imprimé et quelques explications:

$p = false; /* No part of the polynomial has yet been printed. */
for ($i = count($a = array_reverse(explode(',',trim($argv[1],'[]')))) - 1; $i >= 0; $i--)
{
    $b = (float)$a[$i]; /* Cast to float to avoid -0 and numbers like 1.0 */
    if (($b != 0) or (($i == 0) and !$p)) /* Print, if $b != 0 or the constant if there is no part until here. */
    {
        $k = abs($b);
        echo ($b < 0 ? '-' : ( $p ? '+' : '')); /* Sign. The first sign is suppressed (if $p is false) if $b positive. */
        echo ((($k != 1) || ($i == 0)) ? $k : '');  /* Coefficient */
        echo ($i > 1 ? 'x^' . $i : (($i != 0) ? 'x' : ''));  /* x^3, x^2, x, constant with empty string. */
        $p = true; /* Part of the polynomial has been printed. */
    }
}
rexkogitans
la source
1

PowerShell, 295 octets

$c=$args[0]
$p=$c.length-1
$i=0
$q=""
while($p -ge 0){$t="";$e="";$d=$c[$i];switch($p){0{$t=""}1{$t="x"}Default{$t="x^";$e=$p}}if($d-eq 0){$t=""}elseif($d-eq 1){$t="+$t$e"}elseif($d-eq-1){$t="-$t$e"}elseif($d-lt 0 -or$i -eq 0){$t="$d$t$e"}else{$t="+$d$t$e"}$q+=$t;$i++;$p--}if($q -eq""){$q=0}
$q
Allen Fisher
la source