Polinomios de impresión bonita

38

Introducción

Los humanos son una especie notable, pero a veces podemos ser muy incómodos de entender, especialmente para las computadoras. En particular, parece que nos gusta escribir polinomios de una manera muy complicada con reglas aparentemente arbitrarias.

¿Cuál es el programa más corto que puede escribir para formatear un polinomio correctamente usando estas reglas?

Reto

Entrada

Una lista de enteros entre -1000 y 1000 (inclusive), que representan los coeficientes de un polinomio, siendo la última entrada el coeficiente de x ^ 0 (la constante), la segunda última es el coeficiente de x ^ 1, etc.

Salida

Una cadena que representa este polinomio en la notación matemática formateada correctamente de humanos.

Reglas:

  • El signo en el coeficiente principal solo se muestra si es negativo.

Right: -x^2+3

Wrong: +x^2+3

  • Los componentes con coeficiente de 0 no se imprimen (excepto en el caso de la esquina donde todos los coeficientes son 0 *).

Right: x^5-x^2+3

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

  • Los coeficientes -1y +1se mostrarán sin el 1, a menos que sean la constante.

Right: x^5-x^2+1

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

  • El exponente solo se muestra si es mayor que 1 y la variable solo se muestra si el exponente es mayor que 0.

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

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

  • * Caso de esquina: si bien los valores cero generalmente no imprimen ese componente, si todos los coeficientes son cero, se debe imprimir la constante 0.

Right: 0

Wrong: 0x+0

Wrong: (nothing)

  • Este es el código de golf, por lo que el ganador será el programa con la menor cantidad de bytes.

Ejemplo de entrada y salida

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

Espero ver sus soluciones. ¡Que te diviertas!

EDITAR:

  • Puede rodear las operaciones con espacios en blanco si lo desea. Entonces, 3x+5y 3x + 5ambos están bien. 3x+ 5y 3x +5no lo son
  • Si desea producir caracteres exponentes reales (digamos en Tex), eso está permitido, ya que está aún más cerca de cómo escriben los humanos.
  • Los coeficientes deben aparecer sin decimales, por ejemplo, 9x^2es correcto, 9.0x^2no lo es.
Oisín Moran
fuente
77
Una pregunta que debería haber hecho en el sandbox pero que no hice, ¿podemos imprimir con espacios en blanco entre los operadores? ¿Entonces 3x^2 + 4versus 3x^2+4?
Giuseppe
1
¿Necesitamos emitir exponentes usando carets? ¿O se permitiría producir un carácter superíndice real (por ejemplo, para una respuesta en TeX)?
Tutleman
3
@KevinCruijssen No soy el OP pero diría que no, porque la mayoría de los humanos no escriben así.
ShreevatsaR
2
@ManishKundu Sí, claro, puedes tomar la entrada como cadenas.
Oisín Moran
1
@ OisínMoran Nada cobarde, simplemente asegurarse un simple 1x-> xsustitución no cambia 21x^2en 2x^2.
DLosc

Respuestas:

10

Retina 0.8.2 , 56 bytes

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

\b1x
x
x.1 
x 
 0

 -
-
 
+

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

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

Inserte todos los poderes de x, incluyendo x^1pero no x^0.

\b0x.\d+ 

Eliminar todas las potencias xcon coeficientes cero, pero no un final 0(todavía).

\b1x
x

Eliminar un multiplicador de 1(pero no una constante 1).

x.1 
x 

Eliminar el ^1de x^1.

 0

Eliminar una constante 0 a menos que sea lo único que queda.

 -
-

Eliminar el espacio antes de a -.

 
+

Cambie los espacios restantes a +s.

Neil
fuente
6

JavaScript (ES6), 107 106 bytes

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

Pruébalo en línea!

¿Cómo?

La salida se construye aplicando las siguientes fórmulas a cada coeficiente c de la matriz de entrada a [] mientras se realiza un seguimiento del exponente actual e .

1.a fórmula: signo más

Si el coeficiente es estrictamente positivo y este no es el primer término en la expresión de salida, agregamos un + . De lo contrario, no agregamos nada.

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

2da fórmula: signo menos y coeficiente

Si el exponente es cero o el valor absoluto del coeficiente no es igual a 1, agregamos el coeficiente (que puede incluir un inicio -). De lo contrario, agregamos un- (si el coeficiente es negativo) o nada.

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

3a fórmula: variable y exponente

Si el exponente es 0, no agregamos nada. Si el exponente es 1, añadimos x. De lo contrario, anexamos x^seguido del exponente.

e ? e - 1 ? 'x^' + e : 'x' : _
Arnauld
fuente
Esto falla en este caso: [0,1,35,0], conducirá con + x ^ 2
Makotosan
2
@ Makotosan ¡Gracias por informar esto! Debería estar bien ahora.
Arnauld
5

Stax , 37 bytes

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

Ejecútelo y depúrelo en línea

Aquí está la versión desempaquetada y sin golf.

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

Ejecute este

recursivo
fuente
5

Python 3, 279 277 258 251 bytes

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

Toma la entrada como una lista de cadenas. Esta solución aún no está muy desarrollada. Básicamente, esto funciona reemplazando las cosas para adaptarlas al formato de salida, lo que aumenta considerablemente el recuento de bytes.

¡Pruébelo en línea!

Un agradecimiento especial a los ovs y NK1406 .

Manish Kundu
fuente
Se corrigieron todos los errores.
Manish Kundu
Puede reordenar sus controles de igualdad para hacerlos if'0'!=iy if'-1'==i.
Zacharý
258 bytes
ovs
@ovs muchas gracias
Manish Kundu
4

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

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

