Moltiplica due polinomi interi


14

Il tuo compito è prendere due espressioni polinomiali a numero intero a variabile singola e moltiplicarle nella loro espansione da sinistra a destra non semplificata del primo termine (AKA FOIL nel caso dei binomi). Non combinare termini simili o riordinare il risultato. Per essere più espliciti sull'espansione, moltiplica il primo termine nella prima espressione per ciascun termine nel secondo, in ordine, e continua nella prima espressione fino a quando tutti i termini non sono stati moltiplicati per tutti gli altri termini. Le espressioni verranno fornite in una variante LaTeX semplificata.

Ogni espressione sarà una sequenza di termini separati da +(con esattamente uno spazio su ciascun lato) Ogni termine sarà conforme alla seguente espressione regolare: (notazione PCRE)

-?\d+x\^\d+

In parole povere, il termine è un carattere facoltativo -seguito da una o più cifre seguite da xe un potere intero non negativo (con ^)

Un esempio di espressione completa:

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

Se collegato a LaTeX, si ottengono 6x3+1337x2+4x1+2x0

Anche l'output dovrebbe essere conforme a questo formato.

Poiché le parentesi non racchiudono esponenti in questo formato, LaTeX visualizzerà in modo errato esponenti a più cifre. (ad es. 4x^3 + -2x^14 + 54x^28 + -4x^5rendering come 4x3+2x14+54x28+4x5 ) Non è necessario tener conto di ciò e non è necessario includere le parentesi nell'output.

Esempi di casi di 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

Regole e presupposti

  • Si può presumere che tutti gli input siano conformi a questo formato esatto. Il comportamento per qualsiasi altro formato non è definito ai fini di questa sfida.
    • Va notato che qualsiasi metodo di acquisizione dei due polinomi è valido, a condizione che entrambi siano letti come stringhe conformi al formato sopra.
  • L'ordine dei polinomi è importante a causa dell'ordine previsto dell'espansione del prodotto.
  • È necessario supportare coefficienti di input tra -128 e 127 e input esponenti fino a 255 .
    • Pertanto , devono essere supportati coefficienti di output tra 16,256 e 16,384 ed esponenti fino a 510 .
  • Puoi assumere che ogni polinomio di input contenga non più di 16 termini
    • Pertanto, è necessario (almeno) supportare fino a 256 termini nell'output
  • I termini con coefficienti zero dovrebbero essere lasciati così come sono, con gli esponenti che devono essere combinati correttamente
  • Lo zero negativo è consentito nell'input, ma è indistinguibile da zero positivo semanticamente. Emette sempre zero positivo. Non omettere zero termini.

Buon golf! In bocca al lupo!



2
@LuisfelipeDejesusMunoz Immagino di no. L'analisi è parte integrante della sfida e l'OP afferma: "Va notato che qualsiasi metodo di acquisizione dei due polinomi è valido, a condizione che entrambi siano letti come stringhe conformi al formato sopra " . (Enfasi aggiunta)
Giuseppe,

Risposte:


4

R , 159 153 148 byte

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)

Provalo online!

Volevo davvero usarlo outer, quindi c'è quasi sicuramente un approccio più efficiente.


4

Haskell , 131 122 byte

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

Provalo online!

fanalizza un polinomio da una stringa, !moltiplica due di essi e formatta il risultato.

H.PWiz ha salvato 9 byte. Grazie!

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

Rubino , 102 100 98 byte

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

Provalo online!

Come?

Primo passo: ottenere tutti i numeri da entrambi i polinomi: scanrestituisce i numeri come una matrice di coppie di stringhe. Quindi, esegui un prodotto cartesiano delle 2 liste. Ora abbiamo tutti i numeri dove ne abbiamo bisogno, ma ancora nell'ordine sbagliato.

Esempio: se moltiplichiamo 3x^4per -5x^2, otteniamo i numeri come [["3","4"],["-5","2"]], la prima idea era quella di comprimere e appiattire questo elenco, quindi inserire i numeri in un'espressione da valutare come [3*-5, 4+2]. In realtà, non abbiamo bisogno di riordinare i numeri, potremmo farlo all'interno dell'espressione usando una variabile temporanea: l'espressione diventa [3*(z=4,-5),z+2].

Dopo aver valutato queste espressioni, otteniamo il coefficiente e l'esponente, dobbiamo unirci a loro usando "x^"e quindi unire tutti i temi usando "+".


2

Haskell, 124 121 byte

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 manca Data.Lists, quindi importerò Data.Lists.Splite Data.List: Provalo online!

Modifica: -3 byte grazie a @Lynn.


Questo è in realtà 123 byte! f!x=map f.splitOn xe quindi z=read!"x^"!"+"salva un byte; per l'ultima riga ne drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)salva altri due. 120 byte
Lynn,

1
@Lynn: la versione TIO importa Data.Listinvece di Data.Lists, quindi è +1 byte.
nimi,



1

Python 2 , 193 byte

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

Provalo online!

Nota a margine: la prima volta che si fa una sfida di golf in codice, quindi scusate se il tentativo fa schifo ahah


3
Benvenuti in PPCG! Non sono un programmatore di Python, ma probabilmente c'è qualche margine di miglioramento. Forse puoi trovare aiuto in Suggerimenti per giocare a golf in Python o Suggerimenti per giocare a golf in <tutte le lingue> ! Spero ti piaccia il tempo che passi qui :-)
Giuseppe,


1
Qualche golf veloce per 161 byte . Anche se guardare le altre risposte di Python, re.finditerpotrebbe non essere l'approccio più breve
Jo King,

