September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -0,0 +1,37 @@
|
|||
// version 1.1.2
|
||||
|
||||
/* returns x where (a * x) % b == 1 */
|
||||
fun multInv(a: Int, b: Int): Int {
|
||||
if (b == 1) return 1
|
||||
var aa = a
|
||||
var bb = b
|
||||
var x0 = 0
|
||||
var x1 = 1
|
||||
while (aa > 1) {
|
||||
val q = aa / bb
|
||||
var t = bb
|
||||
bb = aa % bb
|
||||
aa = t
|
||||
t = x0
|
||||
x0 = x1 - q * x0
|
||||
x1 = t
|
||||
}
|
||||
if (x1 < 0) x1 += b
|
||||
return x1
|
||||
}
|
||||
|
||||
fun chineseRemainder(n: IntArray, a: IntArray): Int {
|
||||
val prod = n.fold(1) { acc, i -> acc * i }
|
||||
var sum = 0
|
||||
for (i in 0 until n.size) {
|
||||
val p = prod / n[i]
|
||||
sum += a[i] * multInv(p, n[i]) * p
|
||||
}
|
||||
return sum % prod
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val n = intArrayOf(3, 5, 7)
|
||||
val a = intArrayOf(2, 3, 2)
|
||||
println(chineseRemainder(n, a))
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
function f = chineseRemainder(r, m)
|
||||
s = prod(m) ./ m;
|
||||
[~, t] = gcd(s, m);
|
||||
f = s .* t * r';
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
>> chineseRemainder([2 3 2], [3 5 7])
|
||||
ans = 23
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
EnableExplicit
|
||||
DisableDebugger
|
||||
DataSection
|
||||
LBL_n1:
|
||||
Data.i 3,5,7
|
||||
LBL_a1:
|
||||
Data.i 2,3,2
|
||||
LBL_n2:
|
||||
Data.i 11,12,13
|
||||
LBL_a2:
|
||||
Data.i 10,4,12
|
||||
LBL_n3:
|
||||
Data.i 10,4,9
|
||||
LBL_a3:
|
||||
Data.i 11,22,19
|
||||
EndDataSection
|
||||
|
||||
Procedure ErrorHdl()
|
||||
Print(ErrorMessage())
|
||||
Input()
|
||||
EndProcedure
|
||||
|
||||
Macro PrintData(n,a)
|
||||
Define Idx.i=0
|
||||
Print("[")
|
||||
While n+SizeOf(Integer)*Idx<a
|
||||
Print("( ")
|
||||
Print(Str(PeekI(a+SizeOf(Integer)*Idx)))
|
||||
Print(" . ")
|
||||
Print(Str(PeekI(n+SizeOf(Integer)*Idx)))
|
||||
Print(" )")
|
||||
Idx+1
|
||||
Wend
|
||||
Print(~"]\nx = ")
|
||||
EndMacro
|
||||
|
||||
Procedure.i Produkt_n(n_Adr.i,a_Adr.i)
|
||||
Define p.i=1
|
||||
While n_Adr<a_Adr
|
||||
p*PeekI(n_Adr)
|
||||
n_Adr+SizeOf(Integer)
|
||||
Wend
|
||||
ProcedureReturn p
|
||||
EndProcedure
|
||||
|
||||
Procedure.i Eval_x1(a.i,b.i)
|
||||
Define b0.i=b, x0.i=0, x1.i=1, q.i, t.i
|
||||
If b=1 : ProcedureReturn x1 : EndIf
|
||||
While a>1
|
||||
q=Int(a/b)
|
||||
t=b : b=a%b : a=t
|
||||
t=x0 : x0=x1-q*x0 : x1=t
|
||||
Wend
|
||||
If x1<0 : ProcedureReturn x1+b0 : EndIf
|
||||
ProcedureReturn x1
|
||||
EndProcedure
|
||||
|
||||
Procedure.i ChineseRem(n_Adr.i,a_Adr.i)
|
||||
Define prod.i=Produkt_n(n_Adr,a_Adr), a.i, b.i, p.i, Idx.i=0, sum.i
|
||||
While n_Adr+SizeOf(Integer)*Idx<a_Adr
|
||||
b=PeekI(n_Adr+SizeOf(Integer)*Idx)
|
||||
p=Int(prod/b) : a=p
|
||||
sum+PeekI(a_Adr+SizeOf(Integer)*Idx)*Eval_x1(a,b)*p
|
||||
Idx+1
|
||||
Wend
|
||||
ProcedureReturn sum%prod
|
||||
EndProcedure
|
||||
|
||||
OnErrorCall(@ErrorHdl())
|
||||
OpenConsole("Chinese remainder theorem")
|
||||
PrintData(?LBL_n1,?LBL_a1)
|
||||
PrintN(Str(ChineseRem(?LBL_n1,?LBL_a1)))
|
||||
PrintData(?LBL_n2,?LBL_a2)
|
||||
PrintN(Str(ChineseRem(?LBL_n2,?LBL_a2)))
|
||||
PrintData(?LBL_n3,?LBL_a3)
|
||||
PrintN(Str(ChineseRem(?LBL_n3,?LBL_a3)))
|
||||
Input()
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
fn mul_inv(mut a: i32,mut b: i32)-> i32
|
||||
{ let b0=b;let mut t;let mut q;
|
||||
let mut x0=0;let mut x1=1;
|
||||
if b==1
|
||||
{return 1;
|
||||
}
|
||||
while a>1
|
||||
{ q=a/b;
|
||||
t=b;
|
||||
b=a%b;
|
||||
a=t;
|
||||
t=x0;
|
||||
x0=x1-q*x0;
|
||||
x1=t;
|
||||
}
|
||||
if x1<0
|
||||
{x1+=b0;
|
||||
}
|
||||
x1
|
||||
}
|
||||
|
||||
fn chinese_remainder(n: &mut[i32],a: &mut[i32],len: usize)->i32
|
||||
{
|
||||
let mut p=0;let mut prod=1;let mut sum=0;
|
||||
for i in 0..len
|
||||
{ prod*=n[i];
|
||||
}
|
||||
for i in 0..len
|
||||
{ p=prod/n[i];
|
||||
sum += a[i]*mul_inv(p, n[i])*p;
|
||||
}
|
||||
sum%prod
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
|
||||
let mut n = [3,5,7];
|
||||
let mut a = [2,3,2];
|
||||
let s = a.len();
|
||||
println!("{}",chinese_remainder(&mut n,&mut a,s));
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -16,5 +16,3 @@ func chinese_remainder(*n) {
|
|||
}.sum
|
||||
}
|
||||
}
|
||||
|
||||
say chinese_remainder(3, 5, 7)(2, 3, 2);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
import Darwin
|
||||
|
||||
/*
|
||||
* Function: euclid
|
||||
* Usage: (r,s) = euclid(m,n)
|
||||
* --------------------------
|
||||
* The extended Euclidean algorithm subsequently performs
|
||||
* Euclidean divisions till the remainder is zero and then
|
||||
* returns the Bézout coefficients r and s.
|
||||
*/
|
||||
|
||||
func euclid(_ m:Int, _ n:Int) -> (Int,Int) {
|
||||
if m % n == 0 {
|
||||
return (0,1)
|
||||
} else {
|
||||
let rs = euclid(n % m, m)
|
||||
let r = rs.1 - rs.0 * (n / m)
|
||||
let s = rs.0
|
||||
|
||||
return (r,s)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: gcd
|
||||
* Usage: x = gcd(m,n)
|
||||
* -------------------
|
||||
* The greatest common divisor of two numbers a and b
|
||||
* is expressed by ax + by = gcd(a,b) where x and y are
|
||||
* the Bézout coefficients as determined by the extended
|
||||
* euclidean algorithm.
|
||||
*/
|
||||
|
||||
func gcd(_ m:Int, _ n:Int) -> Int {
|
||||
let rs = euclid(m, n)
|
||||
return m * rs.0 + n * rs.1
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: coprime
|
||||
* Usage: truth = coprime(m,n)
|
||||
* ---------------------------
|
||||
* If two values are coprime, their greatest common
|
||||
* divisor is 1.
|
||||
*/
|
||||
|
||||
func coprime(_ m:Int, _ n:Int) -> Bool {
|
||||
return gcd(m,n) == 1 ? true : false
|
||||
}
|
||||
|
||||
coprime(14,26)
|
||||
//coprime(2,4)
|
||||
|
||||
/*
|
||||
* Function: crt
|
||||
* Usage: x = crt(a,n)
|
||||
* -------------------
|
||||
* The Chinese Remainder Theorem supposes that given the
|
||||
* integers n_1...n_k that are pairwise co-prime, then for
|
||||
* any sequence of integers a_1...a_k there exists an integer
|
||||
* x that solves the system of linear congruences:
|
||||
*
|
||||
* x === a_1 (mod n_1)
|
||||
* ...
|
||||
* x === a_k (mod n_k)
|
||||
*/
|
||||
|
||||
func crt(_ a_i:[Int], _ n_i:[Int]) -> Int {
|
||||
// There is no identity operator for elements of [Int].
|
||||
// The offset of the elements of an enumerated sequence
|
||||
// can be used instead, to determine if two elements of the same
|
||||
// array are the same.
|
||||
let divs = n_i.enumerated()
|
||||
|
||||
// Check if elements of n_i are pairwise coprime divs.filter{ $0.0 < n.0 }
|
||||
divs.forEach{
|
||||
n in divs.filter{ $0.0 < n.0 }.forEach{
|
||||
assert(coprime(n.1, $0.1))
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate factor N
|
||||
let N = n_i.map{$0}.reduce(1, *)
|
||||
|
||||
// Euclidean algorithm determines s_i (and r_i)
|
||||
var s:[Int] = []
|
||||
|
||||
// Using euclidean algorithm to calculate r_i, s_i
|
||||
n_i.forEach{ s += [euclid($0, N / $0).1] }
|
||||
|
||||
// Solve for x
|
||||
var x = 0
|
||||
a_i.enumerated().forEach{
|
||||
x += $0.1 * s[$0.0] * N / n_i[$0.0]
|
||||
}
|
||||
|
||||
// Return minimal solution
|
||||
return x % N
|
||||
}
|
||||
|
||||
let a = [2,3,2]
|
||||
let n = [3,5,7]
|
||||
|
||||
let x = crt(a,n)
|
||||
|
||||
print(x)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
var BN=Import("zklBigNum"), one=BN(1);
|
||||
|
||||
fcn crt(xs,ys){
|
||||
p:=xs.reduce('*,BN(1));
|
||||
X:=BN(0);
|
||||
foreach x,y in (xs.zip(ys)){
|
||||
q:=p/x;
|
||||
z,s,_:=q.gcdExt(x);
|
||||
if(z!=one) throw(Exception.ValueError("%d not coprime".fmt(x)));
|
||||
X+=y*s*q;
|
||||
}
|
||||
return(X % p);
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
println(crt(T(3,5,7), T(2,3,2))); //-->23
|
||||
println(crt(T(11,12,13),T(10,4,12))); //-->1000
|
||||
println(crt(T(11,22,19), T(10,4,9))); //-->ValueError: 11 not coprime
|
||||
Loading…
Add table
Add a link
Reference in a new issue