Multiplizieren Sie zwei ganzzahlige Polynome


14

Ihre Aufgabe ist es, zwei einfachvariable ganzzahlige Polynomausdrücke zu nehmen und sie mit ihrer nicht vereinfachten Haupterweiterung von links nach rechts (AKA FOIL im Fall von Binomen) zu multiplizieren . Kombinieren Sie keine ähnlichen Begriffe und ordnen Sie das Ergebnis nicht neu an. Um die Erweiterung genauer zu beschreiben, multiplizieren Sie den ersten Term im ersten Ausdruck nacheinander mit jedem Term im zweiten und fahren Sie mit dem ersten Ausdruck fort, bis alle Terms mit allen anderen Terms multipliziert wurden. Ausdrücke werden in einer vereinfachten LaTeX-Variante angegeben.

Jeder Ausdruck ist eine Folge von Begriffen, die durch +(mit genau einem Leerzeichen auf jeder Seite) getrennt sind. Jeder Ausdruck entspricht dem folgenden regulären Ausdruck: (PCRE-Notation)

-?\d+x\^\d+

Im Klartext ist der Begriff ein optionales Anführungszeichen, -gefolgt von einer oder mehreren Ziffern, gefolgt von xeiner nichtnegativen ganzzahligen Potenz (mit ^).

Ein Beispiel für einen vollständigen Ausdruck:

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

Bei Anschluss an LaTeX erhalten Sie 6x3+1337x2+4x1+2x0

Die Ausgabe sollte ebenfalls diesem Format entsprechen.

Da Exponenten in diesem Format nicht in Klammern eingeschlossen sind, gibt LaTeX mehrstellige Exponenten falsch wieder. (z. B. 4x^3 + -2x^14 + 54x^28 + -4x^5Rendert als 4x3+2x14+54x28+4x5 ) Sie müssen dies nicht berücksichtigen und sollten die Klammern nicht in Ihre Ausgabe aufnehmen.

Beispiel Testfälle

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

Regeln und Annahmen

  • Sie können davon ausgehen, dass alle Eingaben genau diesem Format entsprechen. Das Verhalten für jedes andere Format ist für die Zwecke dieser Herausforderung nicht definiert.
    • Es ist zu beachten, dass jede Methode zur Aufnahme der beiden Polynome gültig ist, vorausgesetzt, beide werden als Zeichenfolgen eingelesen, die dem obigen Format entsprechen.
  • Die Reihenfolge der Polynome ist aufgrund der erwarteten Reihenfolge der Produkterweiterung von Bedeutung.
  • Sie müssen Eingabekoeffizienten zwischen 128 und 127 und Eingabeexponenten bis zu 255 .
    • Ausgangskoeffizienten zwischen -16,256 und 16,384 und Exponenten bis 510 müssen daher unterstützt werden.
  • Sie können davon ausgehen, dass jedes Eingabepolynom nicht mehr als 16 Terme enthält
    • Daher müssen Sie (mindestens) bis zu 256 Terme in der Ausgabe unterstützen
  • Terme mit Koeffizienten Null sollten so belassen werden, wie sie sind, wobei Exponenten richtig kombiniert werden
  • Negative Null ist in der Eingabe zulässig, aber semantisch nicht von positiver Null zu unterscheiden. Immer positive Null ausgeben. Lassen Sie keine Nullterme aus.

Viel Spaß beim Golfen! Viel Glück!



2
@ LuisfelipeDejesusMunoz stelle ich mir nicht vor. Das Parsen ist ein wesentlicher Bestandteil der Herausforderung, und im OP heißt es: "Es ist zu beachten, dass jede Methode zur Aufnahme der beiden Polynome gültig ist, vorausgesetzt, beide werden als Zeichenfolgen eingelesen, die dem obigen Format entsprechen. " (Hervorhebung hinzugefügt)
Giuseppe

Antworten:


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)

Probieren Sie es online!

Ich wollte es unbedingt verwenden outer, daher gibt es mit ziemlicher Sicherheit einen effizienteren Ansatz.


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)

Probieren Sie es online!

fparst ein Polynom aus einer Zeichenkette, !multipliziert zwei davon und formatiert das Ergebnis.

H.PWiz sparte 9 Bytes. Vielen Dank!

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



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^"}}*?+}

Probieren Sie es online!

Wie?

