June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -0,0 +1,8 @@
div{
{
q r d
(d) > nr : q r
c (r) ÷ d
(c,q) ((¯1r) - c × ¯1(-n)d) d
}
}

View file

@ -0,0 +1,95 @@
(defn grevlex [term1 term2]
(let [grade1 (reduce +' term1)
grade2 (reduce +' term2)
comp (- grade2 grade1)] ;; total degree
(if (not= 0 comp)
comp
(loop [term1 term1
term2 term2]
(if (empty? term1)
0
(let [grade1 (last term1)
grade2 (last term2)
comp (- grade1 grade2)] ;; differs from grlex because terms are flipped from above
(if (not= 0 comp)
comp
(recur (pop term1)
(pop term2)))))))))
(defn mul
;; transducer
([poly1] ;; completion
(fn
([] poly1)
([poly2] (mul poly1 poly2))
([poly2 & more] (mul poly1 poly2 more))))
([poly1 poly2]
(let [product (atom (transient (sorted-map-by grevlex)))]
(doall ;; `for` is lazy so must to be forced for side-effects
(for [term1 poly1
term2 poly2
:let [vars (mapv +' (key term1) (key term2))
coeff (* (val term1) (val term2))]]
(if (contains? @product vars)
(swap! product assoc! vars (+ (get @product vars) coeff))
(swap! product assoc! vars coeff))))
(->> product
(deref)
(persistent!)
(denull))))
([poly1 poly2 & more]
(reduce mul (mul poly1 poly2) more)))
(defn compl [term1 term2]
(map (fn [x y]
(cond
(and (zero? x) (not= 0 y)) nil
(< x y) nil
(>= x y) (- x y)))
term1
term2))
(defn s-poly [f g]
(let [f-vars (first f)
g-vars (first g)
lcm (compl f-vars g-vars)]
(if (not-any? nil? lcm)
{(vec lcm)
(/ (second f) (second g))})))
(defn divide [f g]
(loop [f f
g g
result (transient {})
remainder {}]
(if (empty? f)
(list (persistent! result)
(->> remainder
(filter #(not (nil? %)))
(into (sorted-map-by grevlex))))
(let [term1 (first f)
term2 (first g)
s-term (s-poly term1 term2)]
(if (nil? s-term)
(recur (dissoc f (first term1))
(dissoc g (first term2))
result
(conj remainder term1))
(recur (sub f (mul g s-term))
g
(conj! result s-term)
remainder))))))
(deftest divide-tests
(is (= (divide {[1 1] 2, [1 0] 3, [0 1] 5, [0 0] 7}
{[1 1] 2, [1 0] 3, [0 1] 5, [0 0] 7})
'({[0 0] 1} {})))
(is (= (divide {[1 1] 2, [1 0] 3, [0 1] 5, [0 0] 7}
{[0 0] 1})
'({[1 1] 2, [1 0] 3, [0 1] 5, [0 0] 7} {})))
(is (= (divide {[1 1] 2, [1 0] 10, [0 1] 3, [0 0] 15}
{[0 1] 1, [0 0] 5})
'({[1 0] 2, [0 0] 3} {})))
(is (= (divide {[1 1] 2, [1 0] 10, [0 1] 3, [0 0] 15}
{[1 0] 2, [0 0] 3})
'({[0 1] 1, [0 0] 5} {}))))

View file

@ -0,0 +1,118 @@
import java.util.Arrays;
public class PolynomialLongDivision {
private static class Solution {
double[] quotient, remainder;
Solution(double[] q, double[] r) {
this.quotient = q;
this.remainder = r;
}
}
private static int polyDegree(double[] p) {
for (int i = p.length - 1; i >= 0; --i) {
if (p[i] != 0.0) return i;
}
return Integer.MIN_VALUE;
}
private static double[] polyShiftRight(double[] p, int places) {
if (places <= 0) return p;
int pd = polyDegree(p);
if (pd + places >= p.length) {
throw new IllegalArgumentException("The number of places to be shifted is too large");
}
double[] d = Arrays.copyOf(p, p.length);
for (int i = pd; i >= 0; --i) {
d[i + places] = d[i];
d[i] = 0.0;
}
return d;
}
private static void polyMultiply(double[] p, double m) {
for (int i = 0; i < p.length; ++i) {
p[i] *= m;
}
}
private static void polySubtract(double[] p, double[] s) {
for (int i = 0; i < p.length; ++i) {
p[i] -= s[i];
}
}
private static Solution polyLongDiv(double[] n, double[] d) {
if (n.length != d.length) {
throw new IllegalArgumentException("Numerator and denominator vectors must have the same size");
}
int nd = polyDegree(n);
int dd = polyDegree(d);
if (dd < 0) {
throw new IllegalArgumentException("Divisor must have at least one one-zero coefficient");
}
if (nd < dd) {
throw new IllegalArgumentException("The degree of the divisor cannot exceed that of the numerator");
}
double[] n2 = Arrays.copyOf(n, n.length);
double[] q = new double[n.length];
while (nd >= dd) {
double[] d2 = polyShiftRight(d, nd - dd);
q[nd - dd] = n2[nd] / d2[nd];
polyMultiply(d2, q[nd - dd]);
polySubtract(n2, d2);
nd = polyDegree(n2);
}
return new Solution(q, n2);
}
private static void polyShow(double[] p) {
int pd = polyDegree(p);
for (int i = pd; i >= 0; --i) {
double coeff = p[i];
if (coeff == 0.0) continue;
if (coeff == 1.0) {
if (i < pd) {
System.out.print(" + ");
}
} else if (coeff == -1.0) {
if (i < pd) {
System.out.print(" - ");
} else {
System.out.print("-");
}
} else if (coeff < 0.0) {
if (i < pd) {
System.out.printf(" - %.1f", -coeff);
} else {
System.out.print(coeff);
}
} else {
if (i < pd) {
System.out.printf(" + %.1f", coeff);
} else {
System.out.print(coeff);
}
}
if (i > 1) System.out.printf("x^%d", i);
else if (i == 1) System.out.print("x");
}
System.out.println();
}
public static void main(String[] args) {
double[] n = new double[]{-42.0, 0.0, -12.0, 1.0};
double[] d = new double[]{-3.0, 1.0, 0.0, 0.0};
System.out.print("Numerator : ");
polyShow(n);
System.out.print("Denominator : ");
polyShow(d);
System.out.println("-------------------------------------");
Solution sol = polyLongDiv(n, d);
System.out.print("Quotient : ");
polyShow(sol.quotient);
System.out.print("Remainder : ");
polyShow(sol.remainder);
}
}

View file

@ -0,0 +1,90 @@
// version 1.1.51
typealias IAE = IllegalArgumentException
data class Solution(val quotient: DoubleArray, val remainder: DoubleArray)
fun polyDegree(p: DoubleArray): Int {
for (i in p.size - 1 downTo 0) {
if (p[i] != 0.0) return i
}
return Int.MIN_VALUE
}
fun polyShiftRight(p: DoubleArray, places: Int): DoubleArray {
if (places <= 0) return p
val pd = polyDegree(p)
if (pd + places >= p.size) {
throw IAE("The number of places to be shifted is too large")
}
val d = p.copyOf()
for (i in pd downTo 0) {
d[i + places] = d[i]
d[i] = 0.0
}
return d
}
fun polyMultiply(p: DoubleArray, m: Double) {
for (i in 0 until p.size) p[i] *= m
}
fun polySubtract(p: DoubleArray, s: DoubleArray) {
for (i in 0 until p.size) p[i] -= s[i]
}
fun polyLongDiv(n: DoubleArray, d: DoubleArray): Solution {
if (n.size != d.size) {
throw IAE("Numerator and denominator vectors must have the same size")
}
var nd = polyDegree(n)
val dd = polyDegree(d)
if (dd < 0) {
throw IAE("Divisor must have at least one one-zero coefficient")
}
if (nd < dd) {
throw IAE("The degree of the divisor cannot exceed that of the numerator")
}
val n2 = n.copyOf()
val q = DoubleArray(n.size) // all elements zero by default
while (nd >= dd) {
val d2 = polyShiftRight(d, nd - dd)
q[nd - dd] = n2[nd] / d2[nd]
polyMultiply(d2, q[nd - dd])
polySubtract(n2, d2)
nd = polyDegree(n2)
}
return Solution(q, n2)
}
fun polyShow(p: DoubleArray) {
val pd = polyDegree(p)
for (i in pd downTo 0) {
val coeff = p[i]
if (coeff == 0.0) continue
print (when {
coeff == 1.0 -> if (i < pd) " + " else ""
coeff == -1.0 -> if (i < pd) " - " else "-"
coeff < 0.0 -> if (i < pd) " - ${-coeff}" else "$coeff"
else -> if (i < pd) " + $coeff" else "$coeff"
})
if (i > 1) print("x^$i")
else if (i == 1) print("x")
}
println()
}
fun main(args: Array<String>) {
val n = doubleArrayOf(-42.0, 0.0, -12.0, 1.0)
val d = doubleArrayOf( -3.0, 1.0, 0.0, 0.0)
print("Numerator : ")
polyShow(n)
print("Denominator : ")
polyShow(d)
println("-------------------------------------")
val (q, r) = polyLongDiv(n, d)
print("Quotient : ")
polyShow(q)
print("Remainder : ")
polyShow(r)
}

View file

@ -0,0 +1,44 @@
/* REXX needed by some... */
z='1 -12 0 -42' /* Numerator */
n='1 -3' /* Denominator */
zx=z
nx=n copies('0 ',words(z)-words(n))
qx='' /* Quotient */
Do Until words(zx)<words(n)
Parse Value div(zx,nx) With q zx
qx=qx q
nx=subword(nx,1,words(nx)-1)
End
Say '('show(z)')/('show(n)')=('show(qx)')'
Say 'Remainder:' show(zx)
Exit
div: Procedure
Parse Arg z,n
q=word(z,1)/word(n,1)
zz=''
Do i=1 To words(z)
zz=zz word(z,i)-q*word(n,i)
End
Return q subword(zz,2)
show: Procedure
Parse Arg poly
d=words(poly)-1
res=''
Do i=1 To words(poly)
Select
When d>1 Then fact='*x**'d
When d=1 Then fact='*x'
Otherwise fact=''
End
Select
When word(poly,i)=0 Then p=''
When word(poly,i)=1 Then p='+'substr(fact,2)
When word(poly,i)=-1 Then p='-'substr(fact,2)
When word(poly,i)<0 Then p=word(poly,i)||fact
Otherwise p='+'word(poly,i)||fact
End
res=res p
d=d-1
End
Return strip(space(res,0),'L','+')