tasks a-s

This commit is contained in:
Ingy döt Net 2013-04-10 23:57:08 -07:00
parent 47bf37c096
commit b83f433714
12433 changed files with 156208 additions and 123 deletions

View file

@ -0,0 +1,93 @@
{{Wikipedia}}
:<cite>In algebra, [[wp:Polynomial long division|polynomial long division]] is an algorithm for dividing a polynomial by another polynomial of the same or lower degree.</cite>
Let us suppose a polynomial is represented by a vector, <math>x</math> (i.e., an ordered collection of [[wp:Coefficient|coefficients]]) so that the <math>i</math><sup>th</sup> element keeps the coefficient of <math>x^i</math>, and the multiplication by a monomial is a ''shift'' of the vector's elements "towards right" (injecting zeros from left) followed by a multiplication of each element by the coefficient of the monomial.
Then a pseudocode for the polynomial long division using the conventions described above could be:
degree('''P'''):
'''return''' the index of the last non-zero element of '''P''';
if all elements are 0, return -∞
polynomial_long_division('''N''', '''D''') ''returns'' ('''q''', '''r'''):
<span class="co1">// '''N''', '''D''', '''q''', '''r''' are vectors</span>
'''if''' degree('''D''') < 0 '''then''' ''error''
'''if''' degree('''N''') ≥ degree('''D''') '''then'''
'''q''' ← '''0'''
'''while''' degree('''N''') ≥ degree('''D''')
'''d''' ← '''D''' ''shifted right'' ''by'' (degree('''N''') - degree('''D'''))
'''q'''(degree('''N''') - degree('''D''')) ← '''N'''(degree('''N''')) / '''d'''(degree('''d'''))
<span class="co1">// by construction, degree('''d''') = degree('''N''') of course</span>
'''d''' ← '''d''' * '''q'''(degree('''N''') - degree('''D'''))
'''N''' ← '''N''' - '''d'''
'''endwhile'''
'''r''' ← '''N'''
'''else'''
'''q''' ← '''0'''
'''r''' ← '''N'''
'''endif'''
'''return''' ('''q''', '''r''')
'''Note''': <code>vector * scalar</code> multiplies each element of the vector by the scalar; <code>vectorA - vectorB</code> subtracts each element of the vectorB from the element of the vectorA with "the same index". The vectors in the pseudocode are zero-based.
* Error handling (for allocations or for wrong inputs) is not mandatory.
* Conventions can be different; in particular, note that if the first coefficient in the vector is the highest power of x for the polynomial represented by the vector, then the algorithm becomes simpler.
'''Example for clarification'''
<br>
This example is from Wikipedia, but changed to show how the given pseudocode works.
0 1 2 3
----------------------
N: -42 0 -12 1 degree = 3
D: -3 1 0 0 degree = 1
<span class="co1">d(N) - d(D) = 2, so let's shift D towards right by 2:</span>
N: -42 0 -12 1
d: 0 0 -3 1
<span class="co1">N(3)/d(3) = 1, so d is unchanged. Now remember that "shifting by 2"
is like multiplying by x<sup>2</sup>, and the final multiplication
(here by 1) is the coefficient of this monomial. Let's store this
into q:</span>
0 1 2
---------------
q: 0 0 1
<span class="co1">now compute N - d, and let it be the "new" N, and let's loop</span>
N: -42 0 -9 0 degree = 2
D: -3 1 0 0 degree = 1
<span class="co1">d(N) - d(D) = 1, right shift D by 1 and let it be d</span>
N: -42 0 -9 0
d: 0 -3 1 0 * -9/1 = -9
q: 0 -9 1
d: 0 27 -9 0
N ← N - d
N: -42 -27 0 0 degree = 1
D: -3 1 0 0 degree = 1
<span class="co1">looping again... d(N)-d(D)=0, so no shift is needed; we
multiply D by -27 (= -27/1) storing the result in d, then</span>
q: -27 -9 1
<span class="co1">and</span>
N: -42 -27 0 0 -
d: 81 -27 0 0 =
N: -123 0 0 0 (last N)
<span class="co1">d(N) &lt; d(D), so now r ← N, and the result is:</span>
0 1 2
-------------
q: -27 -9 1 → x<sup>2</sup> - 9x - 27
r: -123 0 0 → -123

View file

@ -0,0 +1,2 @@
---
note: Classic CS problems and programs

View file