Erster Schritt: Hole alle Zahlen aus beiden Polynomen: scan Gibt die Zahlen als Array von Zeichenfolgenpaaren zurück. Dann machen Sie ein kartesisches Produkt der 2 Listen. Jetzt haben wir alle Nummern dort, wo wir sie brauchen, aber immer noch in der falschen Reihenfolge.

Beispiel: Wenn wir mehrfach 3x^4durch -5x^2, so erhalten wir die Zahlen als [["3","4"],["-5","2"]]die erste Idee zu zip war und diese Liste abflachen und dann die Zahlen in einen Ausdruck setzen , wie bewertet werden [3*-5, 4+2]. Tatsächlich müssen wir die Zahlen nicht neu anordnen, sondern können dies innerhalb des Ausdrucks mithilfe einer temporären Variablen tun: Der Ausdruck wird[3*(z=4,-5),z+2] .

Nachdem wir diese Ausdrücke ausgewertet haben, erhalten wir den Koeffizienten und den Exponenten. Wir müssen sie mit verbinden "x^"und dann alle Tems mit verbinden "+".


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)

Hinweis: TIO fehlt Data.Lists, deshalb importiere ich Data.Lists.Splitund Data.List: Probiere es online aus!

Edit: -3 Bytes dank @Lynn.


Das sind tatsächlich 123 Bytes! f!x=map f.splitOn xund z=read!"x^"!"+"speichert dann ein Byte; für die letzte zeile drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)spart man noch zwei. 120 Bytes
Lynn

1
@Lynn: die TIO Version Importe Data.Liststatt Data.Lists, so dass es ein Byte ist.
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))

Probieren Sie es online!

Randnotiz: Das erste Mal, dass ich eine Code-Golf-Challenge mache. Tut mir leid, wenn der Versuch scheitert, haha


3
Willkommen bei PPCG! Ich bin kein großer Python-Programmierer, aber es gibt wahrscheinlich Raum für Verbesserungen. Vielleicht finden Sie Hilfe bei Tipps zum Golfen in Python oder Tipps zum Golfen in <allen Sprachen> ! Ich hoffe, Sie genießen die Zeit, die Sie hier verbringen :-)
Giuseppe


1
Schnelles Golfen für 161 Bytes . Ein Blick auf die anderen Python-Antworten ist re.finditervielleicht nicht der kürzeste Weg
Jo King,

1

Netzhaut , 110 Bytes

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

Probieren Sie es online! Erläuterung:

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

Stellen Sie jedem Begriff in der ersten Eingabe ein #, eine Kopie der zweiten Eingabe und ein Leerzeichen voran. Dies bedeutet, dass allen Begriffen in Kopien der zweiten Eingabe ein Leerzeichen vorangestellt ist und keiner der Begriffe aus der ersten Eingabe.

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

Vergleichen Sie alle Kopien von Begriffen in der zweiten Eingabe mit dem entsprechenden Begriff aus der ersten Eingabe. Verketten Sie alle -Zeichen, multiplizieren Sie die Koeffizienten und addieren Sie die Indizes. Verbinden Sie schließlich alle resultierenden Ersetzungen mit der Zeichenfolge  + .

--|-(0)
$1

Löschen Sie alle Paare von -s und konvertieren Sie -0zu 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

Probieren Sie es 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



1

C # (Visual C # Interactive Compiler) , 192 bis 190 Byte

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;

Die Abfragesyntax scheint ein Byte kürzer als die Methodensyntax zu sein.

Probieren Sie es online!


Jeder Ausdruck ist eine Folge von Begriffen, die durch + (mit genau einem Leerzeichen auf jeder Seite) getrennt sind. 190 Byte
Abgelaufene Daten

1

Gelee , 28 Bytes

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

Probieren Sie es online!

Volles Programm. Nimmt die beiden Polynome als Liste von zwei Zeichenfolgen.

Erklärung (erweiterte Form)

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

)ist das gleiche wie µ€.
Ein Trailing ist impliziert und kann weggelassen werden.

Algorithmus

Nehmen wir an, wir haben diesen Input:

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

Das erste Verfahren ist das Parsen, das auf jedes der beiden Polynome angewendet wird. Lassen Sie uns den ersten behandeln "6x^2 + 7x^1 + -2x^0":

Der erste Schritt besteht darin, die Zeichenfolge durch zu teilen '+', um die Begriffe zu trennen. Das führt zu:

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

Der nächste Schritt besteht darin, jede Zeichenfolge durch zu teilen 'x', um den Koeffizienten vom Exponenten zu trennen. Das Ergebnis ist folgendes:

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

