Multipliez deux polynômes entiers

14

Votre tâche consiste à prendre deux expressions polynomiales entières à variable unique et à les multiplier dans leur expansion de gauche à droite non simplifiée du premier terme (AKA FOIL dans le cas des binômes). Ne combinez pas des termes similaires et ne réorganisez pas le résultat. Pour être plus explicite sur l'expansion, multipliez le premier terme de la première expression par chaque terme du second, dans l'ordre, et continuez dans la première expression jusqu'à ce que tous les termes aient été multipliés par tous les autres termes. Les expressions seront données dans une variante simplifiée de LaTeX.

Chaque expression sera une séquence de termes séparés par +(avec exactement un espace de chaque côté) Chaque terme sera conforme à l'expression régulière suivante: (notation PCRE)

-?\d+x\^\d+

En anglais simple, le terme est un interligne facultatif -suivi d'un ou plusieurs chiffres suivis de xet d'une puissance entière non négative (avec ^)

Un exemple d'une expression complète:

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

Une fois branché sur LaTeX, vous obtenez 6x3+1337X2+-4X1+2X0

La sortie doit également être conforme à ce format.

Étant donné que les crochets n'entourent pas les exposants dans ce format, LaTeX rendra en fait les exposants à plusieurs chiffres de manière incorrecte. (par exemple, 4x^3 + -2x^14 + 54x^28 + -4x^5rend 4x3+2x14+54x28+4x5 ) Vous n'avez pas besoin de tenir compte de cela et vous ne devez pas inclure les crochets dans votre sortie.

Exemples de cas de test

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

Règles et hypothèses

  • Vous pouvez supposer que toutes les entrées sont conformes à ce format exact. Le comportement pour tout autre format n'est pas défini aux fins de ce défi.
    • Il convient de noter que toute méthode de prise en compte des deux polynômes est valide, à condition que les deux soient lus en tant que chaînes conformes au format ci-dessus.
  • L'ordre des polynômes est important en raison de l'ordre prévu de l'expansion du produit.
  • Vous devez prendre en charge les coefficients d'entrée compris entre 128 et 127 et les exposants d'entrée jusqu'à 255 .
    • Les coefficients de sortie entre 16,256 et 16,384 et les exposants jusqu'à 510 doivent donc être pris en charge.
  • Vous pouvez supposer que chaque polynôme d'entrée ne contient pas plus de 16 termes
    • Par conséquent, vous devez (au minimum) prendre en charge jusqu'à 256 termes dans la sortie
  • Les termes avec des coefficients nuls doivent être laissés tels quels, les exposants étant correctement combinés
  • Le zéro négatif est autorisé en entrée, mais il est impossible de le distinguer sémantiquement du zéro positif. Toujours sortir un zéro positif. N'omettez pas les termes zéro.

Bon golf! Bonne chance!

Beefster
la source
1
connexes
H.PWiz
2
@LuisfelipeDejesusMunoz J'imagine que non. L'analyse syntaxique fait partie intégrante du défi et l'OP dit - "Il convient de noter que toute méthode de prise dans les deux polynômes est valide, à condition que les deux soient lus comme des chaînes conformes au format ci-dessus. " (Non souligné dans l'original)
Giuseppe

Réponses:

4

R , 159 153 148 octets

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)

Essayez-le en ligne!

Je voulais vraiment utiliser outer, donc il y a presque sûrement une approche plus efficace.

Giuseppe
la source
4

Haskell , 131 122 octets

(%)=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)

Essayez-le en ligne!

fanalyse un polynôme à partir d'une chaîne, en !multiplie deux et formate le résultat.

H.PWiz a enregistré 9 octets. Merci!

Non 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
Lynn
la source
129 octets
H.PWiz
1
encore mieux
H.PWiz
2

Rubis , 102 100 98 octets

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

Essayez-le en ligne!

Comment?

Première étape: obtenir tous les nombres des deux polynômes: scanrenvoie les nombres sous forme de tableau de paires de chaînes. Ensuite, faites un produit cartésien des 2 listes. Nous avons maintenant tous les numéros où nous en avons besoin, mais toujours dans le mauvais ordre.

