Polynomialception


22

Dati due polinomi f,gdi grado arbitrario sugli interi, il tuo programma / funzione dovrebbe valutare il primo polinomio nel secondo polinomio. f(g(x))(aka la composizione (fog)(x) dei due polinomi)

Dettagli

Sono ammessi i builtin. Puoi assumere qualsiasi formattazione ragionevole come input / output, ma il formato di input e output dovrebbe corrispondere. Ad esempio, formattazione come stringa

x^2+3x+5

o come elenco di coefficienti:

[1,3,5] or alternatively [5,3,1]

Inoltre, si può presumere che i polinomi di input siano completamente espansi e che anche gli output siano completamente espansi.

Esempi

A(x) = x^2 + 3x + 5, B(y) = y+1
A(B(y)) = (y+1)^2 + 3(y+1) + 5 = y^2 + 5y + 9

A(x) = x^6 + x^2 + 1, B(y) = y^2 - y
A(B(y))= y^12 - 6y^11 + 15y^10 - 20y^9 + 15y^8 - 6y^7 + y^6 + y^4 - 2 y^3 + y^2 + 1

A(x) = 24x^3 - 144x^2 + 288x - 192, B(y) = y + 2
A(B(y)) = 24y^3

A(x) = 3x^4 - 36x^3 + 138x^2 - 180x + 27, B(y) = 2y + 3
A(B(y)) = 48y^4 - 96y^2

che dire di builtin?
Maltysen,

1
@Maltysen "Dettagli: sono ammessi i builtin. (...)" : D
flawr

2
Penso che "qualsiasi formato ragionevole" potrebbe essere un po 'estensibile. Se è consentita una funzione che valuta il polinomio, allora la funzione di composizione(.) è una risposta in Haskell. Probabilmente intendi una rappresentazione dell'elenco dei coefficienti.
xnor

1
Il titolo! L'ho appena preso MrGreen
Luis Mendo il

2
@LuisMendo Quick thinker = P
flawr

Risposte:


10

Haskell, 86 72 byte

u!c=foldr1((.u).zipWith(+).(++[0,0..])).map c
o g=(0:)!((<$>g).(*))!pure

Definisce una funzione otale che o g fcalcola la composizione f ∘ g. I polinomi sono rappresentati da un elenco non vuoto di coefficienti a partire dal termine costante.

dimostrazione

*Main> o [1,1] [5,3,1]
[9,5,1]
*Main> o [0,-1,1] [1,0,1,0,0,0,1]
[1,0,1,-2,1,0,1,-6,15,-20,15,-6,1]
*Main> o [2,1] [-192,288,-144,24]
[0,0,0,24]
*Main> o [3,2] [27,-180,138,-36,3]
[0,0,-96,0,48]

Come funziona

Nessun builtin o librerie relative al polinomio. Osserva le ricorrenze simili

f (x) = a + f₁ (x) x ⇒ f (x) g (x) = ag (x) + f₁ (x) g (x) x,
f (x) = a + f₁ (x) x ⇒ f (g (x)) = a + f₁ (g (x)) g (x),

per la moltiplicazione e la composizione polinomiale, rispettivamente. Entrambi prendono la forma

f (x) = a + f₁ (x) x ⇒ W (f) (x) = C (a) (x) + U (W (f₁)) (x).

L'operatore !risolve una ricorrenza di questo modulo per W dato U e C, usandozipWith(+).(++[0,0..]) per l'aggiunta polinomiale (supponendo che il secondo argomento sia più lungo - per i nostri scopi, lo sarà sempre). Poi,

(0:)moltiplica un argomento polinomiale per x (anteponendo un coefficiente zero);
(<$>g).(*)moltiplica un argomento scalare per il polinomio g;
(0:)!((<$>g).(*))moltiplica un argomento polinomiale per il polinomio g;
puresolleva un argomento scalare in un polinomio costante (elenco singleton);
(0:)!((<$>g).(*))!purecompone un argomento polinomiale con il polinomio g.


9

Mathematica, 17 byte

