Multiplicar dos polinomios enteros


14

Su tarea es tomar dos expresiones polinómicas enteras de una sola variable y multiplicarlas en su expansión de izquierda a derecha principal no simplificada de primer término (AKA FOIL en el caso de binomios). No combine términos similares ni reordene el resultado. Para ser más explícito sobre la expansión, multiplique el primer término en la primera expresión por cada término en el segundo, en orden, y continúe en la primera expresión hasta que todos los términos se hayan multiplicado por todos los demás términos. Las expresiones se darán en una variante simplificada de LaTeX.

Cada expresión será una secuencia de términos separados por +(con exactamente un espacio en cada lado) Cada término se ajustará a la siguiente expresión regular: (notación PCRE)

-?\d+x\^\d+

En inglés simple, el término es un encabezado opcional -seguido de uno o más dígitos seguidos de xuna potencia entera no negativa (con^ )

Un ejemplo de una expresión completa:

6x^3 + 1337x^2 + -4x^1 + 2x^0

Cuando se conecta a LaTeX, obtiene 6x3+1337x2+-4 4X1+2X0 0

La salida también debe cumplir con este formato.

Dado que los corchetes no rodean exponentes en este formato, LaTeX realmente representará exponentes de varios dígitos de manera incorrecta. (p. ej., se 4x^3 + -2x^14 + 54x^28 + -4x^5representa como 4 4X3+-2X14 4+54X28+-4 4X5 5 ) No es necesario que tenga en cuenta esto y no debe incluir los corchetes en su salida.

Ejemplos de casos de prueba

5x^4
3x^23

15x^27

6x^2 + 7x^1 + -2x^0
1x^2 + -2x^3

6x^4 + -12x^5 + 7x^3 + -14x^4 + -2x^2 + 4x^3

3x^1 + 5x^2 + 2x^4 + 3x^0
3x^0

9x^1 + 15x^2 + 6x^4 + 9x^0

4x^3 + -2x^14 + 54x^28 + -4x^5
-0x^7

0x^10 + 0x^21 + 0x^35 + 0x^12

4x^3 + -2x^4 + 0x^255 + -4x^5
-3x^4 + 2x^2

-12x^7 + 8x^5 + 6x^8 + -4x^6 + 0x^259 + 0x^257 + 12x^9 + -8x^7

Reglas y Suposiciones

  • Puede suponer que todas las entradas se ajustan a este formato exacto. El comportamiento para cualquier otro formato no está definido para los propósitos de este desafío.
    • Cabe señalar que cualquier método para tomar los dos polinomios es válido, siempre que ambos se lean como cadenas que se ajusten al formato anterior.
  • El orden de los polinomios es importante debido al orden esperado de expansión del producto.
  • Debe admitir coeficientes de entrada entre 128 y 127 y exponentes de entrada de hasta 255 .
    • Por lo tanto, deben admitirse coeficientes de salida entre 16,256 y 16,384 y exponentes de hasta 510 .
  • Puede suponer que cada polinomio de entrada contiene no más de 16 términos
    • Por lo tanto, debe (como mínimo) admitir hasta 256 términos en la salida
  • Los términos con coeficientes cero deben dejarse como están, con los exponentes combinados adecuadamente
  • Se permite el cero negativo en la entrada, pero no se puede distinguir semánticamente del cero positivo. Siempre da salida a cero positivo. No omita los términos cero.

¡Feliz golf! ¡Buena suerte!



2
@LuisfelipeDejesusMunoz Me imagino que no. El análisis es una parte integral del desafío y el OP dice: "Debe tenerse en cuenta que cualquier método de capturar los dos polinomios es válido, siempre que ambos se lean como cadenas que se ajusten al formato anterior " (énfasis agregado).
Giuseppe

Respuestas:


4

R , 159 153 148 bytes

function(P,Q,a=h(P),b=h(Q))paste0(b[1,]%o%a[1,],"x^",outer(b,a,"+")[2,,2,],collapse=" + ")
h=function(s,`/`=strsplit)sapply(el(s/" . ")/"x.",strtoi)

Pruébalo en línea!

Tenía muchas ganas de usar outer, por lo que es casi seguro que haya un enfoque más eficiente.


4

Haskell , 131122 bytes

(%)=drop
f s=do(a,t)<-reads s;(i,u)<-reads$2%t;(a,i):f(3%u)
p!q=3%do(a,i)<-f p;(b,j)<-f q;" + "++shows(a*b)"x^"++show(i+j)

Pruébalo en línea!

fanaliza un polinomio de una cadena, !multiplica dos de ellos y formatea el resultado.

H.PWiz guardó 9 bytes. ¡Gracias!

Sin golf