Exemple: si nous multiplions 3x^4par -5x^2, nous obtenons les nombres comme [["3","4"],["-5","2"]], la première idée était de compresser et d'aplatir cette liste, puis de mettre les nombres dans une expression à évaluer comme [3*-5, 4+2]. En fait, nous n'avons pas besoin de réorganiser les nombres, nous pouvons le faire à l'intérieur de l'expression en utilisant une variable temporaire: l'expression devient [3*(z=4,-5),z+2].

Après avoir évalué ces expressions, nous obtenons le coefficient et l'exposant, nous devons les joindre à l'aide "x^", puis joindre tous les tems à l'aide "+".

GB
la source
2

Haskell, 124 121 octets

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)

Remarque: TIO manque Data.Lists , alors j'importe Data.Lists.Splitet Data.List: Essayez-le en ligne!

Edit: -3 octets grâce à @Lynn.

nimi
la source
C'est en fait 123 octets! f!x=map f.splitOn xpuis z=read!"x^"!"+"enregistre un octet; pour la dernière ligne drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)enregistre deux autres. 120 octets
Lynn
1
@Lynn: la version TIO importe à la Data.Listplace de Data.Lists, donc c'est +1 octet.
nimi
1

JavaScript (nœud Babel) , 118 octets

Prend l'entrée comme (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` + `

Essayez-le en ligne!

Arnauld
la source
1

Python 2 , 193 octets

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

Essayez-le en ligne!

Note: Première fois que vous faites un défi de golf de code, désolé si la tentative est nulle haha

GotCubes
la source
3
Bienvenue chez PPCG! Je ne suis pas vraiment un programmeur python, mais il y a probablement une marge d'amélioration. Vous pouvez peut-être trouver de l'aide sur Tips for Golfing in Python ou Tips for Golfing in <all languages> ! J'espère que vous apprécierez le temps que vous passez ici :-)
Giuseppe
1
Du golf rapide pour 161 octets . Bien que regardant les autres réponses python, re.finditerce ne soit peut-être pas l'approche la plus courte
Jo King
1

Rétine , 110 octets

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

Essayez-le en ligne! Explication:

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

Préfixez chaque terme dans la première entrée avec un #, une copie de la deuxième entrée et un espace. Cela signifie que tous les termes dans les copies de la deuxième entrée sont précédés d'un espace et aucun des termes de la première entrée ne l'est.

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

Faites correspondre toutes les copies des termes de la deuxième entrée et leur terme correspondant de la première entrée. Concatène tous les -signes, multiplie les coefficients et ajoute les indices. Enfin, joignez toutes les substitutions résultantes avec la chaîne  + .

--|-(0)
$1

Supprimez toutes les paires de -s et convertissez-les -0en 0.

Neil
la source
1

SNOBOL4 (CSNOBOL4) , 192 176 octets

	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

Essayez-le en ligne!

	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
la source
1

Perl 6 , 114 octets

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

Essayez-le en ligne!

bb94
la source
1
86 octets
Jo King
1

Python 2 , 130 octets

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(' + ')]

Essayez-le en ligne!

Chas Brown
la source
1

C # (Visual C # Interactive Compiler) , 192 190 octets

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 syntaxe de requête semble être un octet plus court que la syntaxe de méthode.

Essayez-le en ligne!

Incarnation de l'ignorance
la source
Chaque expression sera une séquence de termes séparés par + (avec exactement un espace de chaque côté) 190 octets
Données expirées le
1

Gelée , 28 octets

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

Essayez-le en ligne!

Programme complet. Prend les deux polynômes comme une liste de deux chaînes.

Explication (formulaire développé)

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

)est le même que µ€.
Un suivi est implicite et peut être omis.

Algorithme

Disons que nous avons cette entrée:

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

La première procédure est l'analyse syntaxique, appliquée à chacun des deux polynômes. La poignée de laisser le premier un, "6x^2 + 7x^1 + -2x^0":

La première étape consiste à diviser la chaîne de '+'manière à séparer les termes. Il en résulte:

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