Expand[#/.x->#2]&

Esempio di utilizzo:

In[17]:= Expand[#/.x->#2]& [27 - 180x + 138x^2 - 36x^3 + 3x^4, 3 + 2x]

              2       4
Out[17]= -96 x  + 48 x

7

TI-Basic 68k, 12 byte

a|x=b→f(a,b)

L'uso è semplice, ad esempio per il primo esempio:

f(x^2+3x+5,y+1)

Che ritorna

y^2+5y+9

Mi sembra ingannare richiedere che gli input siano in variabili diverse. È importante per questa risposta?
feersum

Sentiti libero di farlo, ho esplicitamente permesso qualsiasi formato di input conveniente ragionevole.
flawr,

Per quanto riguarda la modifica del tuo commento: sì, è importante.
flawr,

Non ho familiarità con le regole di questo sito. È corretto essere 1 byte in TI-BASIC?
asmeurer,

@asmeurer In effetti: TI-Basic è segnato dalla codifica utilizzata sui calcolatori corrispondenti. Se sei interessato ai dettagli, puoi leggerlo qui su meta . Una tabella di token è disponibile qui su ti-basic-dev .
Flawr,

6

Python 2, 138 156 162 byte

Ci si aspetta che gli input siano liste intere con potenze più piccole per prime.

def c(a,b):
 g=lambda p,q:q>[]and q[0]+p*g(p,q[1:]);B=99**len(`a+b`);s=g(g(B,b),a);o=[]
 while s:o+=(s+B/2)%B-B/2,;s=(s-o[-1])/B
 return o

Ungolfed:

def c(a,b):
 B=sum(map(abs,a+b))**len(a+b)**2
 w=sum(B**i*x for i,x in enumerate(b))
 s=sum(w**i*x for i,x in enumerate(a))
 o=[]
 while s:o+=min(s%B,s%B-B,key=abs),; s=(s-o[-1])/B
 return o

In questo calcolo, i coefficienti polinomiali sono visti come cifre (che possono essere negative) di un numero in una base molto grande. Dopo che i polinomi sono in questo formato, la moltiplicazione o l'aggiunta è una singola operazione intera. Finché la base è sufficientemente grande, non ci saranno riporti che si riversano nelle cifre vicine.

-18 dal miglioramento legato Bcome suggerito da @xnor.


Bel metodo. Per B, sarebbe 10**len(`a+b`)abbastanza?
xnor

@xnor Forse ... è difficile per me dirlo.
feersum

+1 Questa è una soluzione davvero creativa e un buon uso delle origini !!!
Flawr,

@xnor Ora sono riuscito a convincermi che la lunghezza del coefficiente hte è lineare nella lunghezza di input :)
feersum

5

Python + SymPy, 59 35 byte

from sympy import*
var('x')
compose

Grazie a @asmeurer per giocare a golf con 24 byte!

Prova

>>> from sympy import*
>>> var('x')
x
>>> f = compose
>>> f(x**2 + 3*x + 5, x + 1)
x**2 + 5*x + 9

1
SymPy ha una compose()funzione.
asmeurer,

1
Dov'è la risposta? Non definisce più alcuna funzione o fa nulla ...
feersum

1
@feersum Non è mai stato così. Hai appena modificato quel meta post.
Mego,

3
@feersum Hai modificato un meta post accettato per modificare la politica per la tua agenda. Non va bene
Mego,

3
@feersum Anche se potresti aver pensato che le tue parole fossero ambigue, chiaramente non lo era per il resto della comunità. Abbiamo accettato il consenso che from module import*;functionera una proposta valida. Indipendentemente da ciò, questa è una politica più recente, che consente importazioni e funzioni di supporto con lambda senza nome.
Mego,

3

Salvia, 24 byte

lambda A,B:A(B).expand()

A partire da Sage 6.9 (la versione che funziona su http://sagecell.sagemath.org ), le chiamate di funzione senza assegnazione esplicita di argomenti ( f(2) rather than f(x=2)) causano la stampa di un messaggio fastidioso e inutile su STDERR. Poiché STDERR può essere ignorato di default nel code golf, questo è ancora valido.

Questo è molto simile alla risposta SymPy di ​​Dennis perché Sage è a) basato su Python eb) usa Maxima , un sistema di algebra del computer molto simile a SymPy in molti modi. Tuttavia, Sage è molto più potente di Python con SymPy, e quindi è un linguaggio abbastanza diverso da meritare la propria risposta.