@ -0,0 +1,110 @@
with Ada.Text_IO; use Ada.Text_IO;
procedure Long_Division is
package Int_IO is new Ada.Text_IO.Integer_IO (Integer);
use Int_IO;
type Degrees is range -1 .. Integer'Last;
subtype Valid_Degrees is Degrees range 0 .. Degrees'Last;
type Polynom is array (Valid_Degrees range <>) of Integer;
function Degree (P : Polynom) return Degrees is
begin
for I in reverse P'Range loop
if P (I) /= 0 then
return I;
end if;
end loop;
return -1;
end Degree;
function Shift_Right (P : Polynom; D : Valid_Degrees) return Polynom is
Result : Polynom (0 .. P'Last + D) := (others => 0);
begin
Result (Result'Last - P'Length + 1 .. Result'Last) := P;
return Result;
end Shift_Right;
function "*" (Left : Polynom; Right : Integer) return Polynom is
Result : Polynom (Left'Range);
begin
for I in Result'Range loop
Result (I) := Left (I) * Right;
end loop;
return Result;
end "*";
function "-" (Left, Right : Polynom) return Polynom is
Result : Polynom (Left'Range);
begin
for I in Result'Range loop
if I in Right'Range then
Result (I) := Left (I) - Right (I);
else
Result (I) := Left (I);
end if;
end loop;
return Result;
end "-";
procedure Poly_Long_Division (Num, Denom : Polynom; Q, R : out Polynom) is
N : Polynom := Num;
D : Polynom := Denom;
begin
if Degree (D) < 0 then
raise Constraint_Error;
end if;
Q := (others => 0);
while Degree (N) >= Degree (D) loop
declare
T : Polynom := Shift_Right (D, Degree (N) - Degree (D));
begin
Q (Degree (N) - Degree (D)) := N (Degree (N)) / T (Degree (T));
T := T * Q (Degree (N) - Degree (D));
N := N - T;
end;
end loop;
R := N;
end Poly_Long_Division;
procedure Output (P : Polynom) is
First : Boolean := True;
begin
for I in reverse P'Range loop
if P (I) /= 0 then
if First then
First := False;
else
Put (" + ");
end if;
if I > 0 then
if P (I) /= 1 then
Put (P (I), 0);
Put ("*");
end if;
Put ("x");
if I > 1 then
Put ("^");
Put (Integer (I), 0);
end if;
elsif P (I) /= 0 then
Put (P (I), 0);
end if;
end if;
end loop;
New_Line;
end Output;
Test_N : constant Polynom := (0 => -42, 1 => 0, 2 => -12, 3 => 1);
Test_D : constant Polynom := (0 => -3, 1 => 1);
Test_Q : Polynom (Test_N'Range);
Test_R : Polynom (Test_N'Range);
begin
Poly_Long_Division (Test_N, Test_D, Test_Q, Test_R);
Put_Line ("Dividing Polynoms:");
Put ("N: "); Output (Test_N);
Put ("D: "); Output (Test_D);
Put_Line ("-------------------------");
Put ("Q: "); Output (Test_Q);
Put ("R: "); Output (Test_R);
end Long_Division;

View file

@ -0,0 +1,44 @@
DIM N%(3) : N%() = -42, 0, -12, 1
DIM D%(3) : D%() = -3, 1, 0, 0
DIM q%(3), r%(3)
PROC_poly_long_div(N%(), D%(), q%(), r%())
PRINT "Quotient = "; FNcoeff(q%(2)) "x^2" FNcoeff(q%(1)) "x" FNcoeff(q%(0))
PRINT "Remainder = " ; r%(0)
END
DEF PROC_poly_long_div(N%(), D%(), q%(), r%())
LOCAL d%(), i%, s%
DIM d%(DIM(N%(),1))
s% = FNdegree(N%()) - FNdegree(D%())
IF s% >= 0 THEN
q%() = 0
WHILE s% >= 0
FOR i% = 0 TO DIM(d%(),1) - s%
d%(i%+s%) = D%(i%)
NEXT
q%(s%) = N%(FNdegree(N%())) DIV d%(FNdegree(d%()))
d%() = d%() * q%(s%)
N%() -= d%()
s% = FNdegree(N%()) - FNdegree(D%())
ENDWHILE
r%() = N%()
ELSE
q%() = 0
r%() = N%()
ENDIF
ENDPROC
DEF FNdegree(a%())
LOCAL i%
i% = DIM(a%(),1)
WHILE a%(i%)=0
i% -= 1
IF i%<0 EXIT WHILE
ENDWHILE
= i%
DEF FNcoeff(n%)
IF n%=0 THEN = ""
IF n%<0 THEN = " - " + STR$(-n%)
IF n%=1 THEN = " + "
= " + " + STR$(n%)

View file

@ -0,0 +1,16 @@
#include <iostream>
#include <math.h>
using namespace std;
// does: prints all members of vector
// input: c - ASCII char with the name of the vector
// d - degree of vector
// A - pointer to vector
void Print(char c, int d, double* A) {
int i;
for (i=0; i < d+1; i++)
cout << c << "[" << i << "]= " << A[i] << endl;
cout << "Degree of " << c << ": " << d << endl << endl;
}

View file

@ -0,0 +1,106 @@
int main() {
double *N,*D,*d,*q,*r; // vectors - N / D = q N % D = r
int dN, dD, dd, dq, dr; // degrees of vectors
int i; // iterators
// setting the degrees of vectors
cout << "Enter the degree of N:";
cin >> dN;
cout << "Enter the degree of D:";
cin >> dD;
dq = dN-dD;
dr = dN-dD;
// allocation and initialization of vectors
N=new double [dN+1];
cout << "Enter the coefficients of N:"<<endl;
for ( i = 0; i < dN+1; i++ ) {
cout << "N[" << i << "]= " << endl;
cin >> N[i];
}
D=new double [dN+1];
cout << "Enter the coefficients of D:"<<endl;
for ( i = 0; i < dD+1; i++ ) {
cout << "D[" << i << "]= " << endl;
cin >> D[i];
}
d=new double [dN+1];
for( i = dD+1 ; i < dN+1; i++ ) {
D[i] = 0;
}
q=new double [dq+1];
for( i = 0 ; i < dq + 1 ; i++ ) {
q[i] = 0;
}
r=new double [dr+1];
for( i = 0 ; i < dr + 1 ; i++ ) {
r[i] = 0;
}
if( dD < 0) {
cout << "Degree of D is less than zero. Error!";
}
cout << "-- Procedure --" << endl << endl;
if( dN >= dD ) {
while(dN >= dD) {
// d equals D shifted right
for( i = 0 ; i < dN + 1 ; i++ ) {
d[i] = 0;
}
for( i = 0 ; i < dD + 1 ; i++ ) {
d[i+dN-dD] = D[i];
}
dd = dN;
Print( 'd', dd, d );
// calculating one element of q
q[dN-dD] = N[dN]/d[dd];
Print( 'q', dq, q );
// d equals d * q[dN-dD]
for( i = 0 ; i < dq + 1 ; i++ ) {
d[i] = d[i] * q[dN-dD];
}
Print( 'd', dd, d );
// N equals N - d
for( i = 0 ; i < dN + 1 ; i++ ) {
N[i] = N[i] - d[i];
}
dN--;
Print( 'N', dN, N );
cout << "-----------------------" << endl << endl;
}
}
// r equals N
for( i = 0 ; i < dN + 1 ; i++ ) {
r[i] = N[i];
}
dr = dN;
cout << "=========================" << endl << endl;
cout << "-- Result --" << endl << endl;
Print( 'q', dq, q );
Print( 'r', dr, r );
// dealocation
delete [] N;
delete [] D;
delete [] d;
delete [] q;
delete [] r;
}

View file

@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <gsl/gsl_vector.h>
#define MAX(A,B) (((A)>(B))?(A):(B))
void reoshift(gsl_vector *v, int h)
{
if ( h > 0 ) {
gsl_vector *temp = gsl_vector_alloc(v->size);
gsl_vector_view p = gsl_vector_subvector(v, 0, v->size - h);
gsl_vector_view p1 = gsl_vector_subvector(temp, h, v->size - h);
gsl_vector_memcpy(&p1.vector, &p.vector);
p = gsl_vector_subvector(temp, 0, h);
gsl_vector_set_zero(&p.vector);
gsl_vector_memcpy(v, temp);
gsl_vector_free(temp);
}
}
gsl_vector *poly_long_div(gsl_vector *n, gsl_vector *d, gsl_vector **r)
{
gsl_vector *nt = NULL, *dt = NULL, *rt = NULL, *d2 = NULL, *q = NULL;
int gn, gt, gd;
if ( (n->size >= d->size) && (d->size > 0) && (n->size > 0) ) {
nt = gsl_vector_alloc(n->size); assert(nt != NULL);
dt = gsl_vector_alloc(n->size); assert(dt != NULL);
rt = gsl_vector_alloc(n->size); assert(rt != NULL);
d2 = gsl_vector_alloc(n->size); assert(d2 != NULL);
gsl_vector_memcpy(nt, n);
gsl_vector_set_zero(dt); gsl_vector_set_zero(rt);
gsl_vector_view p = gsl_vector_subvector(dt, 0, d->size);
gsl_vector_memcpy(&p.vector, d);
gsl_vector_memcpy(d2, dt);
gn = n->size - 1;
gd = d->size - 1;
gt = 0;
while( gsl_vector_get(d, gd) == 0 ) gd--;
while ( gn >= gd ) {
reoshift(dt, gn-gd);
double v = gsl_vector_get(nt, gn)/gsl_vector_get(dt, gn);
gsl_vector_set(rt, gn-gd, v);
gsl_vector_scale(dt, v);
gsl_vector_sub(nt, dt);
gt = MAX(gt, gn-gd);
while( (gn>=0) && (gsl_vector_get(nt, gn) == 0.0) ) gn--;
gsl_vector_memcpy(dt, d2);
}
q = gsl_vector_alloc(gt+1); assert(q != NULL);
p = gsl_vector_subvector(rt, 0, gt+1);
gsl_vector_memcpy(q, &p.vector);
if ( r != NULL ) {
if ( (gn+1) > 0 ) {
*r = gsl_vector_alloc(gn+1); assert( *r != NULL );
p = gsl_vector_subvector(nt, 0, gn+1);
gsl_vector_memcpy(*r, &p.vector);
} else {
*r = gsl_vector_alloc(1); assert( *r != NULL );
gsl_vector_set_zero(*r);
}
}
gsl_vector_free(nt); gsl_vector_free(dt);
gsl_vector_free(rt); gsl_vector_free(d2);
return q;
} else {
q = gsl_vector_alloc(1); assert( q != NULL );
gsl_vector_set_zero(q);
if ( r != NULL ) {
*r = gsl_vector_alloc(n->size); assert( *r != NULL );
gsl_vector_memcpy(*r, n);
}
return q;
}
}
void poly_print(gsl_vector *p)
{
int i;
for(i=p->size-1; i >= 0; i--) {
if ( i > 0 )
printf("%lfx^%d + ",
gsl_vector_get(p, i), i);
else
printf("%lf\n", gsl_vector_get(p, i));
}
}
gsl_vector *create_poly(int d, ...)
{
va_list al;
int i;
gsl_vector *r = NULL;
va_start(al, d);
r = gsl_vector_alloc(d); assert( r != NULL );
for(i=0; i < d; i++)
gsl_vector_set(r, i, va_arg(al, double));
return r;
}

View file

@ -0,0 +1,23 @@
int main()
{
int i;
gsl_vector *q, *r;
gsl_vector *nv, *dv;
//nv = create_poly(4, -42., 0., -12., 1.);
//dv = create_poly(2, -3., 1.);
//nv = create_poly(3, 2., 3., 1.);
//dv = create_poly(2, 1., 1.);
nv = create_poly(4, -42., 0., -12., 1.);
dv = create_poly(3, -3., 1., 1.);
q = poly_long_div(nv, dv, &r);
poly_print(q);
poly_print(r);
gsl_vector_free(q);
gsl_vector_free(r);
return 0;
}

View file

@ -0,0 +1,104 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
typedef struct {
int power;
double * coef;
} poly_t, *poly;
#define E(x, i) (x)->coef[i]
/* passing in negative power to have a zeroed poly */
poly p_new(int power, ...)
{
int i, zeroed = 0;
va_list ap;
if (power < 0) {
power = -power;
zeroed = 1;
}
poly p = malloc(sizeof(poly_t));
p->power = power;
p->coef = malloc(sizeof(double) * ++power);
if (zeroed)
for (i = 0; i < power; i++) p->coef[i] = 0;
else {
va_start(ap, power);
for (i = 0; i < power; i++)
E(p, i) = va_arg(ap, double);
va_end(ap);
}
return p;
}
void p_del(poly p)
{
free(p->coef);
free(p);
}
void p_print(poly p)
{
int i;
for (i = 0; i <= p->power; i++)
printf("%g ", E(p, i));
printf("\n");
}
poly p_copy(poly p)
{
poly q = p_new(-p->power);
memcpy(q->coef, p->coef, sizeof(double) * (1 + p->power));
return q;
}
/* p: poly; d: divisor; r: remainder; returns quotient */
poly p_div(poly p, poly d, poly* r)
{
poly q;
int i, j;
int power = p->power - d->power;
double ratio;
if (power < 0) return 0;
q = p_new(-power);
*r= p_copy(p);
for (i = p->power; i >= d->power; i--) {
E(q, i - d->power) = ratio = E(*r, i) / E(d, d->power);
E(*r ,i) = 0;
for (j = 0; j < d->power; j++)
E(*r, i - d->power + j) -= E(d, j) * ratio;
}
while (! E(*r, --(*r)->power));
return q;
}
int main()
{
poly p = p_new(3, 1., 2., 3., 4.);
poly d = p_new(2, 1., 2., 1.);
poly r;
poly q = p_div(p, d, &r);
printf("poly: "); p_print(p);
printf("div: "); p_print(d);
printf("quot: "); p_print(q);
printf("rem: "); p_print(r);
p_del(p);
p_del(q);
p_del(r);
p_del(d);
return 0;
}

View file

@ -0,0 +1,41 @@
(defun add (p1 p2)
(do ((sum '())) ((and (endp p1) (endp p2)) (nreverse sum))
(let ((pd1 (if (endp p1) -1 (caar p1)))
(pd2 (if (endp p2) -1 (caar p2))))
(multiple-value-bind (c1 c2)
(cond
((> pd1 pd2) (values (cdr (pop p1)) 0))
((< pd1 pd2) (values 0 (cdr (pop p2))))
(t (values (cdr (pop p1)) (cdr (pop p2)))))
(let ((csum (+ c1 c2)))
(unless (zerop csum)
(setf sum (acons (max pd1 pd2) csum sum))))))))
(defun multiply (p1 p2)
(flet ((*p2 (p)
(destructuring-bind (d . c) p
(loop for (pd . pc) in p2
collecting (cons (+ d pd) (* c pc))))))
(reduce 'add (mapcar #'*p2 p1) :initial-value '())))
(defun subtract (p1 p2)
(add p1 (multiply '((0 . -1)) p2)))
(defun divide (dividend divisor &aux (sum '()))
(assert (not (endp divisor)) (divisor)
'division-by-zero
:operation 'divide
:operands (list dividend divisor))
(flet ((floor1 (dividend divisor)
(if (endp dividend) (values '() ())
(destructuring-bind (d1 . c1) (first dividend)
(destructuring-bind (d2 . c2) (first divisor)
(if (> d2 d1) (values '() dividend)
(let* ((quot (list (cons (- d1 d2) (/ c1 c2))))
(rem (subtract dividend (multiply divisor quot))))
(values quot rem))))))))
(loop (multiple-value-bind (quotient remainder)
(floor1 dividend divisor)
(if (endp quotient) (return (values sum remainder))
(setf dividend remainder
sum (add quotient sum)))))))

View file

@ -0,0 +1,4 @@
> (divide '((3 . 1) (2 . -12) (0 . -42)) ; x^3 - 12x^2 - 42
'((1 . 1) (0 . -3))) ; x - 3
((2 . 1) (1 . -9) (0 . -27)) ; x^2 - 9x - 27
((0 . -123)) ; -123

View file

@ -0,0 +1,38 @@
import std.stdio, std.range, std.algorithm, std.typecons;
Tuple!(double[],double[]) polyDiv(in double[] inN, in double[] inD)
/*pure nothrow*/ {
// code smell: a function that does two things
static int trimAndDegree(T)(ref T[] poly) /*nothrow pure*/ {
poly.length -= poly.retro().countUntil!q{a != 0}();
return (cast(int)poly.length) - 1;
}
double[] N = inN.dup;
const(double)[] D = inD;
const dD = trimAndDegree(D);
auto dN = trimAndDegree(N);
double[] q, r;
if (dD < 0)
throw new Exception("ZeroDivisionError");
if (dN >= dD) {
q = repeat(0.0).take(dN).array();
while (dN >= dD) {
auto d = repeat(0.0).take(dN - dD).array() ~ D;
const mult = q[dN - dD] = N[$ - 1] / d[$ - 1];
d[] *= mult;
N[] -= d[];
dN = trimAndDegree(N);
}
} else {
q = [0.0];
}
r = N;
return tuple(q, r);
}
void main() {
immutable N = [-42.0, 0.0, -12.0, 1.0];
immutable D = [-3.0, 1.0, 0.0, 0.0];
writefln("%s / %s = %s remainder %s", N, D, polyDiv(N,D).tupleof);
}

View file

@ -0,0 +1,7 @@
def n := makePolynomial([-42, 0, -12, 1])
def d := makePolynomial([-3, 1])
println("Numerator: ", n)
println("Denominator: ", d)
def [q, r] := n.quotRem(d, stdout)
println("Quotient: ", q)
println("Remainder: ", r)

View file

@ -0,0 +1,80 @@
module Polynom
implicit none
contains
subroutine poly_long_div(n, d, q, r)
real, dimension(:), intent(in) :: n, d
real, dimension(:), intent(out), allocatable :: q
real, dimension(:), intent(out), allocatable, optional :: r
real, dimension(:), allocatable :: nt, dt, rt
integer :: gn, gt, gd
if ( (size(n) >= size(d)) .and. (size(d) > 0) .and. (size(n) > 0) ) then
allocate(nt(size(n)), dt(size(n)), rt(size(n)))
nt = n
dt = 0
dt(1:size(d)) = d
rt = 0
gn = size(n)-1
gd = size(d)-1
gt = 0
do while ( d(gd+1) == 0 )
gd = gd - 1
end do
do while( gn >= gd )
dt = eoshift(dt, -(gn-gd))
rt(gn-gd+1) = nt(gn+1) / dt(gn+1)
nt = nt - dt * rt(gn-gd+1)
gt = max(gt, gn-gd)
do
gn = gn - 1
if ( nt(gn+1) /= 0 ) exit
end do
dt = 0
dt(1:size(d)) = d
end do
allocate(q(gt+1))
q = rt(1:gt+1)
if ( present(r) ) then
if ( (gn+1) > 0 ) then
allocate(r(gn+1))
r = nt(1:gn+1)
else
allocate(r(1))
r = 0.0
end if
end if
deallocate(nt, dt, rt)
else
allocate(q(1))
q = 0
if ( present(r) ) then
allocate(r(size(n)))
r = n
end if
end if
end subroutine poly_long_div
subroutine poly_print(p)
real, dimension(:), intent(in) :: p
integer :: i
do i = size(p), 1, -1
if ( i > 1 ) then
write(*, '(F0.2,"x^",I0," + ")', advance="no") p(i), i-1
else
write(*, '(F0.2)') p(i)
end if
end do
end subroutine poly_print
end module Polynom

View file

@ -0,0 +1,18 @@
program PolyDivTest
use Polynom
implicit none
real, dimension(:), allocatable :: q
real, dimension(:), allocatable :: r
!! three tests from Wikipedia, plus an extra
!call poly_long_div( (/ -3., 1. /), (/ -42., 0.0, -12., 1. /), q, r)
call poly_long_div( (/ -42., 0.0, -12., 1. /), (/ -3., 1. /), q, r)
!call poly_long_div( (/ -42., 0.0, -12., 1. /), (/ -3., 1., 1. /), q, r)
!call poly_long_div( (/ 2., 3., 1. /), (/ 1., 1. /), q, r)
call poly_print(q)
call poly_print(r)
deallocate(q, r)
end program PolyDivTest

View file

@ -0,0 +1,5 @@
x := Indeterminate(Rationals, "x");
p := x^11 + 3*x^8 + 7*x^2 + 3;
q := x^7 + 5*x^3 + 1;
QuotientRemainder(p, q);
# [ x^4+3*x-5, -16*x^4+25*x^3+7*x^2-3*x+8 ]

View file

@ -0,0 +1,46 @@
package main
import "fmt"
func main() {
n := []float64{-42, 0, -12, 1}
d := []float64{-3, 1}
fmt.Println("N:", n)
fmt.Println("D:", d)
q, r, ok := pld(n, d)
if ok {
fmt.Println("Q:", q)
fmt.Println("R:", r)
} else {
fmt.Println("error")
}
}
func degree(p []float64) int {
for d := len(p) - 1; d >= 0; d-- {
if p[d] != 0 {
return d
}
}
return -1
}
func pld(nn, dd []float64) (q, r []float64, ok bool) {
if degree(dd) < 0 {
return
}
nn = append(r, nn...)
if degree(nn) >= degree(dd) {
q = make([]float64, degree(nn)-degree(dd)+1)
for degree(nn) >= degree(dd) {
d := make([]float64, degree(nn)+1)
copy(d[degree(nn)-degree(dd):], dd)
q[degree(nn)-degree(dd)] = nn[degree(nn)] / d[degree(d)]
for i := range d {
d[i] *= q[degree(nn)-degree(dd)]
nn[i] -= d[i]
}
}
}
return q, nn, true
}

View file

@ -0,0 +1,22 @@
import Data.List
shift n l = l ++ replicate n 0
pad n l = replicate n 0 ++ l
norm :: Fractional a => [a] -> [a]
norm = dropWhile (== 0)
deg l = length (norm l) - 1
zipWith' op p q = zipWith op (pad (-d) p) (pad d q)
where d = (length p) - (length q)
polydiv f g = aux (norm f) (norm g) []
where aux f s q | ddif < 0 = (q, f)
| otherwise = aux f' s q'
where ddif = (deg f) - (deg s)
k = (head f) / (head s)
ks = map (* k) $ shift ddif s
q' = zipWith' (+) q $ shift ddif [k]
f' = norm $ tail $ zipWith' (-) f ks

View file

@ -0,0 +1,11 @@
str_poly l = intercalate " + " $ terms l
where term v 0 = show v
term 1 1 = "x"
term v 1 = (show v) ++ "x"
term 1 p = "x^" ++ (show p)
term v p = (show v) ++ "x^" ++ (show p)
terms :: Fractional a => [a] -> [String]
terms [] = []
terms (0:t) = terms t
terms (h:t) = (term h (length t)) : (terms t)

View file

@ -0,0 +1 @@
divmod=:[: (}: ; {:) ([ (] -/@,:&}. (* {:)) ] , %&{.~)^:(>:@-~&#)&.|.~

View file

@ -0,0 +1 @@
_42 0 _12 1 divmod _3 1

View file

@ -0,0 +1,19 @@
> p := randpoly( x ); # pick a random polynomial in x
5 4 3 2
p := -56 - 7 x + 22 x - 55 x - 94 x + 87 x
> rem( p, x^2 + 2, x, 'q' ); # remainder
220 + 169 x
> q; # quotient
3 2
-7 x + 22 x - 41 x - 138
> quo( p, x^2 + 2, x, 'r' ); # quotient
3 2
-7 x + 22 x - 41 x - 138
> r; # remainder
220 + 169 x
> expand( (x^2+2)*q + r - p ); # check
0

View file

@ -0,0 +1 @@
PolynomialQuotientRemainder[x^3-12 x^2-42,x-3,x]

View file

@ -0,0 +1,8 @@
let rec shift n l = if n <= 0 then l else shift (pred n) (l @ [0.0])
let rec pad n l = if n <= 0 then l else pad (pred n) (0.0 :: l)
let rec norm = function | 0.0 :: tl -> norm tl | x -> x
let deg l = List.length (norm l) - 1
let zip op p q =
let d = (List.length p) - (List.length q) in
List.map2 op (pad (-d) p) (pad d q)

View file

@ -0,0 +1,10 @@
let polydiv f g =
let rec aux f s q =
let ddif = (deg f) - (deg s) in
if ddif < 0 then (q, f) else
let k = (List.hd f) /. (List.hd s) in
let ks = List.map (( *.) k) (shift ddif s) in
let q' = zip (+.) q (shift ddif [k])
and f' = norm (List.tl (zip (-.) f ks)) in
aux f' s q' in
aux (norm f) (norm g) []

View file

@ -0,0 +1,12 @@
let str_poly l =
let term v p = match (v, p) with
| ( _, 0) -> string_of_float v
| (1.0, 1) -> "x"
| ( _, 1) -> (string_of_float v) ^ "*x"
| (1.0, _) -> "x^" ^ (string_of_int p)
| _ -> (string_of_float v) ^ "*x^" ^ (string_of_int p) in
let rec terms = function
| [] -> []
| h :: t ->
if h = 0.0 then (terms t) else (term h (List.length t)) :: (terms t) in
String.concat " + " (terms l)

View file

@ -0,0 +1,6 @@
let _ =
let f = [1.0; -4.0; 6.0; 5.0; 3.0] and g = [1.0; 2.0; 1.0] in
let q, r = polydiv f g in
Printf.printf
" (%s) div (%s)\ngives\nquotient:\t(%s)\nremainder:\t(%s)\n"
(str_poly f) (str_poly g) (str_poly q) (str_poly r)

View file

@ -0,0 +1,37 @@
function [q, r] = poly_long_div(n, d)
gd = length(d);
pv = zeros(1, length(n));
pv(1:gd) = d;
if ( length(n) >= gd )
q = [];
while ( length(n) >= gd )
q = [q, n(1)/pv(1)];
n = n - pv .* (n(1)/pv(1));
n = shift(n, -1); %
tn = n(1:length(n)-1); % eat the higher power term
n = tn; %
tp = pv(1:length(pv)-1);
pv = tp; % make pv the same length of n
endwhile
r = n;
else
q = [0];
r = n;
endif
endfunction
[q, r] = poly_long_div([1,-12,0,-42], [1,-3]);
polyout(q, 'x');
polyout(r, 'x');
disp("");
[q, r] = poly_long_div([1,-12,0,-42], [1,1,-3]);
polyout(q, 'x');
polyout(r, 'x');
disp("");
[q, r] = poly_long_div([1,3,2], [1,1]);
polyout(q, 'x');
polyout(r, 'x');
disp("");
[q, r] = poly_long_div([1,3], [1,-12,0,-42]);
polyout(q, 'x');
polyout(r, 'x');

View file

@ -0,0 +1,5 @@
poldiv(a,b)={
my(rem=a%b);
[(a - rem)/b, rem]
};
poldiv(x^9+1, x^3+x-3)

View file

@ -0,0 +1 @@
divrem(x^9+1, x^3+x-3)~

View file

@ -0,0 +1,24 @@
sub poly_long_div ( @n is copy, @d ) {
return [0], @n if +@n < +@d;
my @q = gather while +@n >= +@d {
@n = @n Z- ( ( @d X* take ( @n[0] / @d[0] ) ), 0 xx * );
@n.shift;
}
return $(@q), $(@n);
}
sub xP ( $power ) { $power>1 ?? "x^$power" !! $power==1 ?? 'x' !! '' }
sub poly_print ( @c ) { join ' + ', @c.kv.map: { $^v ~ xP( @c.end - $^k ) } }
my @polys = [ [ 1, -12, 0, -42 ], [ 1, -3 ] ],
[ [ 1, -12, 0, -42 ], [ 1, 1, -3 ] ],
[ [ 1, 3, 2 ], [ 1, 1 ] ],
[ [ 1, -4, 6, 5, 3 ], [ 1, 2, 1 ] ];
say '<math>\begin{array}{rr}';
for @polys -> [ @a, @b ] {
printf "%s , & %s \\\\\n", poly_long_div( @a, @b ).map: { poly_print($_) };
}
say '\end{array}</math>';

View file

@ -0,0 +1,22 @@
use strict;
use List::Util qw(min);
sub poly_long_div
{
my ($rn, $rd) = @_;
my @n = @$rn;
my $gd = scalar(@$rd);
if ( scalar(@n) >= $gd ) {
my @q = ();
while ( scalar(@n) >= $gd ) {
my $piv = $n[0]/$rd->[0];
push @q, $piv;
$n[$_] -= $rd->[$_] * $piv foreach ( 0 .. min(scalar(@n), $gd)-1 );
shift @n;
}
return ( \@q, \@n );
} else {
return ( [0], $rn );
}
}

View file

@ -0,0 +1,10 @@
sub poly_print
{
my @c = @_;
my $l = scalar(@c);
for(my $i=0; $i < $l; $i++) {
print $c[$i];
print "x^" . ($l-$i-1) . " + " if ($i < ($l-1));
}
print "\n";
}

View file

@ -0,0 +1,18 @@
my ($q, $r);
($q, $r) = poly_long_div([1, -12, 0, -42], [1, -3]);
poly_print(@$q);
poly_print(@$r);
print "\n";
($q, $r) = poly_long_div([1,-12,0,-42], [1,1,-3]);
poly_print(@$q);
poly_print(@$r);
print "\n";
($q, $r) = poly_long_div([1,3,2], [1,1]);
poly_print(@$q);
poly_print(@$r);
print "\n";
# the example from the OCaml solution
($q, $r) = poly_long_div([1,-4,6,5,3], [1,2,1]);
poly_print(@$q);
poly_print(@$r);

View file

@ -0,0 +1,18 @@
(de degree (P)
(let I NIL
(for (N . C) P
(or (=0 C) (setq I N)) )
(dec I) ) )
(de divPoly (N D)
(if (lt0 (degree D))
(quit "Div/0" D)
(let (Q NIL Diff)
(while (ge0 (setq Diff (- (degree N) (degree D))))
(setq Q (need (- -1 Diff) Q 0))
(let E D
(do Diff (push 'E 0))
(let F (/ (get N (inc (degree N))) (get E (inc (degree E))))
(set (nth Q (inc Diff)) F)
(setq N (mapcar '((N E) (- N (* E F))) N E)) ) ) )
(list Q N) ) ) )

View file

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
from itertools import izip
from math import fabs
def degree(poly):
while poly and poly[-1] == 0:
poly.pop() # normalize
return len(poly)-1
def poly_div(N, D):
dD = degree(D)
dN = degree(N)
if dD < 0: raise ZeroDivisionError
if dN >= dD:
q = [0] * dN
while dN >= dD:
d = [0]*(dN - dD) + D
mult = q[dN - dD] = N[-1] / float(d[-1])
d = [coeff*mult for coeff in d]
N = [fabs ( coeffN - coeffd ) for coeffN, coeffd in izip(N, d)]
dN = degree(N)
r = N
else:
q = [0]
r = N
return q, r
if __name__ == '__main__':
print "POLYNOMIAL LONG DIVISION"
N = [-42, 0, -12, 1]
D = [-3, 1, 0, 0]
print " %s / %s =" % (N,D),
print " %s remainder %s" % poly_div(N, D)

View file

@ -0,0 +1,34 @@
polylongdiv <- function(n,d) {
gd <- length(d)
pv <- vector("numeric", length(n))
pv[1:gd] <- d
if ( length(n) >= gd ) {
q <- c()
while ( length(n) >= gd ) {
q <- c(q, n[1]/pv[1])
n <- n - pv * (n[1]/pv[1])
n <- n[2:length(n)]
pv <- pv[1:(length(pv)-1)]
}
list(q=q, r=n)
} else {
list(q=c(0), r=n)
}
}
# an utility function to print polynomial
print.polynomial <- function(p) {
i <- length(p)-1
for(a in p) {
if ( i == 0 ) {
cat(a, "\n")
} else {
cat(a, "x^", i, " + ", sep="")
}
i <- i - 1
}
}
r <- polylongdiv(c(1,-12,0,-42), c(1,-3))
print.polynomial(r$q)
print.polynomial(r$r)

View file

@ -0,0 +1,46 @@
def polynomial_long_division(numerator, denominator)
dd = degree(denominator)
raise ArgumentError, "denominator is zero" if dd < 0
if dd == 0
return [multiply(numerator, 1.0/denominator[0]), [0]*numerator.length]
end
q = [0] * numerator.length
while (dn = degree(numerator)) >= dd
d = shift_right(denominator, dn - dd)
q[dn-dd] = numerator[dn] / d[degree(d)]
d = multiply(d, q[dn-dd])
numerator = subtract(numerator, d)
end
[q, numerator]
end
def degree(ary)
idx = ary.rindex {|x| x.nonzero?}
idx.nil? ? -1 : idx
end
def shift_right(ary, n)
[0]*n + ary[0, ary.length - n]
end
def subtract(a1, a2)
a1.zip(a2).collect {|v1,v2| v1 - v2}
end
def multiply(ary, num)
ary.collect {|x| x * num}
end
f = [-42, 0, -12, 1]
g = [-3, 1, 0, 0]
q, r = polynomial_long_division(f, g)
p [f, g, q, r]
# => [[-42, 0, -12, 1], [-3, 1, 0, 0], [-27, -9, 1, 0, 0], [-123, 0, 0, 0, 0]]
g = [-3, 1, 1, 0]
q, r = polynomial_long_division(f, g)
p [f, g, q, r]
# => [[-42, 0, -12, 1], [-3, 1, 0, 0], [-13, 1, 0, 0, 0], [-81, 16, 0, 0, 0]]

View file

@ -0,0 +1,68 @@
def polynomial_division(f, g)
if g.length == 0 or (g.length == 1 and g[0] == 0)
raise ArgumentError, "denominator is zero"
elsif g.length == 1
[f.collect {|x| Float(x)/g[0]}, [0]]
elsif g.length == 2
synthetic_division(f, g)
else
higher_degree_synthetic_division(f, g)
end
end
def synthetic_division(f, g)
board = [f] << Array.new(f.length) << Array.new(f.length)
board[2][0] = board[0][0]
1.upto(f.length - 1).each do |i|
board[1][i] = board[2][i-1] * -g[1]
board[2][i] = board[0][i] + board[1][i]
end
[board[2][0..-2], [board[2][-1]]]
end
# an ugly mess of array index arithmetic
# http://en.wikipedia.org/wiki/Polynomial_long_division#Higher_degree_synthetic_division
def higher_degree_synthetic_division(f, g)
# [use] the negative coefficients of the denominator following the leading term
lhs = g[1..-1].collect {|x| -x}
board = [f]
q = []
1.upto(f.length - lhs.length).each do |i|
n = 2*i - 1
# underline the leading coefficient of the right-hand side, multiply it by
# the left-hand coefficients and write the products beneath the next columns
# on the right.
q << board[n-1][i-1]
board << Array.new(f.length).fill(0, i) # row n
(lhs.length).times do |j|
board[n][i+j] = q[-1]*lhs[j]
end
# perform an addition
board << Array.new(f.length).fill(0, i) # row n+1
(lhs.length + 1).times do |j|
board[n+1][i+j] = board[n-1][i+j] + board[n][i+j] if i+j < f.length
end
end
# the remaining numbers in the bottom row correspond to the coefficients of the remainder
r = board[-1].compact
q = [0] if q.empty?
[q, r]
end
f = [1, -12, 0, -42]
g = [1, -3]
q, r = polynomial_division(f, g)
p [f, g, q, r]
# => [[1, -12, 0, -42], [1, -3], [1, -9, -27], [-123]]
g = [1, 1, -3]
q, r = polynomial_division(f, g)
p [f, g, q, r]
# => [[1, -12, 0, -42], [1, 1, -3], [1, -13], [16, -81]]

View file

@ -0,0 +1,30 @@
def tcl_polynomial_division(f, g)
if g.length == 0 or (g.length == 1 and g[0] == 0)
raise ArgumentError, "denominator is zero"
end
return [[0], f] if f.length < g.length
q = []
n, d = f.dup, g
while n.length >= d.length
q << Float(n[0]) / d[0]
n[0, d.length].zip(d).each_with_index do |pair, i|
n[i] = Float(pair[0]) - q[-1] * pair[1]
end
n.shift
end
q = [0] if q.empty?
n = [0] if n.empty?
[q, n]
end
f = [1, -12, 0, -42]
g = [1, -3]
q, r = polynomial_division(f, g)
p [f, g, q, r]
# => [[1, -12, 0, -42], [1, -3], [1, -9, -27], [-123]]
g = [1, 1, -3]
q, r = polynomial_division(f, g)
p [f, g, q, r]
# => [[1, -12, 0, -42], [1, 1, -3], [1, -13], [16, -81]]

View file

@ -0,0 +1,62 @@
define: #Polynomial &parents: {Comparable} &slots: {#coefficients -> ExtensibleArray new}.
p@(Polynomial traits) new &capacity: n
[
p cloneSettingSlots: #(coefficients) to: {p coefficients new &capacity: n}
].
p@(Polynomial traits) newFrom: seq@(Sequence traits)
[
p clone `>> [coefficients: (seq as: p coefficients). normalize. ]
].
p@(Polynomial traits) copy
[
p cloneSettingSlots: #(coefficients) to: {p coefficients copy}
].
p1@(Polynomial traits) >= p2@(Polynomial traits)
[p1 degree >= p2 degree].
p@(Polynomial traits) degree
[p coefficients indexOfLastSatisfying: [| :n | n isZero not]].
p@(Polynomial traits) normalize
[
[p degree isPositive /\ [p coefficients last isZero]]
whileTrue: [p coefficients removeLast]
].
p@(Polynomial traits) * n@(Number traits)
[
p newFrom: (p coefficients collect: [| :x | x * n])
].
p@(Polynomial traits) / n@(Number traits)
[
p newFrom: (p coefficients collect: [| :x | x / n])
].
p1@(Polynomial traits) minusCoefficients: p2@(Polynomial traits)
[
p1 newFrom: (p1 coefficients with: p2 coefficients collect: #- `er)
].
p@(Polynomial traits) / denom@(Polynomial traits)
[
p >= denom
ifTrue:
[| n q |
n: p copy.
q: p new.
[n >= denom]
whileTrue:
[| piv |
piv: p coefficients last / denom coefficients last.
q coefficients add: piv.
n: (n minusCoefficients: denom * piv).
n normalize].
n coefficients isEmpty ifTrue: [n coefficients add: 0].
{q. n}]
ifFalse: [{p newFrom: #(0). p copy}]
].

View file

@ -0,0 +1,68 @@
Object subclass: Polynomial [
|coeffs|
Polynomial class >> new [ ^ super basicNew init ]
init [ coeffs := OrderedCollection new. ^ self ]
Polynomial class >> newWithCoefficients: coefficients [
|r|
r := super basicNew.
^ r initWithCoefficients: coefficients
]
initWithCoefficients: coefficients [
coeffs := coefficients asOrderedCollection.
^ self
]
/ denominator [ |n q|
n := self deepCopy.
self >= denominator
ifTrue: [
q := Polynomial new.
[ n >= denominator ]
whileTrue: [ |piv|
piv := (n coeff: 0) / (denominator coeff: 0).
q addCoefficient: piv.
n := n - (denominator * piv).
n clean
].
^ { q . (n degree) > 0 ifTrue: [ n ] ifFalse: [ n addCoefficient: 0. n ] }
]
ifFalse: [
^ { Polynomial newWithCoefficients: #( 0 ) . self deepCopy }
]
]
* constant [ |r| r := self deepCopy.
1 to: (coeffs size) do: [ :i |
r at: i put: ((r at: i) * constant)
].
^ r
]
at: index [ ^ coeffs at: index ]
at: index put: obj [ ^ coeffs at: index put: obj ]
>= anotherPoly [
^ (self degree) >= (anotherPoly degree)
]
degree [ ^ coeffs size ]
- anotherPoly [ "This is not a real subtraction between Polynomial: it is an
internal method ..."
|a|
a := self deepCopy.
1 to: ( (coeffs size) min: (anotherPoly degree) ) do: [ :i |
a at: i put: ( (a at: i) - (anotherPoly at: i) )
].
^ a
]
coeff: index [ ^ coeffs at: (index + 1) ]
addCoefficient: coeff [ coeffs add: coeff ]
clean [
[ (coeffs size) > 0
ifTrue: [ (coeffs at: 1) = 0 ] ifFalse: [ false ] ]
whileTrue: [ coeffs removeFirst ].
]
display [
1 to: (coeffs size) do: [ :i |
(coeffs at: i) display.
i < (coeffs size)
ifTrue: [ ('x^%1 + ' % {(coeffs size) - i} ) display ]
]
]
displayNl [ self display. Character nl display ]
].

View file

@ -0,0 +1,11 @@
|res|
res := OrderedCollection new.
res add: ((Polynomial newWithCoefficients: #( 1 -12 0 -42) ) /
(Polynomial newWithCoefficients: #( 1 -3 ) )) ;
add: ((Polynomial newWithCoefficients: #( 1 -12 0 -42) ) /
(Polynomial newWithCoefficients: #( 1 1 -3 ) )).
res do: [ :o |
(o at: 1) display. ' with rest: ' display. (o at: 2) displayNl
]

View file

@ -0,0 +1,40 @@
# poldiv - Divide two polynomials n and d.
# Result is a list of two polynomials, q and r, where n = qd + r
# and the degree of r is less than the degree of b.
# Polynomials are represented as lists, where element 0 is the
# x**0 coefficient, element 1 is the x**1 coefficient, and so on.
proc poldiv {a b} {
# Toss out leading zero coefficients efficiently
while {[lindex $a end] == 0} {set a [lrange $a[set a {}] 0 end-1]}
while {[lindex $b end] == 0} {set b [lrange $b[set b {}] 0 end-1]}
if {[llength $a] < [llength $b]} {
return [list 0 $a]
}
# Rearrange the terms to put highest powers first
set n [lreverse $a]
set d [lreverse $b]
# Carry out classical long division, accumulating quotient coefficients
# in q, and replacing n with the remainder.
set q {}
while {[llength $n] >= [llength $d]} {
set qd [expr {[lindex $n 0] / [lindex $d 0]}]
set i 0
foreach nd [lrange $n 0 [expr {[llength $d] - 1}]] dd $d {
lset n $i [expr {$nd - $qd * $dd}]
incr i
}
lappend q $qd
set n [lrange $n 1 end]
}
# Return quotient and remainder, constant term first
return [list [lreverse $q] [lreverse $n]]
}
# Demonstration
lassign [poldiv {-42. 0. -12. 1.} {-3. 1. 0. 0.}] Q R
puts [list Q = $Q]
puts [list R = $R]

View file

@ -0,0 +1,9 @@
#import std
#import flo
polydiv =
zeroid~-l~~; leql?rlX\~&NlX ^H\(@rNrNSPXlHDlS |\ :/0.) @NlX //=> ?(
@lrrPX ==!| zipp0.; @x not zeroid+ ==@h->hr ~&t,
(^lryPX/~&lrrl2C minus^*p/~&rrr times*lrlPD)^/div@bzPrrPlXO ~&,
@r ^|\~& ~&i&& :/0.)

View file

@ -0,0 +1,3 @@
#cast %eLW
example = polydiv(<-42.,0.,-12.,1.>,<-3.,1.,0.,0.>)