Momentan sieht es so aus, als ob in diesen Zeichenfolgen eine Menge Müll ist, aber dieser Müll ist eigentlich unwichtig. Diese Saiten werden alle als Niladic Jelly Links ausgewertet. Trivialerweise sind die Leerzeichen unwichtig, da sie nicht zwischen den Ziffern der Zahlen stehen. Wir könnten also auch das Folgende auswerten und trotzdem das gleiche Ergebnis erzielen:

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

Das ^ sehen etwas beunruhigender aus, aber sie machen eigentlich auch nichts! Nun, ^ist das bitweise XOR-Atom, jedoch wirken Niladenketten wie monadische Verknüpfungen, mit der Ausnahme, dass die erste Verknüpfung tatsächlich zum Argument wird, anstatt ein Argument zu nehmen, wenn es Niladenketten sind. Ist dies nicht der Fall, hat der Link das Argument 0. Die Exponenten haben das ^s als erstes ^Zeichen und sind nicht niladisch, daher wird das Argument angenommen 0. Der Rest der Zeichenkette, dh die Zahl, ist das richtige Argument von ^. So zum Beispiel ^2ist0 XOR 2=2. Offensichtlich,0 XOR n=n. Alle Exponenten sind ganzzahlig, also ist alles in Ordnung. Daher wird das Ergebnis nicht geändert, wenn Sie dies anstelle der oben genannten auswerten:

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

Auf geht's:

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

Dieser Schritt wandelt auch "-0"zu 0.

Da wir beide Eingaben analysieren, lautet das Ergebnis nach dem Parsen wie folgt:

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

Das Parsing ist jetzt abgeschlossen. Das nächste Verfahren ist die Multiplikation.

Wir nehmen zuerst das kartesische Produkt dieser beiden Listen:

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

Es werden viele Paare gebildet, von denen jedes ein Element aus der linken und eines aus der rechten Liste enthält. Dies ist auch die beabsichtigte Reihenfolge der Ausgabe. Diese Herausforderung fordert uns wirklich auf, multiplikative Verteilungsfähigkeit anzuwenden, da wir gebeten werden, das Ergebnis danach nicht weiter zu verarbeiten.

Die Paare in jedem Paar stellen Terme dar, die wir multiplizieren möchten, wobei das erste Element der Koeffizient und das zweite der Exponent ist. Um die Terme zu multiplizieren, multiplizieren wir die Koeffizienten und addieren die Exponenten (einxcbxd=einbxcxd=einb(xcxd)=(einb)xc+d). Wie machen wir das? Lassen Sie uns das zweite Paar handhaben , [[6, 2], [-2, 3]].

Wir transponieren zuerst das Paar:

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

Wir nehmen dann das Produkt des ersten Paares und die Summe des zweiten:

[-12, 5]

Der relevante Teil des Codes PSƭ€setzt seinen Zähler nicht für jedes Begriffspaar zurück, muss es aber nicht, da es sich um Paare handelt.

Für alle Begriffspaare haben wir:

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

Hier wird die Multiplikation durchgeführt, da wir keine ähnlichen Begriffe kombinieren müssen. Das letzte Verfahren ist das Prettyfying.

Wir verbinden jedes Paar zuerst mit "x^":

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

Dann treten wir der Liste bei mit " + ":

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

Beachten Sie, dass die Liste noch Zahlen enthält, es handelt sich also nicht wirklich um eine Zeichenfolge. Jelly hat jedoch einen Prozess namens "Stringification", der direkt am Ende der Ausführung eines Programms ausgeführt wird, um das Ergebnis auszudrucken. Für eine Liste mit Tiefe 1 konvertiert es wirklich nur jedes Element in seine Zeichenfolgendarstellung und verkettet die Zeichenfolgen miteinander, sodass wir die gewünschte Ausgabe erhalten:

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

1

JavaScript, 112 110 Bytes

Ich habe zwei Alternativen mit der gleichen Länge gefunden. Aufruf mit aktueller Syntax: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 ): Leerzeichen um das splitTrennzeichen entfernen .


JavaScript, 112 Bytes

Verwenden 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'+'2 Bytes zu retten
Luis Felipe De Jesus Munoz


@EmbodimentofIgnorance Mein schlechtes, ich habe Luis 'Kommentar falsch verstanden. Ich dachte, es geht um die join.
Arnauld
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.