Divisione lunga polinomiale


10

Implementa la divisione polinomiale lunga, un algoritmo che divide due polinomi e ottiene il quoziente e il resto:

(12x ^ 3 - 5x ^ 2 + 3x - 1) / (x ^ 2 - 5) = 12x - 5 R 63x - 26

Nei tuoi programmi, rappresenterai i polinomi come un array, con il termine costante sulla coda. ad esempio, x ^ 5 - 3x ^ 4 + 2x ^ 2 - x + 1 diventerà [1, -3, 0, 2, -1, 1].

La funzione di divisione lunga che si intende scrivere restituirà due valori: il quoziente e il resto. Non è necessario gestire imprecisioni numeriche ed errori aritmetici. Non utilizzare la libreria matematica per fare il tuo lavoro, tuttavia, potresti rendere la tua funzione in grado di gestire valori simbolici. Il codice più corto vince.

ESEMPIO: div([12, -5, 3, -1], [1, 0, -5]) == ([12, -5], [63, -26])


Risposte:


3

J, 94

f=:>@(0&{)
d=:0{[%~0{[:f]
D=:4 :'x((1}.([:f])-((#@]{.[)f)*d);([:>1{]),d)^:(>:((#f y)-(#x)))y'

per esempio.

(1 0 _5) D (12 _5 3 _1;'')
63 _26 | 12  _5

Spiegazione di alcuni frammenti, dato che a: (12-5 3 -1) eb: (1 0-5)

lunghezza di a:

#a
4

crea aeb lo stesso ordine aggiungendo zeri a b:

(#a) {. b
1 0 -5 0

dividere i poteri superiori (primi elementi) di a, b:

(0{a) % (0{b)
12

moltiplicare b per quello e sottrarlo da a:

a - 12*b
12 0 _60

ripetere n volte b = f (a, b):

a f^:n b

Due cose. 1) vinci personaggi prendendo dividendi / divisori nell'ordine insolito? 2) è necessario trascinare `; '' 'nel dividendo? sembra qualcosa che dovresti fare dall'interno del programma attuale.
JB,

@JB: 1) No, in realtà potrebbe essere più breve per il "solito" ordine; è solo il modo in cui ho iniziato a pensarci. 2) Fa parte dell'array, quindi suppongo che dovrebbe essere parte dell'input.
Eelvex,

Non riesco a capire cosa c'entri un array vuoto aggiuntivo con l'input.
JB

3

Pitone 2, 260 258 257 255 byte

exec'''def d(p,q):
 R=range;D=len(p);F=len(q)-1;d=q[0];q=[q[i]/-d@R(1,F+1)];r=[0@R(D)];a=[[0@R(F)]@R(D)]
@R(D):
  p[i]/=d;r[i]=sum(a[i])+p[i]
  for j in R(F):
   if i<D-F:a[i+j+1][F-j-1]=r[i]*q[j]
 return r[:D-F],[d*i@r[D-F:]]'''.replace('@',' for i in ')

Questo esegue:

def d(p,q):
 R=range;D=len(p);F=len(q)-1;d=q[0];q=[q[i]/-d for i in R(1,F+1)];r=[0 for i in R(D)];a=[[0 for i in R(F)] for i in R(D)]
 for i in R(D):
  p[i]/=d;r[i]=sum(a[i])+p[i]
  for j in R(F):
   if i<D-F:a[i+j+1][F-j-1]=r[i]*q[j]
 return r[:D-F],[d*i for i in r[D-F:]]

Usa così:

>>>d([12., -5., 3., -1.],[1.,0.,-5.])
([12.0, -5.0], [63.0, -26.0])

1
Wow, la prima volta che ho visto un exec / sostituire effettivamente utilizzato per salvare i personaggi.
xnor

@xnor L'ho fatto un'altra volta, ma per più di una sostituzione.
Giustino,

2

Haskell, 126

Per iniziare:

l s _ 0=s
l(x:s)(y:t)n=x/y:l(zipWith(-)s$map(*(x/y))t++repeat 0)(y:t)(n-1)
d s t=splitAt n$l s t n where n=length s-length t+1

Esempio di utilizzo:

*Main> d [12, -5, 3, -1] [1, 0, -5]
([12.0,-5.0],[63.0,-26.0])

1

Javascript con lambdas, 108

f=(a,b)=>{for(n=b.length;a.length>=n;a.shift())for(b.push(k=a[q=0]/b[0]);q<n;++q)a[q]-=k*b[q];b.splice(0,n)}

Sostituisce il primo argomento per promemoria e il secondo per risultato.

Esempio di utilizzo in Firefox:

f(x=[12,-5,3,-1], y=[1,0,-5]), console.log(x, y)
// Array [ 63, -26 ] Array [ 12, -5 ]

Ci scusiamo per il bug. Già riparato

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.