L'étape suivante consiste à diviser chaque chaîne par 'x', pour séparer le coefficient de l'exposant. Le résultat est le suivant:

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

Actuellement, il semble qu'il y ait beaucoup de corbeille dans ces chaînes, mais cette corbeille est en fait sans importance. Ces chaînes vont toutes être évaluées comme des liens de gelée niladiques. Curieusement, les espaces sont sans importance, car ils ne sont pas entre les chiffres des chiffres. Donc, nous pourrions aussi bien évaluer ce qui suit et toujours obtenir le même résultat:

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

Les ^s semblent un peu plus dérangeants, mais ils ne font rien non plus! Eh bien, ^c'est l'atome XOR au niveau du bit, mais les chaînes niladiques agissent comme des liens monadiques, sauf que le premier lien devient en fait l'argument, au lieu de prendre un argument, s'il est niladique. Si ce n'est pas le cas, le lien aura un argument de 0. Les exposants ont le ^s comme premier caractère et ^ne sont pas niladic, donc l'argument est supposé être 0. Le reste de la chaîne, c'est-à-dire le nombre, est le bon argument de ^. Ainsi, par exemple, ^2est0 XOR 2=2. Évidemment,0 XOR n=n. Tous les exposants sont entiers, nous allons donc bien. Par conséquent, évaluer cela au lieu de ce qui précède ne changera pas le résultat:

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

Et c'est parti:

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

Cette étape sera également convertie "-0"en 0.

Puisque nous analysons les deux entrées, le résultat après l'analyse sera le suivant:

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

L'analyse est maintenant terminée. La procédure suivante est la multiplication.

Nous prenons d'abord le produit cartésien de ces deux listes:

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

De nombreuses paires sont faites, chacune avec un élément de la liste de gauche et un de la droite, dans l'ordre. Cela se trouve également être l'ordre prévu de la sortie. Ce défi nous demande vraiment d'appliquer la distributivité multiplicative, car on nous demande de ne plus traiter le résultat par la suite.

Les paires de chaque paire représentent des termes que nous voulons multiplier, le premier élément étant le coefficient et le second étant l'exposant. Pour multiplier les termes, nous multiplions les coefficients et additionnons les exposants (uneXcbX=unebXcX=uneb(XcX)=(uneb)Xc+). Comment fait-on cela? Allons gérer la deuxième paire, [[6, 2], [-2, 3]].

Nous transposons d'abord la paire:

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

On prend alors le produit de la première paire, et la somme de la seconde:

[-12, 5]

La partie pertinente du code PSƭ€,, ne réinitialise pas réellement son compteur pour chaque paire de termes, mais, comme ce sont des paires, ce n'est pas nécessaire.

Pour toutes les paires de termes, nous avons:

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

Ici, la multiplication est effectuée, car nous n'avons pas à combiner des termes similaires. La procédure finale est le Prettyfying.

Nous rejoignons d'abord chaque paire avec "x^":

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

Ensuite, nous rejoignons la liste avec " + ":

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

Remarquez comment nous avons encore des nombres dans la liste, donc ce n'est pas vraiment une chaîne. Cependant, Jelly a un processus appelé "stringification", exécuté juste à la fin de l'exécution d'un programme pour imprimer le résultat. Pour une liste de profondeur 1, il convertit vraiment chaque élément en sa représentation de chaîne et concatène les chaînes ensemble, nous obtenons donc la sortie souhaitée:

6x^4 + -12x^5 + 7x^3 + -14x^4 + -2x^2 + 4x^3
Erik le Outgolfer
la source
1

JavaScript, 112 110 octets

J'ai trouvé deux alternatives de même longueur. Appel avec syntaxe de 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 octets ( Luis ): supprime les espaces autour du splitdélimiteur.


JavaScript, 112 octets

Utilisation 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
la source
1
split' + ' => split'+'pour économiser 2 octets
Luis felipe De jesus Munoz
@Arnauld semble bien sans eux
Incarnation de l'ignorance
@EmbodimentofIgnorance Mon mauvais, j'ai mal lu le commentaire de Luis. Je pensais que c'était à propos du join.
Arnauld