Multiplicar dois polinômios inteiros

14

Sua tarefa é pegar duas expressões polinomiais inteiras de variável única e multiplicá-las em sua expansão principal da esquerda para a direita não simplificada do primeiro termo (AKA FOIL no caso de binômios). Não combine termos semelhantes nem reordene o resultado. Para ser mais explícito sobre a expansão, multiplique o primeiro termo na primeira expressão por cada termo no segundo, em ordem, e continue na primeira expressão até que todos os termos tenham sido multiplicados por todos os outros termos. As expressões serão dadas em uma variante simplificada do LaTeX.

Cada expressão será uma sequência de termos separados por +(com exatamente um espaço de cada lado). Cada termo estará em conformidade com a seguinte expressão regular: (notação PCRE)

-?\d+x\^\d+

Em inglês simples, o termo é um líder opcional -seguido por um ou mais dígitos seguidos por xe um número inteiro não negativo (com ^)

Um exemplo de uma expressão completa:

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

Quando conectado ao LaTeX, você obtém 6x3+1337x2+-4x1+2x0 0

A saída também deve estar em conformidade com este formato.

Como os colchetes não envolvem expoentes nesse formato, o LaTeX renderiza expoentes de vários dígitos incorretamente. (por exemplo, é 4x^3 + -2x^14 + 54x^28 + -4x^5processado como 4x3+-2x14+54x28+-4x5 ) Você não precisa dar conta disso e não deve incluir os colchetes na saída.

Casos de teste de exemplo

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

Regras e premissas

  • Você pode assumir que todas as entradas estão em conformidade com este formato exato. O comportamento para qualquer outro formato é indefinido para os propósitos deste desafio.
    • Deve-se notar que qualquer método de captura dos dois polinômios é válido, desde que ambos sejam lidos como cadeias de caracteres em conformidade com o formato acima.
  • A ordem dos polinômios é importante devido à ordem esperada da expansão do produto.
  • Você deve suportar coeficientes de entrada entre -128 e 127 e expoentes de entrada até 255 .
    • Coeficientes de saída entre -16,256 e 16,384 e expoentes até 510 devem, portanto, ser suportados.
  • Você pode assumir que cada polinômio de entrada contém no máximo 16 termos
    • Portanto, você deve (no mínimo) suportar até 256 termos na saída
  • Termos com coeficientes zero devem ser deixados como estão, com os expoentes sendo combinados adequadamente
  • O zero negativo é permitido na entrada, mas é indistinguível do zero positivo semântica. Sempre emita zero positivo. Não omita zero termos.

Golfe feliz! Boa sorte!

Beefster
fonte
1
relacionado
H.PWiz 10/04/19
2
@LuisfelipeDejesusMunoz Imagino que não. A análise é parte integrante do desafio e o OP diz: "Deve-se observar que qualquer método de captura dos dois polinômios é válido, desde que ambos sejam lidos como cadeias de caracteres em conformidade com o formato acima " .
21419 Giuseppe

Respostas:

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)

Experimente online!

Eu realmente queria usar outer, então há quase certamente uma abordagem mais eficiente.

Giuseppe
fonte
4

Haskell , 131 122 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)

Experimente online!

fanalisa um polinômio de uma string, !multiplica dois deles e formata o resultado.

H.PWiz salvou 9 bytes. Obrigado!

Ungolfed

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
Lynn
fonte
129 bytes
H.PWiz 12/04/19
1
ainda melhor
H.PWiz 12/04/19
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^"}}*?+}

Experimente online!

Quão?

Primeiro passo: obtenha todos os números de ambos os polinômios: scanretorna os números como uma matriz de pares de cadeias. Em seguida, faça um produto cartesiano das 2 listas. Agora, temos todos os números onde precisamos deles, mas ainda na ordem errada.

Exemplo: se multiplicarmos 3x^4por -5x^2, obtemos os números como [["3","4"],["-5","2"]], a primeira idéia foi compactar e achatar essa lista e, em seguida, colocar os números em uma expressão a ser avaliada como [3*-5, 4+2]. Na verdade, não precisamos reordenar os números, podemos fazê-lo dentro da expressão usando uma variável temporária: a expressão se torna [3*(z=4,-5),z+2].

Depois de avaliar essas expressões, obtemos o coeficiente e o expoente, precisamos uni-los usando "x^"e, em seguida, unimos todos os tems usando "+".

GB
fonte
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: O TIO não possui Data.Lists, portanto importo Data.Lists.Splite Data.List: Experimente online!

Edit: -3 bytes graças a @Lynn.

nimi
fonte
Na verdade, são 123 bytes! f!x=map f.splitOn xe z=read!"x^"!"+"salva um byte; para a última linha drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)economiza mais dois. 120 bytes
Lynn
1
@ Lynn: a versão do TIO é importada em Data.Listvez de Data.Lists, portanto, é de 1 byte.
Nri
1

JavaScript (Nó Babel) , 118 bytes

Aceita entrada como (a)(b) .

a=>b=>(g=s=>[...s.matchAll(/(-?\d+)x.(\d+)/g)])(a).flatMap(([_,x,p])=>g(b).map(([_,X,P])=>x*X+'x^'+-(-p-P))).join` + `

Experimente online!

Arnauld
fonte
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))

Experimente online!

Nota lateral: Primeira vez em um desafio de código de golfe, desculpe se a tentativa for péssima haha