1

Retina , 110 byte

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

Provalo online! Spiegazione:

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

Prefisso ogni termine nel primo input con a #, una copia del secondo input e uno spazio. Ciò significa che tutti i termini nelle copie del secondo input sono preceduti da uno spazio e nessuno dei termini del primo input lo è.

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

Abbina tutte le copie dei termini nel secondo input e il termine corrispondente dal primo input. Concatena qualsiasi -segno, moltiplica i coefficienti e aggiungi gli indici. Infine, unisci tutte le sostituzioni risultanti con la stringa  + .

--|-(0)
$1

Elimina le coppie di se -convertili -0in 0.


1

SNOBOL4 (CSNOBOL4) , 192 176 byte

	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

Provalo 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 # (compilatore interattivo Visual C #) , 192 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;

La sintassi della query sembra essere un byte più breve della sintassi del metodo.

Provalo online!


Ogni espressione sarà una sequenza di termini separati da + (con esattamente uno spazio su ciascun lato) 190 byte
Dati scaduti

1

Gelatina , 28 byte

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

Provalo online!

Programma completo. Prende i due polinomi come un elenco di due stringhe.

Spiegazione (modulo espanso)

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

)è lo stesso di µ€.
Un finale è implicito e può essere omesso.

Algoritmo

Diciamo che abbiamo questo input:

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

La prima procedura è il Parsing, applicato a ciascuno dei due polinomi. Gestiamo il primo,"6x^2 + 7x^1 + -2x^0" :

Il primo passo è dividere la stringa per '+', in modo da separare i termini. Questo risulta in:

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

Il prossimo passo è dividere ogni stringa per 'x', per separare il coefficiente dall'esponente. Il risultato è questo:

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

Attualmente, sembra che ci sia molta spazzatura in queste stringhe, ma quella spazzatura non è in realtà importante. Queste stringhe saranno tutte valutate come collegamenti jelly niladici. In sostanza, gli spazi non sono importanti, in quanto non sono tra le cifre dei numeri. Quindi potremmo anche valutare quanto segue e ottenere comunque lo stesso risultato:

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

Le ^s sembrano un po 'più inquietante, ma in realtà non fanno nulla neanche! Bene, ^è l'atomo XOR bit a bit, tuttavia le catene niladiche si comportano come collegamenti monadici, tranne per il fatto che il primo collegamento in realtà diventa l'argomento, invece di prendere un argomento, se è niladico. In caso contrario, il collegamento avrà un argomento di 0. Gli esponenti hanno la ^s come primo carattere e ^non sono niladici, quindi si presume che l'argomento sia 0. Il resto della stringa, ovvero il numero, è l'argomento giusto di ^. Quindi, per esempio, lo ^2è0 XOR 2=2. Ovviamente,0 XOR n=n. Tutti gli esponenti sono numeri interi, quindi stiamo bene. Pertanto, valutare questo invece di quanto sopra non cambierà il risultato:

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

Eccoci qui:

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

Questo passaggio si convertirà anche "-0"in 0.

Poiché analizziamo entrambi gli input, il risultato dopo l'analisi sarà questo:

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

L'analisi è ora completa. La prossima procedura è la moltiplicazione.

Per prima cosa prendiamo il prodotto cartesiano di questi due elenchi:

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

Vengono create molte coppie, ciascuna con un elemento dall'elenco a sinistra e uno da destra, in ordine. Questo sembra essere anche l'ordine previsto dell'output. Questa sfida ci chiede davvero di applicare la distributività moltiplicativa, poiché ci viene chiesto di non elaborare ulteriormente il risultato.

Le coppie in ciascuna coppia rappresentano termini che vogliamo moltiplicare, con il primo elemento è il coefficiente e il secondo è l'esponente. Per moltiplicare i termini, moltiplichiamo i coefficienti e sommiamo gli esponenti (un'XcBXd=un'BXcXd=un'B(XcXd)=(un'B)Xc+d). Come lo facciamo? Gestiamo la seconda coppia,[[6, 2], [-2, 3]] .

Innanzitutto trasponiamo la coppia:

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

Prendiamo quindi il prodotto della prima coppia e la somma della seconda:

[-12, 5]

La parte pertinente del codice, PSƭ€ realtà non resetta il suo contatore per ogni coppia di termini, ma, poiché sono coppie, non è necessario.

Gestendo tutte le coppie di termini, abbiamo:

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

Qui, la moltiplicazione è fatta, poiché non dobbiamo combinare termini simili. L'ultima procedura è Prettyfying.

Per prima cosa ci uniamo ad ogni coppia con "x^":

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

Quindi ci uniamo alla lista con " + ":

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

Nota come abbiamo ancora numeri nell'elenco, quindi non è davvero una stringa. Tuttavia, Jelly ha un processo chiamato "stringification", eseguito alla fine dell'esecuzione di un programma per stampare il risultato. Per un elenco di profondità 1, converte davvero ogni elemento nella sua rappresentazione di stringa e concatena le stringhe insieme, quindi otteniamo l'output desiderato:

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

1

JavaScript, 112 110 byte

Ho trovato due alternative con la stessa lunghezza. Chiama con la sintassi del 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 byte ( Luis ): rimuove gli spazi attorno al splitdelimitatore.


JavaScript, 112 byte

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


1
split' + ' => split'+'per salvare 2 byte
Luis felipe De jesus Munoz


@EmbodimentofIgnorance Mio cattivo, ho letto male il commento di Luis. Ho pensato che riguardasse il join.
Arnauld,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.