type Monomial = (Int, Int) -- a^i
type Polynomial = [Monomial]

parse :: String -> Polynomial
parse s = do (a, s')  <- reads s
             (i, s'') <- reads (drop 2 s')
             (a, i) : parse (drop 3 s'')

(!) :: String -> String -> String
p!q = drop 3 (concat terms)
  where terms    = [term (a*b) (i+j) | (a,i) <- p', (b,j) <- q']
        term a i = concat [" + ", show a, "x^", show i]
        p'       = parse p
        q'       = parse q



2

Ruby , 102 100 98 bytes

->a,b{a.scan(w=/(.*?)x.(\d+)/).map{|x|b.scan(w).map{|y|(eval"[%s*(z=%s;%s),z+%s]"%y+=x)*"x^"}}*?+}

Pruébalo en línea!

¿Cómo?

Primer paso: obtener todos los números de ambos polinomios: scandevuelve los números como una matriz de pares de cadenas. Luego, haga un producto cartesiano de las 2 listas. Ahora tenemos todos los números donde los necesitamos, pero aún en el orden incorrecto.

Ejemplo: si multiplicamos 3x^4por -5x^2, obtenemos los números como [["3","4"],["-5","2"]], la primera idea era comprimir y aplanar esta lista, y luego poner los números en una expresión para ser evaluados como [3*-5, 4+2]. En realidad, no necesitamos reordenar los números, podríamos hacerlo dentro de la expresión usando una variable temporal: la expresión se convierte en [3*(z=4,-5),z+2].

Después de evaluar estas expresiones, obtenemos el coeficiente y el exponente, necesitamos unirlos usando "x^", y luego unir todos los elementos usando "+".


2

Haskell, 124 121 bytes

import Data.Lists
f!x=map f.splitOn x
z=read!"x^"!"+"
a#b=drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)

Nota: TIO carece Data.Lists, así que importo Data.Lists.Splity Data.List: ¡ Pruébelo en línea!

Editar: -3 bytes gracias a @Lynn.


¡Esto es en realidad 123 bytes! f!x=map f.splitOn xy luego z=read!"x^"!"+"guarda un byte; para la última línea drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)ahorra dos más. 120 bytes
Lynn

1
@ Lynn: la versión TIO importa en Data.Listlugar de Data.Lists, por lo que es +1 byte.
nimi



1

Python 2 , 193 bytes

import re
f=re.finditer
lambda a,b:' + '.join(' + '.join(`int(m.group(1))*int(n.group(1))`+'x^'+`int(m.group(2))+int(n.group(2))`for n in f('(-?\d+)x\^(\d+)',b))for m in f('(-?\d+)x\^(\d+)',a))

Pruébalo en línea!

Nota al margen: la primera vez que hago un desafío de golf de código, lo siento si el intento apesta jaja


3
Bienvenido a PPCG! No soy un gran programador de Python, pero probablemente haya margen de mejora. ¡Quizás pueda encontrar ayuda en Tips for Golfing en Python o Tips for Golfing en <todos los idiomas> ! Espero que disfrutes el tiempo que pasas aquí :-)
Giuseppe


1
Un poco de golf rápido para 161 bytes . Aunque mirando las otras respuestas de Python, re.finditerpodría no ser el enfoque más corto
Jo King

1

Retina , 110 bytes

\S\S+(?=.*\n(.+))
 $1#$&