Pruébalo en línea!

-4 bytes gracias a @dzaima!

Esto definitivamente se puede reducir aún más. Esto requiere⎕IO←0

Zacharý
fuente
Finalmente me afeité esos dos bytes ...
Zacharý
3

Pip , 78 bytes

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

Toma los coeficientes como argumentos de línea de comandos. Pruébalo en línea!

Utiliza ME(map-enumerate) y J(join) para generar algo de la forma 0x^3+-1x^2+35x^1+0x^0, y luego un montón de reemplazos de expresiones regulares para transformar esto en el formato adecuado.

DLosc
fuente
3

Python 3, 161 162 bytes

Se corrigió un error gracias a los 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'

Expandido:

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
fuente
3

C # , 237 bytes

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
fuente
1
Bienvenido a PPCG!
Martin Ender
3

Limpio , 172 bytes

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])))

Pruébalo en línea!

Οurous
fuente
@BMO arreglado temporalmente en espera de más golf.
Οurous
3

Wolfram Language / Mathematica, 39 bytes

TraditionalForm@Expand@FromDigits[#,x]&

Pruébalo en línea!

Resulta que hay un incorporado para entrar en el orden correcto.

Solución previa:

Wolfram Language / Mathematica, 93 bytes

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

Al menos para mí, esto es sorprendentemente largo para un lenguaje diseñado para la manipulación matemática. Parece queExpand@FromDigits[#,x]& debería funcionar, pero el orden predeterminado para los polinomios es el reverso de lo que requiere la pregunta, por lo que se requiere un poco de determinación adicional.

Explicación

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
fuente
No debe SringReplaceser StringReplace?
Scott Milner
@ScottMilner Debe haber sido un error cuando lo estaba copiando. Gracias por notarlo!
DanTheMan
3

Python3: 150 146 bytes

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'

(implementaciones anteriores):

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'

Puedes probarlo en línea

Felicitaciones a: @Benjamin

Willem Van Onsem
fuente
1
Arhg, me tienes! Lo derribas en 4 eliminando algunos espacios: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 bytes

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

Pruébalo en línea!

Xcali
fuente
No parece funcionar correctamente si el coeficiente final (constante) es 1 o -1.
nwellnhof
Dang Debe haberlo roto mientras jugaba al golf. Lo arreglé con unos pocos bytes más.
Xcali
2

Retina 0.8.2 , 113 bytes

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

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

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

^$
0
 
+

Pruébalo en línea!

Estoy seguro de que hay mucho para jugar golf aquí ...

ovs
fuente
2

Haskell , 166 163 bytes

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"

Pruébalo en línea! Ejemplo de uso: g [0,-1,35,0]rendimientos "-x^2+35x".


Solución anterior de 166 bytes, que es ligeramente mejor legible:

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"

Pruébalo en línea!

Laikoni
fuente
2

Ruby , 111 bytes

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

Pruébalo en línea!

Resolver esto en Ruby resultó ser un poco frustrante, principalmente debido al hecho de que, a diferencia de la mayoría de los idiomas, en Ruby (casi) todo es verdad, incluidos 0-sy cadenas vacías, de modo que incluso una simple comprobación de cero no se acerca. tan corto como x? .

Jugué con varios métodos de construcción de la cadena, y finalmente me decidí por una combinación de varios enfoques:

  • Los términos con coeficientes 0 se eliminan usando un condicional simple
  • +y los -signos se producen formateando la sintaxis con signo forzado:%+d
  • La forma correcta o x^ise selecciona mediante la indexación del operador de cohete[...][i<=>1]
  • Los reemplazos regex eliminan los signos principales + e innecesarios de 1 s
Kirill L.
fuente
2

Casco , 44 43 41 40 bytes

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

Pruébalo en línea!

Esto se siente un poco torpe; Husk no está optimizado para la manipulación de cadenas. Tomé prestadas algunas ideas de la respuesta Stax .

Explicación

         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
fuente
2

Perl 6 , 97 bytes

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

Pruébalo en línea!

Explicación:

$!=+$_;

$! realiza un seguimiento del exponente actual.

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

Agregue +antes de los coeficientes positivos, excepto si es el primero distinto de cero. El $_&&cortocircuito asegura que la variable de estado anónimo $solo se incremente para coeficientes distintos de cero. La &unión se colapsa cuando se obliga a Bool con ?.

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

Decremento $!. Pica el coeficiente 1 o -1 a menos que sea constante.

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

Términos lineales y constantes de casos especiales. El uso de la << >> construcción de protección de comillas es un byte más corto que el equivalente ('','x')o 2>$!??'x'x$!!!'x^'~$!.

x?$_

Oculte los términos cero, pero siempre evalúe la expresión anterior para el --$!efecto secundario.

||'0'

Devuelve 0si todos los coeficientes son cero.

nwellnhof
fuente
2

Java 8, 202 176 174 173 bytes

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 bytes gracias a @Nevay .

Explicación:

Pruébalo en línea.

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
fuente
1
176 bytes: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 Solo ahora me doy cuenta de que todas las entradas son números enteros ... Utilicé una entrada de cadena porque pensé que las entradas decimales también estaban permitidas ...>.> De todos modos, gracias por los -26 bytes. Y he podido jugar golf 2 más al cambiar (j^j--)a 0*j--.
Kevin Cruijssen
2

Python, 165 bytes

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"
pppery
fuente
1

PHP, 213 bytes

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

Argumento de línea de comando según lo solicitado por OP (argumento único con corchetes y comas).

Bonito estampado y alguna explicación:

$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
fuente
1

PowerShell, 295 bytes

$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
fuente