GotCubes
fonte
3
Bem-vindo ao PPCG! Não sou muito programador em python, mas provavelmente há espaço para melhorias. Talvez você possa encontrar ajuda em Dicas para jogar golfe em Python ou Dicas para jogar golfe em <todos os idiomas> ! Esperamos que você aproveite o tempo que você passa aqui :-)
Giuseppe
Salve 12 bytes
Noodle9
1
Golfe rápido para 161 bytes . Embora olhando para as outras respostas python, re.finditerpode não ser a abordagem mais curto
Jo rei
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

Experimente online! Explicação:

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

Prefixe cada termo na primeira entrada com a #, uma cópia da segunda entrada e um espaço. Isso significa que todos os termos nas cópias da segunda entrada são precedidos por um espaço e nenhum dos termos da primeira entrada é.

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

Combine todas as cópias dos termos na segunda entrada e o termo correspondente da primeira entrada. Concatene quaisquer -sinais, multiplique os coeficientes e adicione os índices. Finalmente, junte todas as substituições resultantes à string  + .

--|-(0)
$1

Exclua quaisquer pares de se -converta -0para 0.

Neil
fonte
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

Experimente online!

	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
Giuseppe
fonte
1

Perl 6 , 114 bytes

{my&g=*.match(/(\-?\d+)x\^(\d+)/,:g)».caps».Map;join " + ",map {"{[*] $_»{0}}x^{[+] $_»{1}}"},(g($^a)X g $^b)}

Experimente online!

bb94
fonte
1
86 bytes
Jo King
1

Python 2 , 130 bytes

lambda a,b:' + '.join([`v*V`+'x^'+`k+K`for V,K in g(a)for v,k in g(b)])
g=lambda s:[map(int,t.split('x^'))for t in s.split(' + ')]

Experimente online!

Chas Brown
fonte
1

C # (compilador interativo do 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;

A sintaxe da consulta parece ser um byte menor que a sintaxe do método.

Experimente online!

Modalidade de ignorância
fonte
Cada expressão irá ser uma sequência de termos separados por + (com exactamente um espaço de cada lado) de 190 bytes
Expirado dados
1

Gelatina , 28 bytes

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

Experimente online!

Programa completo. Toma os dois polinômios como uma lista de duas cadeias.

Explicação (formulário expandido)

ṣ”+ṣ”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.

Alias

)é o mesmo que µ€.
Um final está implícito e pode ser omitido.

Algoritmo

Digamos que temos esta entrada:

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

O primeiro procedimento é a análise, aplicada a cada um dos dois polinômios. Vamos lidar com o primeiro,"6x^2 + 7x^1 + -2x^0" :

O primeiro passo é dividir a string por '+', para separar os termos. Isto resulta em:

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

O próximo passo é dividir cada sequência por 'x', para separar o coeficiente do expoente. O resultado é este:

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

Atualmente, parece que há muito lixo nessas cadeias, mas esse lixo não é realmente importante. Essas seqüências serão avaliadas como links niládicos de geléia. Trivialmente, os espaços não são importantes, pois não estão entre os dígitos dos números. Assim, podemos avaliar o abaixo e ainda assim obter o mesmo resultado:

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

^^0^^0^^20 0 XOR 2=20 0 XOR n=n. Todos os expoentes são inteiros, então estamos bem. Portanto, avaliar isso em vez do acima não mudará o resultado:

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

Aqui vamos nós:

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

Esta etapa também será convertida "-0"para0 .

Como estamos analisando as duas entradas, o resultado após a análise será este:

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

A análise está concluída. O próximo procedimento é a multiplicação.

Primeiro, tomamos o produto cartesiano dessas duas 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]]]

Muitos pares são feitos, cada um com um elemento da lista da esquerda e um da direita, em ordem. Isso também é a ordem pretendida da saída. Esse desafio realmente nos pede para aplicar a distributividade multiplicativa, pois somos solicitados a não processar o resultado depois disso.

umaxcbxd=umabxcxd=umab(xcxd)=(umab)xc+d[[6, 2], [-2, 3]]

Primeiro, transpomos o par:

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

Depois, pegamos o produto do primeiro par e a soma do segundo:

[-12, 5]

A parte relevante do código, PSƭ€na verdade, não redefine seu contador para cada par de termos, mas, como são pares, não é necessário.

Manipulando todos os pares de termos, temos:

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

Aqui, a multiplicação é feita, pois não precisamos combinar termos semelhantes. O procedimento final é o Prettyfying.

Primeiro unimos cada par com "x^":

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

Em seguida, ingressamos na lista com " + ":

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

Observe como ainda temos números na lista, portanto não é realmente uma string. No entanto, o Jelly possui um processo chamado "stringification", executado no final da execução de um programa para imprimir o resultado. Para uma lista da profundidade 1, ele realmente apenas converte cada elemento em sua representação de string e concatena as strings juntas, para obter a saída desejada:

6x^4 + -12x^5 + 7x^3 + -14x^4 + -2x^2 + 4x^3
Erik, o Outgolfer
fonte
1

JavaScript, 112 110 bytes

Encontrei duas alternativas com o mesmo comprimento. Ligue com sintaxe de currying: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 ): remova os espaços ao redor do splitdelimitador.


JavaScript, 112 bytes

Usando 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` + `

darrylyeo
fonte
1
split' + ' => split'+'salvar 2 bytes
Luis felipe De jesus Munoz
@Arnauld parece muito bem sem eles
Personificação da Ignorância
@EmbodimentofIgnorance Meu mal, eu interpretei mal o comentário de Luis. Eu pensei que era sobre o join.
Arnauld