|" + "L$v` (-?)(\d+)x.(\d+).*?#(-?)(\d+)x.(\d+)
$1$4$.($2*$5*)x^$.($3*_$6*
--|-(0)
$1

Pruébalo en línea! Explicación:

\S\S+(?=.*\n(.+))
 $1#$&

Prefije cada término en la primera entrada con un # , una copia de la segunda entrada y un espacio. Esto significa que todos los términos en las copias de la segunda entrada están precedidos por un espacio y ninguno de los términos de la primera entrada.

|" + "L$v` (-?)(\d+)x.(\d+).*?#(-?)(\d+)x.(\d+)
$1$4$.($2*$5*)x^$.($3*_$6*

Haga coincidir todas las copias de los términos en la segunda entrada y su término correspondiente de la primera entrada. Concatenar cualquier -signo, multiplicar los coeficientes y sumar los índices. Finalmente unir todas las sustituciones resultantes con la cadena +  .

--|-(0)
$1

Eliminar cualquier par de -sy convertir -0a 0.


1

SNOBOL4 (CSNOBOL4) , 192 176 bytes

	P =INPUT
	Q =INPUT
	D =SPAN(-1234567890)
P	P D . K ARB D . W REM . P	:F(O)
	B =Q
B	B D . C ARB D . E REM . B	:F(P)
	O =O ' + ' K * C 'x^' W + E	:(B)
O	O ' + ' REM . OUTPUT
END

Pruébalo en línea!

	P =INPUT				;* read P
	Q =INPUT				;* read Q
	D =SPAN(-1234567890)			;* save PATTERN for Digits (or a - sign); equivalent to [0-9\\-]+
P	P D . K ARB D . W REM . P	:F(O)	;* save the Koefficient and the poWer, saving the REMainder as P, or if no match, goto O
	B =Q					;* set B = Q
B	B D . C ARB D . E REM . B	:F(P)	;* save the Coefficient and the powEr, saving the REMainder as B, or if no match, goto P
	O =O ' + ' K * C 'x^' W + E	:(B)	;* accumulate the output
O	O ' + ' REM . OUTPUT			;* match ' + ' and OUTPUT the REMainder
END



1

C # (compilador interactivo de Visual C #) , 192 190 bytes

n=>m=>string.Join(g=" + ",from a in n.Split(g)from b in m.Split(g)select f(a.Split(p="x^")[0])*f(b.Split(p)[0])+p+(f(a.Split(p)[1])+f(b.Split(p)[1])));Func<string,int>f=int.Parse;string p,g;

La sintaxis de consulta parece ser un byte más corto que la sintaxis del método.

Pruébalo en línea!


Cada expresión será una secuencia de términos separados por + (con exactamente un espacio en cada lado) 190 bytes
Datos

1

Jalea , 28 bytes

ṣ”+ṣ”xV$€)p/ZPSƭ€j⁾x^Ʋ€j“ + 

Pruébalo en línea!

Programa completo Toma los dos polinomios como una lista de dos cadenas.

Explicación (forma expandida)

ṣ”+ṣ”xV$€µ€p/ZPSƭ€j⁾x^Ʋ€j“ + ” Arguments: x
         µ                     Monadic chain.
          €                    Map the monadic link over the argument.
                               Note that this will "pop" the previous chain, so
                               it will really act as a link rather than a
                               sub-chain.
ṣ”+                             ṣ, right = '+'.
                                Split the left argument on each occurrence of
                                the right.
                                Note that strings in Jelly are lists of
                                single-character Python strings.
        €                       Map the monadic link over the argument.
       $                         Make a non-niladic monadic chain of at least
                                 two links.
   ṣ”x                            ṣ, right = 'x'.
                                  Split the left argument on each occurrence of
                                  the right.
      V                           Evaluate the argument as a niladic link.
            /                  Reduce the dyadic link over the argument.
           p                    Cartesian product of left and right arguments.
                       €       Map the monadic link over the argument.
                      Ʋ         Make a non-niladic monadic chain of at least
                                four links.
             Z                   Transpose the argument.
                 €               Map the monadic link over the argument.
                ƭ                 At the first call, call the first link. At the
                                  second call, call the second link. Rinse and
                                  repeat.
              P                    Product: ;1×/$
               S                   Sum: ;0+/$
                  j⁾x^           j, right = "x^".
                                 Put the right argument between the left one's
                                 elements and concatenate the result.
                        j“ + ” j, right = " + ".
                               Put the right argument between the left one's
                               elements and concatenate the result.

Aliasing

)es el mismo que µ€.
Un final está implícito y puede omitirse.

Algoritmo

Digamos que tenemos esta entrada:

["6x^2 + 7x^1 + -2x^0", "1x^2 + -2x^3"]

El primer procedimiento es el análisis, aplicado a cada uno de los dos polinomios. Manejemos el primero,"6x^2 + 7x^1 + -2x^0" :

El primer paso es dividir la cadena por '+', para separar los términos. Esto resulta en:

["6x^2 ", " 7x^1 ", " -2x^0"]

El siguiente paso es dividir cada cadena por 'x' , para separar el coeficiente del exponente. El resultado es este:

[["6", "^2 "], [" 7", "^1 "], [" -2", "^0"]]

Actualmente, parece que hay mucha basura en estas cadenas, pero esa basura en realidad no es importante. Estas cadenas se evaluarán como enlaces Jelly niládicos. Trivialmente, los espacios no son importantes, ya que no están entre los dígitos de los números. Así que también podríamos evaluar lo siguiente y seguir obteniendo el mismo resultado:

[["6", "^2"], ["7", "^1"], ["-2", "^0"]]