Verifica tutti i casi di test online


2

PARI / GP , 19 byte

(a,b)->subst(a,x,b)

che ti permette di fare

%(x^2+1,x^2+x-1)

ottenere

% 2 = x ^ 4 + 2 * x ^ 3 - x ^ 2 - 2 * x + 2


1

MATLAB con Symbolic Toolbox, 28 byte

@(f,g)collect(subs(f,'x',g))

Questa è una funzione anonima. Per chiamarlo assegnarlo a una variabile o utilizzare ans. Gli input sono stringhe con il formato (gli spazi sono opzionali)

x^2 + 3*x + 5

Esempio di esecuzione:

>> @(f,g)collect(subs(f,'x',g))
ans = 
    @(f,g)collect(subs(f,'x',g))
>> ans('3*x^4 - 36*x^3 + 138*x^2 - 180*x + 27','2*x + 3')
ans =
48*x^4 - 96*x^2

1

Python 2, 239 232 223 byte

r=range
e=reduce
a=lambda*l:map(lambda x,y:(x or 0)+(y or 0),*l)
m=lambda p,q:[sum((p+k*[0])[i]*(q+k*[0])[k-i]for i in r(k+1))for k in r(len(p+q)-1)]
o=lambda f,g:e(a,[e(m,[[c]]+[g]*k)for k,c in enumerate(f)])

Un'implementazione "corretta" che non abusa delle basi. Il coefficiente meno significativo per primo.

aè un'aggiunta polinomiale, mè una moltiplicazione polinomiale ed oè una composizione.


Non m([c],e(m,[[1]]+[g]*k))è lo stesso di e(m,[[c]]+[g]*k)?
Neil,

@Neil Buona chiamata, puoi schiacciarne due in uno con quello!
orlp,

a=lambda*l:map(lambda x,y:(x or 0)+(y or 0),*l)
Anders Kaseorg,

@AndersKaseorg Bene, l'ho aggiunto, grazie :)
orlp

Potrebbe essere possibile semplificare l'aggiunta polinomiale, dal momento che penso che un elenco sarà sempre più lungo dell'altro, quindi non è necessario ( or 0)in quella versione.
Neil,

1

JavaScript (ES6), 150 103 byte

(f,g)=>f.map(n=>r=p.map((m,i)=>(g.map((n,j)=>p[j+=i]=m*n+(p[j]||0)),m*n+(r[i]||0)),p=[]),r=[],p=[1])&&r

Accetta e restituisce i polinomi come una matrice a = [a 0 , a 1 , a 2 , ...] che rappresenta uno 0 + a 1 * x + a 2 * x 2 ...

Modifica: salvato 47 byte passando dalla moltiplicazione polinomiale ricorsiva a quella iterativa, che mi ha permesso di unire due mapchiamate.

Spiegazione: r è il risultato, che inizia da zero, rappresentato da un array vuoto, e p è g h , che inizia da uno. p viene moltiplicato per ogni f h a sua volta e il risultato accumulato in r . p viene anche moltiplicato per g contemporaneamente.

(f,g)=>f.map(n=>            Loop through each term of f (n = f[h])
 r=p.map((m,i)=>(           Loop through each term of p (m = p[i])
  g.map((n,j)=>             Loop though each term of g (n = g[j])
   p[j+=i]=m*n+(p[j]||0)),  Accumulate p*g in p
  m*n+(r[i]||0)),           Meanwhile add p[i]*f[h] to r[i]
  p=[]),                    Reset p to 0 each loop to calculate p*g
 r=[],                      Initialise r to 0
 p=[1]                      Initialise p to 1
)&&r                        Return the result


1

Rubino 2.4 + polinomio , 41 + 12 = 53 byte

Usa la bandiera -rpolynomial. L'input è di due Polynomialoggetti.

Se qualcuno mi supera in Vanilla Ruby (nessuna biblioteca polinomiale esterna), rimarrò molto colpito.

->a,b{i=-1;a.coefs.map{|c|c*b**i+=1}.sum}
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.