Los ^s se ven un poco más inquietante, pero que en realidad no hacen nada, ya sea! Bueno, ^es el átomo XOR bit a bit, sin embargo, las cadenas niládicas actúan como enlaces monádicos, excepto que el primer enlace en realidad se convierte en el argumento, en lugar de tomar un argumento, si es niládico. Si no es así, el enlace tendrá un argumento de 0. Los exponentes tienen la ^s como su primer carácter, y ^no es niládica, por lo que se supone que el argumento es 0. El resto de la cadena, es decir, el número, es el argumento correcto de ^. Entonces, por ejemplo, ^2es0 0 XOR 2=2. Obviamente,0 0 XOR norte=norte. Todos los exponentes son enteros, por lo que estamos bien. Por lo tanto, evaluar esto en lugar de lo anterior no cambiará el resultado:

[["6", "2"], ["7", "1"], ["-2", "0"]]

Aquí vamos:

[[6, 2], [7, 1], [-2, 0]]

Este paso también se convertirá "-0"a 0.

Como estamos analizando ambas entradas, el resultado después del análisis será este:

[[[6, 2], [7, 1], [-2, 0]], [[1, 2], [-2, 3]]]

El análisis ahora está completo. El siguiente procedimiento es la multiplicación.

Primero tomamos el producto cartesiano de estas dos listas:

[[[6, 2], [1, 2]], [[6, 2], [-2, 3]], [[7, 1], [1, 2]], [[7, 1], [-2, 3]], [[-2, 0], [1, 2]], [[-2, 0], [-2, 3]]]

Se forman muchos pares, cada uno con un elemento de la lista de la izquierda y uno de la derecha, en orden. Esto también pasa a ser el orden previsto de la salida. Este desafío realmente nos pide que apliquemos la distributividad multiplicativa, ya que se nos pide que no procesemos más el resultado después de eso.

Los pares en cada par representan términos que queremos multiplicar, siendo el primer elemento el coeficiente y el segundo el exponente. Para multiplicar los términos, multiplicamos los coeficientes y sumamos los exponentes (unXCsiXre=unsiXCXre=unsi(XCXre)=(unsi)XC+re) ¿Como hacemos eso? Manejemos el segundo par,[[6, 2], [-2, 3]] .

Primero transponemos el par:

[[6, -2], [2, 3]]

Luego tomamos el producto del primer par y la suma del segundo:

[-12, 5]

La parte relevante del código, PSƭ€ realidad, no restablece su contador para cada par de términos, pero, dado que son pares, no es necesario.

Manejando todos los pares de términos, tenemos:

[[6, 4], [-12, 5], [7, 3], [-14, 4], [-2, 2], [4, 3]]

Aquí, la multiplicación se realiza, ya que no tenemos que combinar términos similares. El procedimiento final es el Prettyfying.

Primero unimos cada par con "x^":

[[6, 'x', '^', 4], [-12, 'x', '^', 5], [7, 'x', '^', 3], [-14, 'x', '^', 4], [-2, 'x', '^', 2], [4, 'x', '^', 3]]

Luego nos unimos a la lista con " + ":

[6, 'x', '^', 4, ' ', '+', ' ', -12, 'x', '^', 5, ' ', '+', ' ', 7, 'x', '^', 3, ' ', '+', ' ', -14, 'x', '^', 4, ' ', '+', ' ', -2, 'x', '^', 2, ' ', '+', ' ', 4, 'x', '^', 3]

Observe cómo todavía tenemos números en la lista, por lo que no es realmente una cadena. Sin embargo, Jelly tiene un proceso llamado "stringificación", que se ejecutó justo al final de la ejecución de un programa para imprimir el resultado. Para una lista de profundidad 1, realmente solo convierte cada elemento en su representación de cadena y concatena las cadenas juntas, por lo que obtenemos el resultado deseado:

6x^4 + -12x^5 + 7x^3 + -14x^4 + -2x^2 + 4x^3

1

JavaScript, 112 110 bytes

Encontré dos alternativas con la misma longitud. Llamada con sintaxis curry:f(A)(B)

A=>B=>(P=x=>x.split`+`.map(x=>x.split`x^`))(A).flatMap(a=>P(B).map(b=>a[0]*b[0]+'x^'+(a[1]- -b[1]))).join` + `

A=>B=>(P=x=>x.split`+`.map(x=>x.split`x^`))(A).flatMap(([c,e])=>P(B).map(([C,E])=>c*C+'x^'+(e- -E))).join` + `

-2 bytes ( Luis ): Eliminar espacios alrededor del splitdelimitador.


JavaScript, 112 bytes

Utilizando String.prototype.matchAll.

A=>B=>(P=x=>[...x.matchAll(/(\S+)x.(\S+)/g)])(A).flatMap(a=>P(B).map(b=>a[1]*b[1]+'x^'+(a[2]- -b[2]))).join` + `


1
split' + ' => split'+'guardar 2 bytes
Luis felipe De jesus Munoz


@EmbodimentofIgnorance Lo malo, leí mal el comentario de Luis. Pensé que era sobre el join.
Arnauld
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.