Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Chinese-remainder-theorem/00-META.yaml
Normal file
2
Task/Chinese-remainder-theorem/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Chinese_remainder_theorem
|
||||
49
Task/Chinese-remainder-theorem/00-TASK.txt
Normal file
49
Task/Chinese-remainder-theorem/00-TASK.txt
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
Suppose <math>n_1</math>, <math>n_2</math>, <math>\ldots</math>, <math>n_k</math> are positive [[integer]]s that are pairwise co-prime.
|
||||
|
||||
Then, for any given sequence of integers <math>a_1</math>, <math>a_2</math>, <math>\dots</math>, <math>a_k</math>, there exists an integer <math>x</math> solving the following system of simultaneous congruences:
|
||||
|
||||
::: <math>\begin{align}
|
||||
x &\equiv a_1 \pmod{n_1} \\
|
||||
x &\equiv a_2 \pmod{n_2} \\
|
||||
&{}\ \ \vdots \\
|
||||
x &\equiv a_k \pmod{n_k}
|
||||
\end{align}</math>
|
||||
|
||||
Furthermore, all solutions <math>x</math> of this system are congruent modulo the product, <math>N=n_1n_2\ldots n_k</math>.
|
||||
|
||||
|
||||
;Task:
|
||||
Write a program to solve a system of linear congruences by applying the [[wp:Chinese Remainder Theorem|Chinese Remainder Theorem]].
|
||||
|
||||
If the system of equations cannot be solved, your program must somehow indicate this.
|
||||
|
||||
(It may throw an exception or return a special false value.)
|
||||
|
||||
Since there are infinitely many solutions, the program should return the unique solution <math>s</math> where <math>0 \leq s \leq n_1n_2\ldots n_k</math>.
|
||||
|
||||
|
||||
''Show the functionality of this program'' by printing the result such that the <math>n</math>'s are <math>[3,5,7]</math> and the <math>a</math>'s are <math>[2,3,2]</math>.
|
||||
|
||||
|
||||
'''Algorithm''': The following algorithm only applies if the <math>n_i</math>'s are pairwise co-prime.
|
||||
|
||||
Suppose, as above, that a solution is required for the system of congruences:
|
||||
|
||||
::: <math>x \equiv a_i \pmod{n_i} \quad\mathrm{for}\; i = 1, \ldots, k</math>
|
||||
|
||||
Again, to begin, the product <math>N = n_1n_2 \ldots n_k</math> is defined.
|
||||
|
||||
Then a solution <math>x</math> can be found as follows:
|
||||
|
||||
For each <math>i</math>, the integers <math>n_i</math> and <math>N/n_i</math> are co-prime.
|
||||
|
||||
Using the [[wp:Extended Euclidean algorithm|Extended Euclidean algorithm]], we can find integers <math>r_i</math> and <math>s_i</math> such that <math>r_i n_i + s_i N/n_i = 1</math>.
|
||||
|
||||
Then, one solution to the system of simultaneous congruences is:
|
||||
|
||||
::: <math>x = \sum_{i=1}^k a_i s_i N/n_i</math>
|
||||
|
||||
and the minimal solution,
|
||||
|
||||
::: <math>x \pmod{N}</math>.
|
||||
<br><br>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
F mul_inv(=a, =b)
|
||||
V b0 = b
|
||||
V x0 = 0
|
||||
V x1 = 1
|
||||
I b == 1
|
||||
R 1
|
||||
L a > 1
|
||||
V q = a I/ b
|
||||
(a, b) = (b, a % b)
|
||||
(x0, x1) = (x1 - q * x0, x0)
|
||||
I x1 < 0
|
||||
x1 += b0
|
||||
R x1
|
||||
|
||||
F chinese_remainder(n, a)
|
||||
V sum = 0
|
||||
V prod = product(n)
|
||||
L(n_i, a_i) zip(n, a)
|
||||
V p = prod I/ n_i
|
||||
sum += a_i * mul_inv(p, n_i) * p
|
||||
R sum % prod
|
||||
|
||||
V n = [3, 5, 7]
|
||||
V a = [2, 3, 2]
|
||||
print(chinese_remainder(n, a))
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
* Chinese remainder theorem 06/09/2015
|
||||
CHINESE CSECT
|
||||
USING CHINESE,R12 base addr
|
||||
LR R12,R15
|
||||
BEGIN LA R9,1 m=1
|
||||
LA R6,1 j=1
|
||||
LOOPJ C R6,NN do j=1 to nn
|
||||
BH ELOOPJ
|
||||
LR R1,R6 j
|
||||
SLA R1,2 j*4
|
||||
M R8,N-4(R1) m=m*n(j)
|
||||
LA R6,1(R6) j=j+1
|
||||
B LOOPJ
|
||||
ELOOPJ LA R6,1 x=1
|
||||
LOOPX CR R6,R9 do x=1 to m
|
||||
BH ELOOPX
|
||||
LA R7,1 i=1
|
||||
LOOPI C R7,NN do i=1 to nn
|
||||
BH ELOOPI
|
||||
LR R1,R7 i
|
||||
SLA R1,2 i*4
|
||||
LR R5,R6 x
|
||||
LA R4,0
|
||||
D R4,N-4(R1) x//n(i)
|
||||
C R4,A-4(R1) if x//n(i)^=a(i)
|
||||
BNE ITERX then iterate x
|
||||
LA R7,1(R7) i=i+1
|
||||
B LOOPI
|
||||
ELOOPI MVC PG(2),=C'x='
|
||||
XDECO R6,PG+2 edit x
|
||||
XPRNT PG,14 print buffer
|
||||
B RETURN
|
||||
ITERX LA R6,1(R6) x=x+1
|
||||
B LOOPX
|
||||
ELOOPX XPRNT NOSOL,17 print
|
||||
RETURN XR R15,R15 rc=0
|
||||
BR R14
|
||||
NN DC F'3'
|
||||
N DC F'3',F'5',F'7'
|
||||
A DC F'2',F'3',F'2'
|
||||
PG DS CL80
|
||||
NOSOL DC CL17'no solution found'
|
||||
YREGS
|
||||
END CHINESE
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/* ARM assembly AARCH64 Raspberry PI 3B */
|
||||
/* program chineserem64.s */
|
||||
|
||||
/************************************/
|
||||
/* Constantes */
|
||||
/************************************/
|
||||
/* for this file see task include a file in language AArch64 assembly*/
|
||||
.include "../includeConstantesARM64.inc"
|
||||
|
||||
|
||||
/*********************************/
|
||||
/* Initialized data */
|
||||
/*********************************/
|
||||
.data
|
||||
szMessResult: .asciz "Result = "
|
||||
szCarriageReturn: .asciz "\n"
|
||||
.align 2
|
||||
arrayN: .quad 3,5,7
|
||||
arrayA: .quad 2,3,2
|
||||
.equ ARRAYSIZE, (. - arrayA)/8
|
||||
/*********************************/
|
||||
/* UnInitialized data */
|
||||
/*********************************/
|
||||
.bss
|
||||
sZoneConv: .skip 24
|
||||
/*********************************/
|
||||
/* code section */
|
||||
/*********************************/
|
||||
.text
|
||||
.global main
|
||||
main:
|
||||
ldr x0,qAdrarrayN // N array address
|
||||
ldr x1,qAdrarrayA // A array address
|
||||
mov x2,#ARRAYSIZE // array size
|
||||
bl chineseremainder
|
||||
|
||||
ldr x1,qAdrsZoneConv
|
||||
bl conversion10 // call décimal conversion
|
||||
mov x0,#3
|
||||
ldr x1,qAdrszMessResult
|
||||
ldr x2,qAdrsZoneConv // insert conversion in message
|
||||
ldr x3,qAdrszCarriageReturn
|
||||
bl displayStrings // display message
|
||||
|
||||
100: // standard end of the program
|
||||
mov x0, #0 // return code
|
||||
mov x8,EXIT
|
||||
svc #0 // perform the system call
|
||||
qAdrszCarriageReturn: .quad szCarriageReturn
|
||||
qAdrsZoneConv: .quad sZoneConv
|
||||
qAdrszMessResult: .quad szMessResult
|
||||
qAdrarrayA: .quad arrayA
|
||||
qAdrarrayN: .quad arrayN
|
||||
|
||||
/******************************************************************/
|
||||
/* compute chinese remainder */
|
||||
/******************************************************************/
|
||||
/* x0 contains n array address */
|
||||
/* x1 contains a array address */
|
||||
/* x2 contains array size */
|
||||
chineseremainder:
|
||||
stp x1,lr,[sp,-16]! // save registers
|
||||
stp x2,x3,[sp,-16]! // save registers
|
||||
stp x4,x5,[sp,-16]! // save registers
|
||||
stp x6,x7,[sp,-16]! // save registers
|
||||
stp x8,x9,[sp,-16]! // save registers
|
||||
mov x4,#1 // product
|
||||
mov x5,#0 // sum
|
||||
mov x6,#0 // indice
|
||||
1:
|
||||
ldr x3,[x0,x6,lsl #3] // load a value
|
||||
mul x4,x3,x4 // compute product
|
||||
add x6,x6,#1
|
||||
cmp x6,x2
|
||||
blt 1b
|
||||
mov x6,#0
|
||||
mov x7,x0 // save entry
|
||||
mov x8,x1
|
||||
mov x9,x2
|
||||
2:
|
||||
mov x0,x4 // product
|
||||
ldr x1,[x7,x6,lsl #3] // value of n
|
||||
sdiv x2,x0,x1
|
||||
mov x0,x2 // p
|
||||
bl inverseModulo
|
||||
mul x0,x2,x0 // = product / n * invmod
|
||||
ldr x3,[x8,x6,lsl #3] // value a
|
||||
madd x5,x0,x3,x5 // sum = sum + (result1 * a)
|
||||
add x6,x6,#1
|
||||
cmp x6,x9
|
||||
blt 2b
|
||||
sdiv x1,x5,x4 // divide sum by produc
|
||||
msub x0,x1,x4,x5 // compute remainder
|
||||
100:
|
||||
ldp x8,x9,[sp],16 // restaur registers
|
||||
ldp x6,x7,[sp],16 // restaur registers
|
||||
ldp x4,x5,[sp],16 // restaur registers
|
||||
ldp x2,x3,[sp],16 // restaur registers
|
||||
ldp x1,lr,[sp],16 // restaur registers
|
||||
ret
|
||||
/***************************************************/
|
||||
/* Calcul modulo inverse */
|
||||
/***************************************************/
|
||||
/* x0 cont.quad number, x1 modulo */
|
||||
/* x0 return result */
|
||||
inverseModulo:
|
||||
stp x1,lr,[sp,-16]! // save registers
|
||||
stp x2,x3,[sp,-16]! // save registers
|
||||
stp x4,x5,[sp,-16]! // save registers
|
||||
stp x6,x7,[sp,-16]! // save registers
|
||||
mov x7,x1 // save Modulo
|
||||
mov x6,x1 // A x0=B
|
||||
mov x4,#1 // X
|
||||
mov x5,#0 // Y
|
||||
1: //
|
||||
cmp x0,#0 // B = 0
|
||||
beq 2f
|
||||
mov x1,x0 // T = B
|
||||
mov x0,x6 // A
|
||||
sdiv x2,x0,x1 // A / T
|
||||
msub x0,x2,x1,x0 // B and x2=Q
|
||||
mov x6,x1 // A=T
|
||||
mov x1,x4 // T=X
|
||||
msub x4,x2,x1,x5 // X=Y-(Q*T)
|
||||
mov x5,x1 // Y=T
|
||||
b 1b
|
||||
2:
|
||||
add x7,x7,x5 // = Y + N
|
||||
cmp x5,#0 // Y > 0
|
||||
bge 3f
|
||||
mov x0,x7
|
||||
b 100f
|
||||
3:
|
||||
mov x0,x5
|
||||
100:
|
||||
ldp x6,x7,[sp],16 // restaur registers
|
||||
ldp x4,x5,[sp],16 // restaur registers
|
||||
ldp x2,x3,[sp],16 // restaur registers
|
||||
ldp x1,lr,[sp],16 // restaur registers
|
||||
ret
|
||||
/***************************************************/
|
||||
/* display multi strings */
|
||||
/***************************************************/
|
||||
/* x0 contains number strings address */
|
||||
/* x1 address string1 */
|
||||
/* x2 address string2 */
|
||||
/* x3 address string3 */
|
||||
/* other address on the stack */
|
||||
/* thinck to add number other address * 4 to add to the stack */
|
||||
displayStrings: // INFO: affichageStrings
|
||||
stp x1,lr,[sp,-16]! // save registers
|
||||
stp x2,x3,[sp,-16]! // save registers
|
||||
stp x4,x5,[sp,-16]! // save registers
|
||||
add fp,sp,#48 // save paraméters address (6 registers saved * 8 bytes)
|
||||
mov x4,x0 // save strings number
|
||||
cmp x4,#0 // 0 string -> end
|
||||
ble 100f
|
||||
mov x0,x1 // string 1
|
||||
bl affichageMess
|
||||
cmp x4,#1 // number > 1
|
||||
ble 100f
|
||||
mov x0,x2
|
||||
bl affichageMess
|
||||
cmp x4,#2
|
||||
ble 100f
|
||||
mov x0,x3
|
||||
bl affichageMess
|
||||
cmp x4,#3
|
||||
ble 100f
|
||||
mov x3,#3
|
||||
sub x2,x4,#4
|
||||
1: // loop extract address string on stack
|
||||
ldr x0,[fp,x2,lsl #3]
|
||||
bl affichageMess
|
||||
subs x2,x2,#1
|
||||
bge 1b
|
||||
100:
|
||||
ldp x4,x5,[sp],16 // restaur registers
|
||||
ldp x2,x3,[sp],16 // restaur registers
|
||||
ldp x1,lr,[sp],16 // restaur registers
|
||||
ret
|
||||
/***************************************************/
|
||||
/* ROUTINES INCLUDE */
|
||||
/***************************************************/
|
||||
/* for this file see task include a file in language AArch64 assembly */
|
||||
.include "../includeARM64.inc"
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/* ARM assembly Raspberry PI or android with termux */
|
||||
/* program chineserem.s */
|
||||
|
||||
/* REMARK 1 : this program use routines in a include file
|
||||
see task Include a file language arm assembly
|
||||
for the routine affichageMess conversion10
|
||||
see at end of this program the instruction include */
|
||||
/* for constantes see task include a file in arm assembly */
|
||||
/************************************/
|
||||
/* Constantes */
|
||||
/************************************/
|
||||
.include "../constantes.inc"
|
||||
|
||||
|
||||
/*********************************/
|
||||
/* Initialized data */
|
||||
/*********************************/
|
||||
.data
|
||||
szMessResult: .asciz "Result = "
|
||||
szCarriageReturn: .asciz "\n"
|
||||
.align 2
|
||||
arrayN: .int 3,5,7
|
||||
arrayA: .int 2,3,2
|
||||
.equ ARRAYSIZE, (. - arrayA)/4
|
||||
/*********************************/
|
||||
/* UnInitialized data */
|
||||
/*********************************/
|
||||
.bss
|
||||
sZoneConv: .skip 24
|
||||
/*********************************/
|
||||
/* code section */
|
||||
/*********************************/
|
||||
.text
|
||||
.global main
|
||||
main:
|
||||
ldr r0,iAdrarrayN @ N array address
|
||||
ldr r1,iAdrarrayA @ A array address
|
||||
mov r2,#ARRAYSIZE @ array size
|
||||
bl chineseremainder
|
||||
|
||||
ldr r1,iAdrsZoneConv
|
||||
bl conversion10 @ call décimal conversion
|
||||
mov r0,#3
|
||||
ldr r1,iAdrszMessResult
|
||||
ldr r2,iAdrsZoneConv @ insert conversion in message
|
||||
ldr r3,iAdrszCarriageReturn
|
||||
bl displayStrings @ display message
|
||||
|
||||
100: @ standard end of the program
|
||||
mov r0, #0 @ return code
|
||||
mov r7, #EXIT @ request to exit program
|
||||
svc #0 @ perform the system call
|
||||
iAdrszCarriageReturn: .int szCarriageReturn
|
||||
iAdrsZoneConv: .int sZoneConv
|
||||
iAdrszMessResult: .int szMessResult
|
||||
iAdrarrayA: .int arrayA
|
||||
iAdrarrayN: .int arrayN
|
||||
|
||||
/******************************************************************/
|
||||
/* compute chinese remainder */
|
||||
/******************************************************************/
|
||||
/* r0 contains n array address */
|
||||
/* r1 contains a array address */
|
||||
/* r2 contains array size */
|
||||
chineseremainder:
|
||||
push {r1-r9,lr} @ save registers
|
||||
mov r4,#1 @ product
|
||||
mov r5,#0 @ sum
|
||||
mov r6,#0 @ indice
|
||||
1:
|
||||
ldr r3,[r0,r6,lsl #2] @ load a value
|
||||
mul r4,r3,r4 @ compute product
|
||||
add r6,#1
|
||||
cmp r6,r2
|
||||
blt 1b
|
||||
mov r6,#0
|
||||
mov r7,r0 @ save entry
|
||||
mov r8,r1
|
||||
mov r9,r2
|
||||
2:
|
||||
mov r0,r4 @ product
|
||||
ldr r1,[r7,r6,lsl #2] @ value of n
|
||||
bl division
|
||||
mov r0,r2 @ p
|
||||
bl inverseModulo
|
||||
mul r0,r2,r0 @ = product / n * invmod
|
||||
ldr r3,[r8,r6,lsl #2] @ value a
|
||||
mla r5,r0,r3,r5 @ sum = sum + (result1 * a)
|
||||
add r6,#1
|
||||
cmp r6,r9
|
||||
blt 2b
|
||||
mov r0,r5 @ sum
|
||||
mov r1,r4 @ product
|
||||
bl division
|
||||
mov r0,r3
|
||||
|
||||
100:
|
||||
pop {r1-r9,pc} @ restaur registers
|
||||
/***************************************************/
|
||||
/* Calcul modulo inverse */
|
||||
/***************************************************/
|
||||
/* r0 containt number, r1 modulo */
|
||||
/* x0 return result */
|
||||
inverseModulo:
|
||||
push {r1-r7,lr} @ save registers
|
||||
mov r7,r1 // save Modulo
|
||||
mov r6,r1 // A r0=B
|
||||
mov r4,#1 // X
|
||||
mov r5,#0 // Y
|
||||
1: //
|
||||
cmp r0,#0 // B = 0
|
||||
beq 2f
|
||||
mov r1,r0 // T = B
|
||||
mov r0,r6 // A
|
||||
bl division // A / T
|
||||
mov r0,r3 // B and r2=Q
|
||||
mov r6,r1 // A=T
|
||||
mov r1,r4 // T=X
|
||||
mls r4,r2,r1,r5 // X=Y-(Q*T)
|
||||
mov r5,r1 // Y=T
|
||||
b 1b
|
||||
2:
|
||||
add r7,r7,r5 // = Y + N
|
||||
cmp r5,#0 // Y > 0
|
||||
bge 3f
|
||||
mov r0,r7
|
||||
b 100f
|
||||
3:
|
||||
mov r0,r5
|
||||
100:
|
||||
pop {r1-r7,pc}
|
||||
/***************************************************/
|
||||
/* display multi strings */
|
||||
/***************************************************/
|
||||
/* r0 contains number strings address */
|
||||
/* r1 address string1 */
|
||||
/* r2 address string2 */
|
||||
/* r3 address string3 */
|
||||
/* other address on the stack */
|
||||
/* thinck to add number other address * 4 to add to the stack */
|
||||
displayStrings: @ INFO: affichageStrings
|
||||
push {r1-r4,fp,lr} @ save des registres
|
||||
add fp,sp,#24 @ save paraméters address (6 registers saved * 4 bytes)
|
||||
mov r4,r0 @ save strings number
|
||||
cmp r4,#0 @ 0 string -> end
|
||||
ble 100f
|
||||
mov r0,r1 @ string 1
|
||||
bl affichageMess
|
||||
cmp r4,#1 @ number > 1
|
||||
ble 100f
|
||||
mov r0,r2
|
||||
bl affichageMess
|
||||
cmp r4,#2
|
||||
ble 100f
|
||||
mov r0,r3
|
||||
bl affichageMess
|
||||
cmp r4,#3
|
||||
ble 100f
|
||||
mov r3,#3
|
||||
sub r2,r4,#4
|
||||
1: @ loop extract address string on stack
|
||||
ldr r0,[fp,r2,lsl #2]
|
||||
bl affichageMess
|
||||
subs r2,#1
|
||||
bge 1b
|
||||
100:
|
||||
pop {r1-r4,fp,pc}
|
||||
/***************************************************/
|
||||
/* ROUTINES INCLUDE */
|
||||
/***************************************************/
|
||||
.include "../affichage.inc"
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# Usage: GAWK -f CHINESE_REMAINDER_THEOREM.AWK
|
||||
BEGIN {
|
||||
len = split("3 5 7", n)
|
||||
len = split("2 3 2", a)
|
||||
printf("%d\n", chineseremainder(n, a, len))
|
||||
}
|
||||
function chineseremainder(n, a, len, p, i, prod, sum) {
|
||||
prod = 1
|
||||
sum = 0
|
||||
for (i = 1; i <= len; i++)
|
||||
prod *= n[i]
|
||||
for (i = 1; i <= len; i++) {
|
||||
p = prod / n[i]
|
||||
sum += a[i] * mulinv(p, n[i]) * p
|
||||
}
|
||||
return sum % prod
|
||||
}
|
||||
function mulinv(a, b, b0, t, q, x0, x1) {
|
||||
# returns x where (a * x) % b == 1
|
||||
b0 = b
|
||||
x0 = 0
|
||||
x1 = 1
|
||||
if (b == 1)
|
||||
return 1
|
||||
while (a > 1) {
|
||||
q = int(a / b)
|
||||
t = b
|
||||
b = a % b
|
||||
a = t
|
||||
t = x0
|
||||
x0 = x1 - q * x0
|
||||
x1 = t
|
||||
}
|
||||
if (x1 < 0)
|
||||
x1 += b0
|
||||
return x1
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
INT FUNC MulInv(INT a,b)
|
||||
INT b0,x0,x1,q,tmp
|
||||
|
||||
IF b=1 THEN RETURN (1) FI
|
||||
|
||||
b0=b x0=0 x1=1
|
||||
WHILE a>1
|
||||
DO
|
||||
q=a/b
|
||||
|
||||
tmp=b
|
||||
b=a MOD b
|
||||
a=tmp
|
||||
|
||||
tmp=x0
|
||||
x0=x1-q*x0
|
||||
x1=tmp
|
||||
OD
|
||||
IF x1<0 THEN
|
||||
x1==+b0
|
||||
FI
|
||||
RETURN (x1)
|
||||
|
||||
INT FUNC ChineseRemainder(BYTE ARRAY n,a BYTE len)
|
||||
INT prod,sum,p,m
|
||||
BYTE i
|
||||
|
||||
prod=1 sum=0
|
||||
FOR i=0 TO len-1
|
||||
DO
|
||||
prod==*n(i)
|
||||
OD
|
||||
FOR i=0 TO len-1
|
||||
DO
|
||||
p=prod/n(i)
|
||||
m=MulInv(p,n(i))
|
||||
sum==+a(i)*m*p
|
||||
OD
|
||||
RETURN (sum MOD prod)
|
||||
|
||||
PROC Main()
|
||||
BYTE ARRAY n=[3 5 7],a=[2 3 2]
|
||||
INT res
|
||||
|
||||
res=ChineseRemainder(n,a,3)
|
||||
PrintI(res)
|
||||
RETURN
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
with Ada.Text_IO, Mod_Inv;
|
||||
|
||||
procedure Chin_Rema is
|
||||
N: array(Positive range <>) of Positive := (3, 5, 7);
|
||||
A: array(Positive range <>) of Positive := (2, 3, 2);
|
||||
Tmp: Positive;
|
||||
Prod: Positive := 1;
|
||||
Sum: Natural := 0;
|
||||
|
||||
begin
|
||||
for I in N'Range loop
|
||||
Prod := Prod * N(I);
|
||||
end loop;
|
||||
|
||||
for I in A'Range loop
|
||||
Tmp := Prod / N(I);
|
||||
Sum := Sum + A(I) * Mod_Inv.Inverse(Tmp, N(I)) * Tmp;
|
||||
end loop;
|
||||
Ada.Text_IO.Put_Line(Integer'Image(Sum mod Prod));
|
||||
end Chin_Rema;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
mulInv: function [a0, b0][
|
||||
[a b x0]: @[a0 b0 0]
|
||||
result: 1
|
||||
if b = 1 -> return result
|
||||
while [a > 1][
|
||||
q: a / b
|
||||
a: a % b
|
||||
tmp: a
|
||||
a: b
|
||||
b: tmp
|
||||
result: result - q * x0
|
||||
tmp: x0
|
||||
x0: result
|
||||
result: tmp
|
||||
]
|
||||
if result < 0 -> result: result + b0
|
||||
return result
|
||||
]
|
||||
|
||||
chineseRemainder: function [N, A][
|
||||
prod: 1
|
||||
s: 0
|
||||
|
||||
loop N 'x -> prod: prod * x
|
||||
|
||||
loop.with:'i N 'x [
|
||||
p: prod / x
|
||||
s: s + (mulInv p x) * p * A\[i]
|
||||
]
|
||||
return s % prod
|
||||
]
|
||||
|
||||
print chineseRemainder [3 5 7] [2 3 2]
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
MulInv←⊣|·⊑{0=𝕨?1‿0;(⌽-(0⋈𝕩⌊∘÷𝕨)⊸×)𝕨𝕊˜𝕨|𝕩}
|
||||
ChRem←{
|
||||
num 𝕊 rem:
|
||||
prod←×´num
|
||||
prod|+´rem×(⊢×num⊸(MulInv¨))prod⌊∘÷num
|
||||
}
|
||||
|
||||
•Show 3‿5‿7 ChRem 2‿3‿2
|
||||
•Show 10‿4‿9 ChRem 11‿22‿19
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
23
|
||||
172
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
( ( mul-inv
|
||||
= a b b0 q x0 x1
|
||||
. !arg:(?a.?b:?b0)
|
||||
& ( !b:1
|
||||
| 0:?x0
|
||||
& 1:?x1
|
||||
& whl
|
||||
' ( !a:>1
|
||||
& (!b.mod$(!a.!b):?q.!x1+-1*!q*!x0.!x0)
|
||||
: (?a.?b.?x0.?x1)
|
||||
)
|
||||
& ( !x1:<0&!b0+!x1
|
||||
| !x1
|
||||
)
|
||||
)
|
||||
)
|
||||
& ( chinese-remainder
|
||||
= n a as p ns ni prod sum
|
||||
. !arg:(?n.?a)
|
||||
& 1:?prod
|
||||
& 0:?sum
|
||||
& !n:?ns
|
||||
& whl'(!ns:%?ni ?ns&!prod*!ni:?prod)
|
||||
& !n:?ns
|
||||
& !a:?as
|
||||
& whl
|
||||
' ( !ns:%?ni ?ns
|
||||
& !as:%?ai ?as
|
||||
& div$(!prod.!ni):?p
|
||||
& !sum+!ai*mul-inv$(!p.!ni)*!p:?sum
|
||||
)
|
||||
& mod$(!sum.!prod):?arg
|
||||
& !arg
|
||||
)
|
||||
& 3 5 7:?n
|
||||
& 2 3 2:?a
|
||||
& put$(str$(chinese-remainder$(!n.!a) \n))
|
||||
);
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// Requires C++17
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <execution>
|
||||
|
||||
template<typename _Ty> _Ty mulInv(_Ty a, _Ty b) {
|
||||
_Ty b0 = b;
|
||||
_Ty x0 = 0;
|
||||
_Ty x1 = 1;
|
||||
|
||||
if (b == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (a > 1) {
|
||||
_Ty q = a / b;
|
||||
_Ty amb = a % b;
|
||||
a = b;
|
||||
b = amb;
|
||||
|
||||
_Ty xqx = x1 - q * x0;
|
||||
x1 = x0;
|
||||
x0 = xqx;
|
||||
}
|
||||
|
||||
if (x1 < 0) {
|
||||
x1 += b0;
|
||||
}
|
||||
|
||||
return x1;
|
||||
}
|
||||
|
||||
template<typename _Ty> _Ty chineseRemainder(std::vector<_Ty> n, std::vector<_Ty> a) {
|
||||
_Ty prod = std::reduce(std::execution::seq, n.begin(), n.end(), (_Ty)1, [](_Ty a, _Ty b) { return a * b; });
|
||||
|
||||
_Ty sm = 0;
|
||||
for (int i = 0; i < n.size(); i++) {
|
||||
_Ty p = prod / n[i];
|
||||
sm += a[i] * mulInv(p, n[i]) * p;
|
||||
}
|
||||
|
||||
return sm % prod;
|
||||
}
|
||||
|
||||
int main() {
|
||||
vector<int> n = { 3, 5, 7 };
|
||||
vector<int> a = { 2, 3, 2 };
|
||||
|
||||
cout << chineseRemainder(n,a) << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace ChineseRemainderTheorem
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
int[] n = { 3, 5, 7 };
|
||||
int[] a = { 2, 3, 2 };
|
||||
|
||||
int result = ChineseRemainderTheorem.Solve(n, a);
|
||||
|
||||
int counter = 0;
|
||||
int maxCount = n.Length - 1;
|
||||
while (counter <= maxCount)
|
||||
{
|
||||
Console.WriteLine($"{result} ≡ {a[counter]} (mod {n[counter]})");
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChineseRemainderTheorem
|
||||
{
|
||||
public static int Solve(int[] n, int[] a)
|
||||
{
|
||||
int prod = n.Aggregate(1, (i, j) => i * j);
|
||||
int p;
|
||||
int sm = 0;
|
||||
for (int i = 0; i < n.Length; i++)
|
||||
{
|
||||
p = prod / n[i];
|
||||
sm += a[i] * ModularMultiplicativeInverse(p, n[i]) * p;
|
||||
}
|
||||
return sm % prod;
|
||||
}
|
||||
|
||||
private static int ModularMultiplicativeInverse(int a, int mod)
|
||||
{
|
||||
int b = a % mod;
|
||||
for (int x = 1; x < mod; x++)
|
||||
{
|
||||
if ((b * x) % mod == 1)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Task/Chinese-remainder-theorem/C/chinese-remainder-theorem.c
Normal file
39
Task/Chinese-remainder-theorem/C/chinese-remainder-theorem.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <stdio.h>
|
||||
|
||||
// returns x where (a * x) % b == 1
|
||||
int mul_inv(int a, int b)
|
||||
{
|
||||
int b0 = b, t, q;
|
||||
int x0 = 0, 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;
|
||||
return x1;
|
||||
}
|
||||
|
||||
int chinese_remainder(int *n, int *a, int len)
|
||||
{
|
||||
int p, i, prod = 1, sum = 0;
|
||||
|
||||
for (i = 0; i < len; i++) prod *= n[i];
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
p = prod / n[i];
|
||||
sum += a[i] * mul_inv(p, n[i]) * p;
|
||||
}
|
||||
|
||||
return sum % prod;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int n[] = { 3, 5, 7 };
|
||||
int a[] = { 2, 3, 2 };
|
||||
|
||||
printf("%d\n", chinese_remainder(n, a, sizeof(n)/sizeof(n[0])));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
(ns test-p.core
|
||||
(:require [clojure.math.numeric-tower :as math]))
|
||||
|
||||
(defn extended-gcd
|
||||
"The extended Euclidean algorithm
|
||||
Returns a list containing the GCD and the Bézout coefficients
|
||||
corresponding to the inputs. "
|
||||
[a b]
|
||||
(cond (zero? a) [(math/abs b) 0 1]
|
||||
(zero? b) [(math/abs a) 1 0]
|
||||
:else (loop [s 0
|
||||
s0 1
|
||||
t 1
|
||||
t0 0
|
||||
r (math/abs b)
|
||||
r0 (math/abs a)]
|
||||
(if (zero? r)
|
||||
[r0 s0 t0]
|
||||
(let [q (quot r0 r)]
|
||||
(recur (- s0 (* q s)) s
|
||||
(- t0 (* q t)) t
|
||||
(- r0 (* q r)) r))))))
|
||||
|
||||
(defn chinese_remainder
|
||||
" Main routine to return the chinese remainder "
|
||||
[n a]
|
||||
(let [prod (apply * n)
|
||||
reducer (fn [sum [n_i a_i]]
|
||||
(let [p (quot prod n_i) ; p = prod / n_i
|
||||
egcd (extended-gcd p n_i) ; Extended gcd
|
||||
inv_p (second egcd)] ; Second item is the inverse
|
||||
(+ sum (* a_i inv_p p))))
|
||||
sum-prod (reduce reducer 0 (map vector n a))] ; Replaces the Python for loop to sum
|
||||
; (map vector n a) is same as
|
||||
; ; Python's version Zip (n, a)
|
||||
(mod sum-prod prod))) ; Result line
|
||||
|
||||
(def n [3 5 7])
|
||||
(def a [2 3 2])
|
||||
|
||||
(println (chinese_remainder n a))
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
crt = (n,a) ->
|
||||
sum = 0
|
||||
prod = n.reduce (a,c) -> a*c
|
||||
for [ni,ai] in _.zip n,a
|
||||
p = prod // ni
|
||||
sum += ai * p * mulInv p,ni
|
||||
sum % prod
|
||||
|
||||
mulInv = (a,b) ->
|
||||
b0 = b
|
||||
[x0,x1] = [0,1]
|
||||
if b==1 then return 1
|
||||
while a > 1
|
||||
q = a // b
|
||||
[a,b] = [b, a % b]
|
||||
[x0,x1] = [x1-q*x0, x0]
|
||||
if x1 < 0 then x1 += b0
|
||||
x1
|
||||
|
||||
print crt [3,5,7], [2,3,2]
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
(defun chinese-remainder (am)
|
||||
"Calculates the Chinese Remainder for the given set of integer modulo pairs.
|
||||
Note: All the ni and the N must be coprimes."
|
||||
(loop :for (a . m) :in am
|
||||
:with mtot = (reduce #'* (mapcar #'(lambda(X) (cdr X)) am))
|
||||
:with sum = 0
|
||||
:finally (return (mod sum mtot))
|
||||
:do
|
||||
(incf sum (* a (invmod (/ mtot m) m) (/ mtot m)))))
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
def extended_gcd(a, b)
|
||||
last_remainder, remainder = a.abs, b.abs
|
||||
x, last_x = 0, 1
|
||||
|
||||
until remainder == 0
|
||||
tmp = remainder
|
||||
quotient, remainder = last_remainder.divmod(remainder)
|
||||
last_remainder = tmp
|
||||
x, last_x = last_x - quotient * x, x
|
||||
end
|
||||
|
||||
return last_remainder, last_x * (a < 0 ? -1 : 1)
|
||||
end
|
||||
|
||||
|
||||
def invmod(e, et)
|
||||
g, x = extended_gcd(e, et)
|
||||
unless g == 1
|
||||
raise "Multiplicative inverse modulo does not exist"
|
||||
end
|
||||
return x % et
|
||||
end
|
||||
|
||||
|
||||
def chinese_remainder(mods, remainders)
|
||||
max = mods.product
|
||||
series = remainders.zip(mods).map { |r, m| r * max * invmod(max // m, m) // m }
|
||||
return series.sum % max
|
||||
end
|
||||
|
||||
|
||||
puts chinese_remainder([3, 5, 7], [2, 3, 2])
|
||||
puts chinese_remainder([5, 7, 9, 11], [1, 2, 3, 4])
|
||||
40
Task/Chinese-remainder-theorem/D/chinese-remainder-theorem.d
Normal file
40
Task/Chinese-remainder-theorem/D/chinese-remainder-theorem.d
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import std.stdio, std.algorithm;
|
||||
|
||||
T chineseRemainder(T)(in T[] n, in T[] a) pure nothrow @safe @nogc
|
||||
in {
|
||||
assert(n.length == a.length);
|
||||
} body {
|
||||
static T mulInv(T)(T a, T b) pure nothrow @safe @nogc {
|
||||
auto b0 = b;
|
||||
T x0 = 0, x1 = 1;
|
||||
if (b == 1)
|
||||
return T(1);
|
||||
while (a > 1) {
|
||||
immutable q = a / b;
|
||||
immutable amb = a % b;
|
||||
a = b;
|
||||
b = amb;
|
||||
immutable xqx = x1 - q * x0;
|
||||
x1 = x0;
|
||||
x0 = xqx;
|
||||
}
|
||||
if (x1 < 0)
|
||||
x1 += b0;
|
||||
return x1;
|
||||
}
|
||||
|
||||
immutable prod = reduce!q{a * b}(T(1), n);
|
||||
|
||||
T p = 1, sm = 0;
|
||||
foreach (immutable i, immutable ni; n) {
|
||||
p = prod / ni;
|
||||
sm += a[i] * mulInv(p, ni) * p;
|
||||
}
|
||||
return sm % prod;
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable n = [3, 5, 7],
|
||||
a = [2, 3, 2];
|
||||
chineseRemainder(n, a).writeln;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
program ChineseRemainderTheorem;
|
||||
|
||||
uses
|
||||
System.SysUtils, Velthuis.BigIntegers;
|
||||
|
||||
function mulInv(a, b: BigInteger): BigInteger;
|
||||
var
|
||||
b0, x0, x1, q, amb, xqx: BigInteger;
|
||||
begin
|
||||
b0 := b;
|
||||
x0 := 0;
|
||||
x1 := 1;
|
||||
|
||||
if (b = 1) then
|
||||
exit(1);
|
||||
|
||||
while (a > 1) do
|
||||
begin
|
||||
q := a div b;
|
||||
amb := a mod b;
|
||||
a := b;
|
||||
b := amb;
|
||||
xqx := x1 - q * x0;
|
||||
x1 := x0;
|
||||
x0 := xqx;
|
||||
end;
|
||||
|
||||
if (x1 < 0) then
|
||||
x1 := x1 + b0;
|
||||
|
||||
Result := x1;
|
||||
end;
|
||||
|
||||
function chineseRemainder(n: TArray<BigInteger>; a: TArray<BigInteger>)
|
||||
: BigInteger;
|
||||
var
|
||||
i: Integer;
|
||||
prod, p, sm: BigInteger;
|
||||
begin
|
||||
prod := 1;
|
||||
|
||||
for i := 0 to High(n) do
|
||||
prod := prod * n[i];
|
||||
|
||||
p := 0;
|
||||
sm := 0;
|
||||
|
||||
for i := 0 to High(n) do
|
||||
begin
|
||||
p := prod div n[i];
|
||||
sm := sm + a[i] * mulInv(p, n[i]) * p;
|
||||
end;
|
||||
Result := sm mod prod;
|
||||
end;
|
||||
|
||||
var
|
||||
n, a: TArray<BigInteger>;
|
||||
|
||||
begin
|
||||
n := [3, 5, 7];
|
||||
a := [2, 3, 2];
|
||||
|
||||
Writeln(chineseRemainder(n, a).ToString);
|
||||
end.
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
proc mul_inv a b . x1 .
|
||||
b0 = b
|
||||
x1 = 1
|
||||
if b <> 1
|
||||
while a > 1
|
||||
q = a div b
|
||||
t = b
|
||||
b = a mod b
|
||||
a = t
|
||||
t = x0
|
||||
x0 = x1 - q * x0
|
||||
x1 = t
|
||||
.
|
||||
if x1 < 0
|
||||
x1 += b0
|
||||
.
|
||||
.
|
||||
.
|
||||
proc remainder . n[] a[] r .
|
||||
prod = 1
|
||||
sum = 0
|
||||
for i = 1 to len n[]
|
||||
prod *= n[i]
|
||||
.
|
||||
for i = 1 to len n[]
|
||||
p = prod / n[i]
|
||||
call mul_inv p n[i] h
|
||||
sum += a[i] * h * p
|
||||
r = sum mod prod
|
||||
.
|
||||
.
|
||||
n[] = [ 3 5 7 ]
|
||||
a[] = [ 2 3 2 ]
|
||||
call remainder n[] a[] h
|
||||
print h
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
(lib 'math)
|
||||
math.lib v1.10 ® EchoLisp
|
||||
Lib: math.lib loaded.
|
||||
|
||||
(crt-solve '(2 3 2) '(3 5 7))
|
||||
→ 23
|
||||
(crt-solve '(2 3 2) '(7 1005 15))
|
||||
💥 error: mod[i] must be co-primes : assertion failed : 1005
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
defmodule Chinese do
|
||||
def remainder(mods, remainders) do
|
||||
max = Enum.reduce(mods, fn x,acc -> x*acc end)
|
||||
Enum.zip(mods, remainders)
|
||||
|> Enum.map(fn {m,r} -> Enum.take_every(r..max, m) |> MapSet.new end)
|
||||
|> Enum.reduce(fn set,acc -> MapSet.intersection(set, acc) end)
|
||||
|> MapSet.to_list
|
||||
end
|
||||
end
|
||||
|
||||
IO.inspect Chinese.remainder([3,5,7], [2,3,2])
|
||||
IO.inspect Chinese.remainder([10,4,9], [11,22,19])
|
||||
IO.inspect Chinese.remainder([11,12,13], [10,4,12])
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
-module(crt).
|
||||
-import(lists, [zip/2, unzip/1, foldl/3, sum/1]).
|
||||
-export([egcd/2, mod/2, mod_inv/2, chinese_remainder/1]).
|
||||
|
||||
egcd(_, 0) -> {1, 0};
|
||||
egcd(A, B) ->
|
||||
{S, T} = egcd(B, A rem B),
|
||||
{T, S - (A div B)*T}.
|
||||
|
||||
mod_inv(A, B) ->
|
||||
{X, Y} = egcd(A, B),
|
||||
if
|
||||
A*X + B*Y =:= 1 -> X;
|
||||
true -> undefined
|
||||
end.
|
||||
|
||||
mod(A, M) ->
|
||||
X = A rem M,
|
||||
if
|
||||
X < 0 -> X + M;
|
||||
true -> X
|
||||
end.
|
||||
|
||||
calc_inverses([], []) -> [];
|
||||
calc_inverses([N | Ns], [M | Ms]) ->
|
||||
case mod_inv(N, M) of
|
||||
undefined -> undefined;
|
||||
Inv -> [Inv | calc_inverses(Ns, Ms)]
|
||||
end.
|
||||
|
||||
chinese_remainder(Congruences) ->
|
||||
{Residues, Modulii} = unzip(Congruences),
|
||||
ModPI = foldl(fun(A, B) -> A*B end, 1, Modulii),
|
||||
CRT_Modulii = [ModPI div M || M <- Modulii],
|
||||
case calc_inverses(CRT_Modulii, Modulii) of
|
||||
undefined -> undefined;
|
||||
Inverses ->
|
||||
Solution = sum([A*B || {A,B} <- zip(CRT_Modulii,
|
||||
[A*B || {A,B} <- zip(Residues, Inverses)])]),
|
||||
mod(Solution, ModPI)
|
||||
end.
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
let rec sieve cs x N =
|
||||
match cs with
|
||||
| [] -> Some(x)
|
||||
| (a,n)::rest ->
|
||||
let arrProgress = Seq.unfold (fun x -> Some(x, x+N)) x
|
||||
let firstXmodNequalA = Seq.tryFind (fun x -> a = x % n)
|
||||
match firstXmodNequalA (Seq.take n arrProgress) with
|
||||
| None -> None
|
||||
| Some(x) -> sieve rest x (N*n)
|
||||
|
||||
[ [(2,3);(3,5);(2,7)];
|
||||
[(10,11); (4,22); (9,19)];
|
||||
[(10,11); (4,12); (12,13)] ]
|
||||
|> List.iter (fun congruences ->
|
||||
let cs =
|
||||
congruences
|
||||
|> List.map (fun (a,n) -> (a % n, n))
|
||||
|> List.sortBy (snd>>(~-))
|
||||
let an = List.head cs
|
||||
match sieve (List.tail cs) (fst an) (snd an) with
|
||||
| None -> printfn "no solution"
|
||||
| Some(x) -> printfn "result = %i" x
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
//Chinese Division Theorem: Nigel Galloway: April 3rd., 2017
|
||||
let CD n g =
|
||||
match Seq.fold(fun n g->if (gcd n g)=1 then n*g else 0) 1 g with
|
||||
|0 -> None
|
||||
|fN-> Some ((Seq.fold2(fun n i g -> n+i*(fN/g)*(MI g ((fN/g)%g))) 0 n g)%fN)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
USING: math.algebra prettyprint ;
|
||||
{ 2 3 2 } { 3 5 7 } chinese-remainder .
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
: egcd ( a b -- a b )
|
||||
dup 0= IF
|
||||
2drop 1 0
|
||||
ELSE
|
||||
dup -rot /mod \ -- b r=a%b q=a/b
|
||||
-rot recurse \ -- q (s,t) = egcd(b, r)
|
||||
>r swap r@ * - r> swap \ -- t (s - q*t)
|
||||
THEN ;
|
||||
|
||||
: egcd>gcd ( a b x y -- n ) \ calculate gcd from egcd
|
||||
rot * -rot * + ;
|
||||
|
||||
: mod-inv ( a m -- a' ) \ modular inverse with coprime check
|
||||
2dup egcd over >r egcd>gcd r> swap 1 <> -24 and throw ;
|
||||
|
||||
: array-product ( adr count -- n )
|
||||
1 -rot cells bounds ?DO i @ * cell +LOOP ;
|
||||
|
||||
: crt-from-array ( adr1 adr2 count -- n )
|
||||
2dup array-product locals| M count m[] a[] |
|
||||
0 \ result
|
||||
count 0 DO
|
||||
m[] i cells + @
|
||||
dup M swap /
|
||||
dup rot mod-inv *
|
||||
a[] i cells + @ * +
|
||||
LOOP M mod ;
|
||||
|
||||
create crt-residues[] 10 cells allot
|
||||
create crt-moduli[] 10 cells allot
|
||||
|
||||
: crt ( .... n -- n ) \ takes pairs of "n (mod m)" from stack.
|
||||
10 min locals| n |
|
||||
n 0 DO
|
||||
crt-moduli[] i cells + !
|
||||
crt-residues[] i cells + !
|
||||
LOOP
|
||||
crt-residues[] crt-moduli[] n crt-from-array ;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
* RC task: use the Chinese Remainder Theorem to solve a system of congruences.
|
||||
|
||||
FUNCTION crt(n, residues, moduli)
|
||||
IMPLICIT INTEGER (A-Z)
|
||||
DIMENSION residues(n), moduli(n)
|
||||
|
||||
p = product(moduli)
|
||||
crt = 0
|
||||
DO 10 i = 1, n
|
||||
m = p/moduli(i)
|
||||
CALL egcd(moduli(i), m, r, s, gcd)
|
||||
IF (gcd .ne. 1) GO TO 20 ! error exit
|
||||
10 crt = crt + residues(i)*s*m
|
||||
crt = modulo(crt, p)
|
||||
RETURN
|
||||
|
||||
20 crt = -1 ! will never be negative, so flag an error
|
||||
END
|
||||
|
||||
|
||||
* Compute egcd(a, b), returning x, y, g s.t.
|
||||
* g = gcd(a, b) and a*x + b*y = g
|
||||
*
|
||||
SUBROUTINE egcd(a, b, x, y, g)
|
||||
IMPLICIT INTEGER (A-Z)
|
||||
|
||||
g = a
|
||||
u = 0
|
||||
v = 1
|
||||
w = b
|
||||
x = 1
|
||||
y = 0
|
||||
|
||||
1 IF (w .eq. 0) RETURN
|
||||
q = g/w
|
||||
u next = x - q*u
|
||||
v next = y - q*v
|
||||
w next = g - q*w
|
||||
x = u
|
||||
y = v
|
||||
g = w
|
||||
u = u next
|
||||
v = v next
|
||||
w = w next
|
||||
GO TO 1
|
||||
END
|
||||
|
||||
|
||||
PROGRAM Chinese Remainder
|
||||
IMPLICIT INTEGER (A-Z)
|
||||
|
||||
PRINT *, crt(3, [2, 3, 2], [3, 5, 7])
|
||||
PRINT *, crt(3, [2, 3, 2], [3, 6, 7]) ! no solution
|
||||
|
||||
END
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include "gcd.bas"
|
||||
function mul_inv( a as integer, b as integer ) as integer
|
||||
if b = 1 then return 1
|
||||
for i as integer = 1 to b
|
||||
if a*i mod b = 1 then return i
|
||||
next i
|
||||
return 0
|
||||
end function
|
||||
|
||||
function chinese_remainder(n() as integer, a() as integer) as integer
|
||||
dim as integer p, i, prod = 1, sum = 0, ln = ubound(n)
|
||||
for p = 0 to ln-1
|
||||
for i = p+1 to ln
|
||||
if gcd(n(i), n(p))>1 then
|
||||
print "N not coprime"
|
||||
end
|
||||
end if
|
||||
next i
|
||||
next p
|
||||
for i = 0 to ln
|
||||
prod *= n(i)
|
||||
next i
|
||||
for i = 0 to ln
|
||||
p = prod/n(i)
|
||||
sum += a(i) * mul_inv(p, n(i))*p
|
||||
next i
|
||||
return sum mod prod
|
||||
end function
|
||||
|
||||
dim as integer n(0 to 2) = { 3, 5, 7 }
|
||||
dim as integer a(0 to 2) = { 2, 3, 2 }
|
||||
|
||||
print chinese_remainder(n(), a())
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/** arguments:
|
||||
[r, m, d=0] where r and m are arrays of the remainder terms r and the
|
||||
modulus terms m respectively. These must be of the same length.
|
||||
returns
|
||||
x, the unique solution mod N where N is the product of all the M terms where x >= d.
|
||||
*/
|
||||
ChineseRemainder[r, m, d=0] :=
|
||||
{
|
||||
if length[r] != length[m]
|
||||
{
|
||||
println["ChineseRemainder: r and m must be arrays of the same length."]
|
||||
return undef
|
||||
}
|
||||
|
||||
N = product[m]
|
||||
|
||||
y = new array
|
||||
z = new array
|
||||
x = 0
|
||||
for i = rangeOf[m]
|
||||
{
|
||||
y@i = N / m@i
|
||||
z@i = modInverse[y@i, m@i]
|
||||
if z@i == undef
|
||||
{
|
||||
println["ChineseRemainder: modInverse returned undef for modInverse[" + y@i + ", " + m@i + "]"]
|
||||
return undef
|
||||
}
|
||||
|
||||
x = x + r@i y@i z@i
|
||||
}
|
||||
|
||||
xp = x mod N
|
||||
f = d div N
|
||||
r = f * N + xp
|
||||
if r < d
|
||||
r = r + N
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
println[ChineseRemainder[[2,3,2],[3,5,7]] ]
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import integers.modinv
|
||||
|
||||
def crt( congruences ) =
|
||||
N = product( n | (_, n) <- congruences )
|
||||
sum( a*modinv(N/n, n)*N/n | (a, n) <- congruences ) mod N
|
||||
|
||||
println( crt([(2, 3), (3, 5), (2, 7)]) )
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var one = big.NewInt(1)
|
||||
|
||||
func crt(a, n []*big.Int) (*big.Int, error) {
|
||||
p := new(big.Int).Set(n[0])
|
||||
for _, n1 := range n[1:] {
|
||||
p.Mul(p, n1)
|
||||
}
|
||||
var x, q, s, z big.Int
|
||||
for i, n1 := range n {
|
||||
q.Div(p, n1)
|
||||
z.GCD(nil, &s, n1, &q)
|
||||
if z.Cmp(one) != 0 {
|
||||
return nil, fmt.Errorf("%d not coprime", n1)
|
||||
}
|
||||
x.Add(&x, s.Mul(a[i], s.Mul(&s, &q)))
|
||||
}
|
||||
return x.Mod(&x, p), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
n := []*big.Int{
|
||||
big.NewInt(3),
|
||||
big.NewInt(5),
|
||||
big.NewInt(7),
|
||||
}
|
||||
a := []*big.Int{
|
||||
big.NewInt(2),
|
||||
big.NewInt(3),
|
||||
big.NewInt(2),
|
||||
}
|
||||
fmt.Println(crt(a, n))
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
class ChineseRemainderTheorem {
|
||||
static int chineseRemainder(int[] n, int[] a) {
|
||||
int prod = 1
|
||||
for (int i = 0; i < n.length; i++) {
|
||||
prod *= n[i]
|
||||
}
|
||||
|
||||
int p, sm = 0
|
||||
for (int i = 0; i < n.length; i++) {
|
||||
p = prod.intdiv(n[i])
|
||||
sm += a[i] * mulInv(p, n[i]) * p
|
||||
}
|
||||
return sm % prod
|
||||
}
|
||||
|
||||
private static int mulInv(int a, int b) {
|
||||
int b0 = b
|
||||
int x0 = 0
|
||||
int x1 = 1
|
||||
|
||||
if (b == 1) {
|
||||
return 1
|
||||
}
|
||||
|
||||
while (a > 1) {
|
||||
int q = a.intdiv(b)
|
||||
int amb = a % b
|
||||
a = b
|
||||
b = amb
|
||||
int xqx = x1 - q * x0
|
||||
x1 = x0
|
||||
x0 = xqx
|
||||
}
|
||||
|
||||
if (x1 < 0) {
|
||||
x1 += b0
|
||||
}
|
||||
|
||||
return x1
|
||||
}
|
||||
|
||||
static void main(String[] args) {
|
||||
int[] n = [3, 5, 7]
|
||||
int[] a = [2, 3, 2]
|
||||
println(chineseRemainder(n, a))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import Control.Monad (zipWithM)
|
||||
|
||||
egcd :: Int -> Int -> (Int, Int)
|
||||
egcd _ 0 = (1, 0)
|
||||
egcd a b = (t, s - q * t)
|
||||
where
|
||||
(s, t) = egcd b r
|
||||
(q, r) = a `quotRem` b
|
||||
|
||||
modInv :: Int -> Int -> Either String Int
|
||||
modInv a b =
|
||||
case egcd a b of
|
||||
(x, y)
|
||||
| a * x + b * y == 1 -> Right x
|
||||
| otherwise ->
|
||||
Left $ "No modular inverse for " ++ show a ++ " and " ++ show b
|
||||
|
||||
chineseRemainder :: [Int] -> [Int] -> Either String Int
|
||||
chineseRemainder residues modulii =
|
||||
zipWithM modInv crtModulii modulii >>=
|
||||
(Right . (`mod` modPI) . sum . zipWith (*) crtModulii . zipWith (*) residues)
|
||||
where
|
||||
modPI = product modulii
|
||||
crtModulii = (modPI `div`) <$> modulii
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
mapM_ (putStrLn . either id show) $
|
||||
uncurry chineseRemainder <$>
|
||||
[ ([10, 4, 12], [11, 12, 13])
|
||||
, ([10, 4, 9], [11, 22, 19])
|
||||
, ([2, 3, 2], [3, 5, 7])
|
||||
]
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
link numbers # for gcd()
|
||||
|
||||
procedure main()
|
||||
write(cr([3,5,7],[2,3,2]) | "No solution!")
|
||||
write(cr([10,4,9],[11,22,19]) | "No solution!")
|
||||
end
|
||||
|
||||
procedure cr(n,a)
|
||||
if 1 ~= gcd(n[i := !*n],a[i]) then fail # Not pairwise coprime
|
||||
(prod := 1, sm := 0)
|
||||
every prod *:= !n
|
||||
every p := prod/(ni := n[i := !*n]) do sm +:= a[i] * mul_inv(p,ni) * p
|
||||
return sm%prod
|
||||
end
|
||||
|
||||
procedure mul_inv(a,b)
|
||||
if b = 1 then return 1
|
||||
(b0 := b, x0 := 0, x1 := 1)
|
||||
while q := (1 < a)/b do {
|
||||
(t := a, a := b, b := t%b)
|
||||
(t := x0, x0 := x1-q*t, x1 := t)
|
||||
}
|
||||
return if x1 < 0 then x1+b0 else x1
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
crt =: (1 + ] - {:@:[ -: {.@:[ | ])^:_&0@:,:
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
3 5 7 crt 2 3 2
|
||||
23
|
||||
11 12 13 crt 10 4 12
|
||||
1000
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import static java.util.Arrays.stream;
|
||||
|
||||
public class ChineseRemainderTheorem {
|
||||
|
||||
public static int chineseRemainder(int[] n, int[] a) {
|
||||
|
||||
int prod = stream(n).reduce(1, (i, j) -> i * j);
|
||||
|
||||
int p, sm = 0;
|
||||
for (int i = 0; i < n.length; i++) {
|
||||
p = prod / n[i];
|
||||
sm += a[i] * mulInv(p, n[i]) * p;
|
||||
}
|
||||
return sm % prod;
|
||||
}
|
||||
|
||||
private static int mulInv(int a, int b) {
|
||||
int b0 = b;
|
||||
int x0 = 0;
|
||||
int x1 = 1;
|
||||
|
||||
if (b == 1)
|
||||
return 1;
|
||||
|
||||
while (a > 1) {
|
||||
int q = a / b;
|
||||
int amb = a % b;
|
||||
a = b;
|
||||
b = amb;
|
||||
int xqx = x1 - q * x0;
|
||||
x1 = x0;
|
||||
x0 = xqx;
|
||||
}
|
||||
|
||||
if (x1 < 0)
|
||||
x1 += b0;
|
||||
|
||||
return x1;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] n = {3, 5, 7};
|
||||
int[] a = {2, 3, 2};
|
||||
System.out.println(chineseRemainder(n, a));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
function crt(num, rem) {
|
||||
let sum = 0;
|
||||
const prod = num.reduce((a, c) => a * c, 1);
|
||||
|
||||
for (let i = 0; i < num.length; i++) {
|
||||
const [ni, ri] = [num[i], rem[i]];
|
||||
const p = Math.floor(prod / ni);
|
||||
sum += ri * p * mulInv(p, ni);
|
||||
}
|
||||
return sum % prod;
|
||||
}
|
||||
|
||||
function mulInv(a, b) {
|
||||
const b0 = b;
|
||||
let [x0, x1] = [0, 1];
|
||||
|
||||
if (b === 1) {
|
||||
return 1;
|
||||
}
|
||||
while (a > 1) {
|
||||
const q = Math.floor(a / b);
|
||||
[a, b] = [b, a % b];
|
||||
[x0, x1] = [x1 - q * x0, x0];
|
||||
}
|
||||
if (x1 < 0) {
|
||||
x1 += b0;
|
||||
}
|
||||
return x1;
|
||||
}
|
||||
|
||||
console.log(crt([3,5,7], [2,3,2]))
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# mul_inv(a;b) returns x where (a * x) % b == 1, or else null
|
||||
def mul_inv(a; b):
|
||||
|
||||
# state: [a, b, x0, x1]
|
||||
def iterate:
|
||||
.[0] as $a | .[1] as $b
|
||||
| if $a > 1 then
|
||||
if $b == 0 then null
|
||||
else ($a / $b | floor) as $q
|
||||
| [$b, ($a % $b), (.[3] - ($q * .[2])), .[2]] | iterate
|
||||
end
|
||||
else .
|
||||
end ;
|
||||
|
||||
if (b == 1) then 1
|
||||
else [a,b,0,1] | iterate
|
||||
| if . == null then .
|
||||
else .[3] | if . < 0 then . + b else . end
|
||||
end
|
||||
end;
|
||||
|
||||
def chinese_remainder(mods; remainders):
|
||||
(reduce mods[] as $i (1; . * $i)) as $prod
|
||||
| reduce range(0; mods|length) as $i
|
||||
(0;
|
||||
($prod/mods[$i]) as $p
|
||||
| mul_inv($p; mods[$i]) as $mi
|
||||
| if $mi == null then error("nogo: p=\($p) mods[\($i)]=\(mods[$i])")
|
||||
else . + (remainders[$i] * $mi * $p)
|
||||
end )
|
||||
| . % $prod ;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
function chineseremainder(n::Array, a::Array)
|
||||
Π = prod(n)
|
||||
mod(sum(ai * invmod(Π ÷ ni, ni) * (Π ÷ ni) for (ni, ai) in zip(n, a)), Π)
|
||||
end
|
||||
|
||||
@show chineseremainder([3, 5, 7], [2, 3, 2])
|
||||
|
|
@ -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,41 @@
|
|||
import std
|
||||
|
||||
def extended_gcd(a, b):
|
||||
var s = 0
|
||||
var old_s = 1
|
||||
var t = 1
|
||||
var old_t = 0
|
||||
var r = b
|
||||
var old_r = a
|
||||
|
||||
while r != 0:
|
||||
let quotient = old_r / r
|
||||
old_r, r = r, old_r - quotient * r
|
||||
old_s, s = s, old_s - quotient * s
|
||||
old_t, t = t, old_t - quotient * t
|
||||
|
||||
return old_r, old_s, old_t, t, s
|
||||
|
||||
def for2(xs, ys, fun): return for xs.length: fun(xs[_], ys[_])
|
||||
|
||||
def crt(xs, ys):
|
||||
let p = reduce(xs): _a * _b
|
||||
var r = 0
|
||||
for2(xs,ys) x, y:
|
||||
let q = p / x
|
||||
let z,s,_t,_qt,_qs = q.extended_gcd(x)
|
||||
if z != 1:
|
||||
return "ng " + x + " not coprime", 0
|
||||
if s < 0: r += y * (s + x) * q
|
||||
else: r += y * s * q
|
||||
return "ok", r % p
|
||||
|
||||
|
||||
def print_crt(xs, ys):
|
||||
let msg, res = crt(xs, ys)
|
||||
print(msg + " " + res)
|
||||
|
||||
print_crt([3,5,7],[2,3,2])
|
||||
print_crt([11,12,13],[10,4,12])
|
||||
print_crt([11,22,19],[10,4,9])
|
||||
print_crt([100,23],[19,0])
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
-- Taken from https://www.rosettacode.org/wiki/Sum_and_product_of_an_array#Lua
|
||||
function prodf(a, ...) return a and a * prodf(...) or 1 end
|
||||
function prodt(t) return prodf(unpack(t)) end
|
||||
|
||||
function mulInv(a, b)
|
||||
local b0 = b
|
||||
local x0 = 0
|
||||
local x1 = 1
|
||||
|
||||
if b == 1 then
|
||||
return 1
|
||||
end
|
||||
|
||||
while a > 1 do
|
||||
local q = math.floor(a / b)
|
||||
local amb = math.fmod(a, b)
|
||||
a = b
|
||||
b = amb
|
||||
local xqx = x1 - q * x0
|
||||
x1 = x0
|
||||
x0 = xqx
|
||||
end
|
||||
|
||||
if x1 < 0 then
|
||||
x1 = x1 + b0
|
||||
end
|
||||
|
||||
return x1
|
||||
end
|
||||
|
||||
function chineseRemainder(n, a)
|
||||
local prod = prodt(n)
|
||||
|
||||
local p
|
||||
local sm = 0
|
||||
for i=1,#n do
|
||||
p = prod / n[i]
|
||||
sm = sm + a[i] * mulInv(p, n[i]) * p
|
||||
end
|
||||
|
||||
return math.fmod(sm, prod)
|
||||
end
|
||||
|
||||
n = {3, 5, 7}
|
||||
a = {2, 3, 2}
|
||||
io.write(chineseRemainder(n, a))
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
Function ChineseRemainder(n(), a()) {
|
||||
Function mul_inv(a, b) {
|
||||
if b==1 then =1 : exit
|
||||
b0=b
|
||||
x1=1 : x0=0
|
||||
while a>1
|
||||
q=a div b
|
||||
t=b : b=a mod b: a=t
|
||||
t=x0: x0=x1-q*x0:x1=t
|
||||
end while
|
||||
if x1<0 then x1+=b0
|
||||
=x1
|
||||
}
|
||||
def p, i, prod=1, sum
|
||||
for i=0 to len(n())-1 {prod*=n(i)}
|
||||
for i=0 to len(a())-1
|
||||
p=prod div n(i)
|
||||
sum+=a(i)*mul_inv(p, n(i))*p
|
||||
next
|
||||
=sum mod prod
|
||||
}
|
||||
Print ChineseRemainder((3,5,7), (2,3,2))
|
||||
|
|
@ -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,2 @@
|
|||
> chrem( [2, 3, 2], [3, 5, 7] );
|
||||
23
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ChineseRemainder[{2, 3, 2}, {3, 5, 7}]
|
||||
23
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
MODULE CRT;
|
||||
FROM FormatString IMPORT FormatString;
|
||||
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
|
||||
|
||||
PROCEDURE WriteInt(n : INTEGER);
|
||||
VAR buf : ARRAY[0..15] OF CHAR;
|
||||
BEGIN
|
||||
FormatString("%i", buf, n);
|
||||
WriteString(buf)
|
||||
END WriteInt;
|
||||
|
||||
PROCEDURE MulInv(a,b : INTEGER) : INTEGER;
|
||||
VAR
|
||||
b0,x0,x1,q,amb,xqx : INTEGER;
|
||||
BEGIN
|
||||
b0 := b;
|
||||
x0 := 0;
|
||||
x1 := 1;
|
||||
|
||||
IF b=1 THEN
|
||||
RETURN 1
|
||||
END;
|
||||
|
||||
WHILE a>1 DO
|
||||
q := a DIV b;
|
||||
amb := a MOD b;
|
||||
a := b;
|
||||
b := amb;
|
||||
xqx := x1 - q * x0;
|
||||
x1 := x0;
|
||||
x0 := xqx
|
||||
END;
|
||||
|
||||
IF x1<0 THEN
|
||||
x1 := x1 + b0
|
||||
END;
|
||||
|
||||
RETURN x1
|
||||
END MulInv;
|
||||
|
||||
PROCEDURE ChineseRemainder(n,a : ARRAY OF INTEGER) : INTEGER;
|
||||
VAR
|
||||
i : CARDINAL;
|
||||
prod,p,sm : INTEGER;
|
||||
BEGIN
|
||||
prod := n[0];
|
||||
FOR i:=1 TO HIGH(n) DO
|
||||
prod := prod * n[i]
|
||||
END;
|
||||
|
||||
sm := 0;
|
||||
FOR i:=0 TO HIGH(n) DO
|
||||
p := prod DIV n[i];
|
||||
sm := sm + a[i] * MulInv(p, n[i]) * p
|
||||
END;
|
||||
|
||||
RETURN sm MOD prod
|
||||
END ChineseRemainder;
|
||||
|
||||
TYPE TA = ARRAY[0..2] OF INTEGER;
|
||||
VAR n,a : TA;
|
||||
BEGIN
|
||||
n := TA{3, 5, 7};
|
||||
a := TA{2, 3, 2};
|
||||
WriteInt(ChineseRemainder(n, a));
|
||||
WriteLn;
|
||||
|
||||
ReadChar
|
||||
END CRT.
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
proc mulInv(a0, b0: int): int =
|
||||
var (a, b, x0) = (a0, b0, 0)
|
||||
result = 1
|
||||
if b == 1: return
|
||||
while a > 1:
|
||||
let q = a div b
|
||||
a = a mod b
|
||||
swap a, b
|
||||
result = result - q * x0
|
||||
swap x0, result
|
||||
if result < 0: result += b0
|
||||
|
||||
proc chineseRemainder[T](n, a: T): int =
|
||||
var prod = 1
|
||||
var sum = 0
|
||||
for x in n: prod *= x
|
||||
|
||||
for i in 0..<n.len:
|
||||
let p = prod div n[i]
|
||||
sum += a[i] * mulInv(p, n[i]) * p
|
||||
|
||||
sum mod prod
|
||||
|
||||
echo chineseRemainder([3,5,7], [2,3,2])
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
exception Modular_inverse
|
||||
let inverse_mod a = function
|
||||
| 1 -> 1
|
||||
| b -> let rec inner a b x0 x1 =
|
||||
if a <= 1 then x1
|
||||
else if b = 0 then raise Modular_inverse
|
||||
else inner b (a mod b) (x1 - (a / b) * x0) x0 in
|
||||
let x = inner a b 0 1 in
|
||||
if x < 0 then x + b else x
|
||||
|
||||
let chinese_remainder_exn congruences =
|
||||
let mtot = congruences
|
||||
|> List.map (fun (_, x) -> x)
|
||||
|> List.fold_left ( *) 1 in
|
||||
(List.fold_left (fun acc (r, n) ->
|
||||
acc + r * inverse_mod (mtot / n) n * (mtot / n)
|
||||
) 0 congruences)
|
||||
mod mtot
|
||||
|
||||
let chinese_remainder congruences =
|
||||
try Some (chinese_remainder_exn congruences)
|
||||
with modular_inverse -> None
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
open Core.Std
|
||||
open Option.Monad_infix
|
||||
|
||||
let rec egcd a b =
|
||||
if b = 0 then (1, 0)
|
||||
else
|
||||
let q = a/b and r = a mod b in
|
||||
let (s, t) = egcd b r in
|
||||
(t, s - q*t)
|
||||
|
||||
|
||||
let mod_inv a b =
|
||||
let (x, y) = egcd a b in
|
||||
if a*x + b*y = 1 then Some x else None
|
||||
|
||||
|
||||
let calc_inverses ns ms =
|
||||
let rec list_inverses ns ms l =
|
||||
match (ns, ms) with
|
||||
| ([], []) -> Some l
|
||||
| ([], _)
|
||||
| (_, []) -> assert false
|
||||
| (n::ns, m::ms) ->
|
||||
let inv = mod_inv n m in
|
||||
match inv with
|
||||
| None -> None
|
||||
| Some v -> list_inverses ns ms (v::l)
|
||||
in
|
||||
list_inverses ns ms [] >>= fun l -> Some (List.rev l)
|
||||
|
||||
|
||||
let chinese_remainder congruences =
|
||||
let (residues, modulii) = List.unzip congruences in
|
||||
let mod_pi = List.reduce_exn modulii ~f:( * ) in
|
||||
let crt_modulii = List.map modulii ~f:(fun m -> mod_pi / m) in
|
||||
calc_inverses crt_modulii modulii >>=
|
||||
fun inverses ->
|
||||
Some (List.map3_exn residues inverses crt_modulii ~f:(fun a b c -> a*b*c)
|
||||
|> List.reduce_exn ~f:(+)
|
||||
|> fun n -> let n' = n mod mod_pi in if n' < 0 then n' + mod_pi else n')
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
chivec(residues, moduli)={
|
||||
my(m=Mod(0,1));
|
||||
for(i=1,#residues,
|
||||
m=chinese(Mod(residues[i],moduli[i]),m)
|
||||
);
|
||||
lift(m)
|
||||
};
|
||||
chivec([2,3,2], [3,5,7])
|
||||
|
|
@ -0,0 +1 @@
|
|||
lift( chinese([Mod(2,3),Mod(3,5),Mod(2,7)]) )
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
chivec(residues,moduli)={
|
||||
lift(chinese(vector(#residues,i,Mod(residues[i],moduli[i]))))
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Rosetta Code task "Chinese remainder theorem".
|
||||
program ChineseRemThm;
|
||||
uses SysUtils;
|
||||
type TIntArray = array of integer;
|
||||
|
||||
// Defining EXTRA adds optional explanatory code
|
||||
{$DEFINE EXTRA}
|
||||
|
||||
// Return (if possible) a residue res_out that satifies
|
||||
// res_out = res1 modulo mod1, res_out = res2 modulo mod2.
|
||||
// Return mod_out = LCM( mod1, mod2), or mod_out = 0 if there's no solution.
|
||||
procedure Solve2( const res1, res2, mod1, mod2 : integer;
|
||||
out res_out, mod_out : integer);
|
||||
var
|
||||
a, c, d, k, m, m1, m2, r, temp : integer;
|
||||
p, p_prev : integer;
|
||||
{$IFDEF EXTRA}
|
||||
q, q_prev : integer;
|
||||
{$ENDIF}
|
||||
begin
|
||||
if (mod1 = 0) or (mod2 = 0) then
|
||||
raise SysUtils.Exception.Create( 'Solve2: Modulus cannot be 0');
|
||||
m1 := Abs( mod1);
|
||||
m2 := Abs( mod2);
|
||||
// Extended Euclid's algorithm for HCF( m1, m2), except that only one
|
||||
// of the Bezout coefficients is needed (here p, could have used q)
|
||||
c := m1; d := m2;
|
||||
p :=0; p_prev := 1;
|
||||
{$IFDEF EXTRA}
|
||||
q := 1; q_prev := 0;
|
||||
{$ENDIF}
|
||||
a := 0;
|
||||
while (d > 0) do begin
|
||||
temp := p_prev - a*p; p_prev := p; p := temp;
|
||||
{$IFDEF EXTRA}
|
||||
temp := q_prev - a*q; q_prev := q; q := temp;
|
||||
{$ENDIF}
|
||||
a := c div d;
|
||||
temp := c - a*d; c := d; d := temp;
|
||||
end;
|
||||
// Here with c = HCF( m1, m2)
|
||||
{$IFDEF EXTRA}
|
||||
Assert( c = p*m2 + q*m1); // p and q are the Bezout coefficients
|
||||
{$ENDIF}
|
||||
// A soution exists iff c divides (res2 - res1)
|
||||
k := (res2 - res1) div c;
|
||||
if res2 - res1 <> k*c then begin
|
||||
res_out := 0; mod_out := 0; // indicate that there's no xolution
|
||||
end
|
||||
else begin
|
||||
m := (m1 div c) * m2; // m := LCM( m1, m2)
|
||||
r:= res2 - k*p*m2; // r := a solution modulo m
|
||||
{$IFDEF EXTRA}
|
||||
Assert( r = res1 + k*q*m1); // alternative formula in terms of q
|
||||
{$ENDIF}
|
||||
// Return the solution in the range 0..(m - 1)
|
||||
// Don't trust the compiler with a negative argument to mod
|
||||
if (r >= 0) then r := r mod m
|
||||
else begin
|
||||
r := (-r) mod m;
|
||||
if (r > 0) then r := m - r;
|
||||
end;
|
||||
res_out := r; mod_out := m;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Return (if possible) a residue res_out that satifies
|
||||
// res_out = res_array[j] modulo mod_array[j], for j = 0..High(res_array).
|
||||
// Return mod_out = LCM of the moduli, or mod_out = 0 if there's no solution.
|
||||
procedure SolveMulti( const res_array, mod_array : TIntArray;
|
||||
out res_out, mod_out : integer);
|
||||
var
|
||||
count, k, m, r : integer;
|
||||
begin
|
||||
count := Length( mod_array);
|
||||
if count <> Length( res_array) then
|
||||
raise SysUtils.Exception.Create( 'Arrays are different sizes')
|
||||
else if count = 0 then
|
||||
raise SysUtils.Exception.Create( 'Arrays are empty');
|
||||
k := 1;
|
||||
m := mod_array[0]; r := res_array[0];
|
||||
while (k < count) and (m > 0) do begin
|
||||
Solve2( r, res_array[k], m, mod_array[k], r, m);
|
||||
inc(k);
|
||||
end;
|
||||
res_out := r; mod_out := m;
|
||||
end;
|
||||
|
||||
// Cosmetic to turn an integer array into a string for printout.
|
||||
function ArrayToString( a : TIntArray) : string;
|
||||
var
|
||||
j : integer;
|
||||
begin
|
||||
result := '[';
|
||||
for j := 0 to High(a) do begin
|
||||
result := result + SysUtils.IntToStr(a[j]);
|
||||
if j < High(a) then result := result + ', '
|
||||
else result := result + ']';
|
||||
end;
|
||||
end;
|
||||
|
||||
// For the passed-in res_array and mod_array, show the solution
|
||||
// found by SolveMulti (above), or state that there's no solution.
|
||||
procedure ShowSolution( const res_array, mod_array : TIntArray);
|
||||
var
|
||||
mod_out, res_out : integer;
|
||||
begin
|
||||
SolveMulti( res_array, mod_array, res_out, mod_out);
|
||||
Write( ArrayToString( res_array) + ' mod '
|
||||
+ ArrayToString( mod_array) + ' --> ');
|
||||
if mod_out = 0 then
|
||||
WriteLn( 'No solution')
|
||||
else
|
||||
WriteLn( SysUtils.Format( '%d mod %d', [res_out, mod_out]));
|
||||
end;
|
||||
|
||||
// Main routine. Examples for Rosetta Code task.
|
||||
begin
|
||||
ShowSolution([2, 3, 2], [3, 5, 7]);
|
||||
ShowSolution([3, 5, 7], [2, 3, 2]);
|
||||
ShowSolution([10, 4, 12], [11, 12, 13]);
|
||||
ShowSolution([1, 2, 3, 4], [5, 7, 9, 11]);
|
||||
ShowSolution([11, 22, 19], [10, 4, 9]);
|
||||
ShowSolution([2328, 410], [16256, 5418]);
|
||||
ShowSolution([19, 0], [100, 23]);
|
||||
end.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
use ntheory qw/chinese/;
|
||||
say chinese([2,3], [3,5], [2,7]);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
use Math::ModInt qw(mod);
|
||||
use Math::ModInt::ChineseRemainder qw(cr_combine);
|
||||
say cr_combine(mod(2,3),mod(3,5),mod(2,7));
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
use ntheory qw/chinese lcm/;
|
||||
say chinese( [2328,16256], [410,5418] ), " mod ", lcm(16256,5418);
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">mul_inv</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">n</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">-</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">;</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">nr</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">/</span><span style="color: #000000;">nr</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nt</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">nt</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">-</span><span style="color: #000000;">q</span><span style="color: #0000FF;">*</span><span style="color: #000000;">nt</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nr</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">nr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">-</span><span style="color: #000000;">q</span><span style="color: #0000FF;">*</span><span style="color: #000000;">nr</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"a is not invertible"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">t</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">n</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">t</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">chinese_remainder</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">prod</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tot</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">;</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000000;">prod</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prod</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">];</span>
|
||||
<span style="color: #004080;">object</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mul_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"fail"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">;</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span><span style="color: #000000;">prod</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">chinese_remainder</span><span style="color: #0000FF;">({</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">chinese_remainder</span><span style="color: #0000FF;">({</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">chinese_remainder</span><span style="color: #0000FF;">({</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">22</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">chinese_remainder</span><span style="color: #0000FF;">({</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,</span><span style="color: #000000;">23</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">})</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
(de modinv (A B)
|
||||
(let (B0 B X0 0 X1 1 Q 0 T1 0)
|
||||
(while (< 1 A)
|
||||
(setq
|
||||
Q (/ A B)
|
||||
T1 B
|
||||
B (% A B)
|
||||
A T1
|
||||
T1 X0
|
||||
X0 (- X1 (* Q X0))
|
||||
X1 T1 ) )
|
||||
(if (lt0 X1) (+ X1 B0) X1) ) )
|
||||
|
||||
(de chinrem (N A)
|
||||
(let P (apply * N)
|
||||
(%
|
||||
(sum
|
||||
'((N A)
|
||||
(setq T1 (/ P N))
|
||||
(* A (modinv T1 N) T1) )
|
||||
N
|
||||
A )
|
||||
P ) ) )
|
||||
|
||||
(println
|
||||
(chinrem (3 5 7) (2 3 2))
|
||||
(chinrem (11 12 13) (10 4 12)) )
|
||||
|
||||
(bye)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
product(A, B, C) :- C is A*B.
|
||||
|
||||
pair(X, Y, X-Y).
|
||||
|
||||
egcd(_, 0, 1, 0) :- !.
|
||||
egcd(A, B, X, Y) :-
|
||||
divmod(A, B, Q, R),
|
||||
egcd(B, R, S, X),
|
||||
Y is S - Q*X.
|
||||
|
||||
modinv(A, B, X) :-
|
||||
egcd(A, B, X, Y),
|
||||
A*X + B*Y =:= 1.
|
||||
|
||||
crt_fold(A, M, P, R0, R1) :- % system of equations of (x = a) (mod m); p = M/m
|
||||
modinv(P, M, Inv),
|
||||
R1 is R0 + A*Inv*P.
|
||||
|
||||
crt(Pairs, N) :-
|
||||
maplist(pair, As, Ms, Pairs),
|
||||
foldl(product, Ms, 1, M),
|
||||
maplist(divmod(M), Ms, Ps, _), % p(n) <- M/m(n)
|
||||
foldl(crt_fold, As, Ms, Ps, 0, N0),
|
||||
N is N0 mod M.
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* Chinese remainder Theorem: Input chinrest([2,3,2], [3,5,7], R). -----> R == 23
|
||||
or chinrest([2,3], [5,13], R). ---------> R == 42
|
||||
Written along the lines of "Introduction to Algorithms" by
|
||||
Thomas Cormen
|
||||
Charles Leiserson
|
||||
Ronald Rivest
|
||||
compiled with gprolog 1.4.5 (64 Bits)
|
||||
*/
|
||||
|
||||
chinrest(A, N, X) :-
|
||||
sort(N),
|
||||
prime(N,Nn), !, lenok(A, Nn), /* test as to whether the ni are primes */
|
||||
product(Nn,P), !, /* P is the product of the ni */
|
||||
milist(P, Nn, Mi), /* The Mi List: mi = n/ni */
|
||||
cilist(Mi, Nn, Ci), /* The first Ci List: mi-1 mod ni */
|
||||
mult_lists(Mi, Ci, Ac), /* The ci List :mi*(mi-1 mod ni) */
|
||||
mult_lists(Ac, A, Ad), /* The ai*ci List */
|
||||
sum_list(Ad, S), /* Sum of the ai*cis */
|
||||
X is S mod P, ! . /* a is (a1c1 + ... +akck) mod n */
|
||||
|
||||
prime([X|Ys], Zs) :- fd_not_prime(X), !, prime(Ys,Zs). /* sift the primes of [list] */
|
||||
prime([Y|Ys], [Y|Zs]) :- fd_prime(Y), !, prime(Ys,Zs).
|
||||
prime([],[]).
|
||||
|
||||
product([], 0). /* n1.n2.n3. ... .ni. ... .nk */
|
||||
product([H|T], P) :- product_1(T, H, P).
|
||||
|
||||
product_1([], P, P).
|
||||
product_1([H|T], H0, P) :- product_1(T, H, P0), P is P0 * H0.
|
||||
|
||||
lenok(A, N) :- length(A, X), length(N, Y), X=:=Y.
|
||||
lenok(_, _) :- write('Please enter equal length prime numbers only'), fail.
|
||||
|
||||
cilist(Mi, Ni, Ci) :- maplist( (modinv), Mi, Ni, Ci). /* generate the Cis */
|
||||
|
||||
mult_lists(Ai, Ci, Ac) :- maplist( (pro), Ai, Ci, Ac). /* The mi*ci */
|
||||
pro(X, Y, Z) :- Z is X * Y.
|
||||
|
||||
milist(_, [],[]).
|
||||
milist(P, [H|T],[X|Y]) :- X is truncate(P/H), milist(P, T, Y).
|
||||
|
||||
modinv(A, B, N) :- eeuclid(A, B, P, _, GCD),
|
||||
GCD =:= 1,
|
||||
N is P mod B.
|
||||
|
||||
eeuclid(A,B,P,S,GCD) :-
|
||||
A >= B,
|
||||
a_b_p_s_(A,B,P,S,1-0,0-1,GCD),
|
||||
GCD is A*P + B*S.
|
||||
|
||||
eeuclid(A,B,P,S,GCD) :-
|
||||
A < B,
|
||||
a_b_p_s_(B,A,S,P,1-0,0-1,GCD);
|
||||
GCD is A*P + B*S.
|
||||
|
||||
a_b_p_s_(A,0,P1,S1,P1-_P2,S1-_S2,A).
|
||||
a_b_p_s_(A,B,P,S,P1-P2,S1-S2,GCD) :-
|
||||
B > 0,
|
||||
A > B,
|
||||
Q is truncate(A/B),
|
||||
B1 is A mod B,
|
||||
P3 is P1-(Q*P2),
|
||||
S3 is S1-(Q*S2),
|
||||
a_b_p_s_(B,B1,P,S,P2-P3,S2-S3,GCD).
|
||||
|
|
@ -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,26 @@
|
|||
# Python 2.7
|
||||
def chinese_remainder(n, a):
|
||||
sum = 0
|
||||
prod = reduce(lambda a, b: a*b, n)
|
||||
|
||||
for n_i, a_i in zip(n, a):
|
||||
p = prod / n_i
|
||||
sum += a_i * mul_inv(p, n_i) * p
|
||||
return sum % prod
|
||||
|
||||
|
||||
def mul_inv(a, b):
|
||||
b0 = b
|
||||
x0, x1 = 0, 1
|
||||
if b == 1: return 1
|
||||
while a > 1:
|
||||
q = a / b
|
||||
a, b = b, a%b
|
||||
x0, x1 = x1 - q * x0, x0
|
||||
if x1 < 0: x1 += b0
|
||||
return x1
|
||||
|
||||
if __name__ == '__main__':
|
||||
n = [3, 5, 7]
|
||||
a = [2, 3, 2]
|
||||
print chinese_remainder(n, a)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# Python 3.6
|
||||
from functools import reduce
|
||||
def chinese_remainder(n, a):
|
||||
sum = 0
|
||||
prod = reduce(lambda a, b: a*b, n)
|
||||
for n_i, a_i in zip(n, a):
|
||||
p = prod // n_i
|
||||
sum += a_i * mul_inv(p, n_i) * p
|
||||
return sum % prod
|
||||
|
||||
|
||||
|
||||
def mul_inv(a, b):
|
||||
b0 = b
|
||||
x0, x1 = 0, 1
|
||||
if b == 1: return 1
|
||||
while a > 1:
|
||||
q = a // b
|
||||
a, b = b, a%b
|
||||
x0, x1 = x1 - q * x0, x0
|
||||
if x1 < 0: x1 += b0
|
||||
return x1
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
n = [3, 5, 7]
|
||||
a = [2, 3, 2]
|
||||
print(chinese_remainder(n, a))
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
'''Chinese remainder theorem'''
|
||||
|
||||
from operator import (add, mul)
|
||||
from functools import reduce
|
||||
|
||||
|
||||
# cnRemainder :: [Int] -> [Int] -> Either String Int
|
||||
def cnRemainder(ms):
|
||||
'''Chinese remainder theorem.
|
||||
(moduli, residues) -> Either explanation or solution
|
||||
'''
|
||||
def go(ms, rs):
|
||||
mp = numericProduct(ms)
|
||||
cms = [(mp // x) for x in ms]
|
||||
|
||||
def possibleSoln(invs):
|
||||
return Right(
|
||||
sum(map(
|
||||
mul,
|
||||
cms, map(mul, rs, invs)
|
||||
)) % mp
|
||||
)
|
||||
return bindLR(
|
||||
zipWithEither(modMultInv)(cms)(ms)
|
||||
)(possibleSoln)
|
||||
|
||||
return lambda rs: go(ms, rs)
|
||||
|
||||
|
||||
# modMultInv :: Int -> Int -> Either String Int
|
||||
def modMultInv(a, b):
|
||||
'''Modular multiplicative inverse.'''
|
||||
x, y = eGcd(a, b)
|
||||
return Right(x) if 1 == (a * x + b * y) else (
|
||||
Left('no modular inverse for ' + str(a) + ' and ' + str(b))
|
||||
)
|
||||
|
||||
|
||||
# egcd :: Int -> Int -> (Int, Int)
|
||||
def eGcd(a, b):
|
||||
'''Extended greatest common divisor.'''
|
||||
def go(a, b):
|
||||
if 0 == b:
|
||||
return (1, 0)
|
||||
else:
|
||||
q, r = divmod(a, b)
|
||||
(s, t) = go(b, r)
|
||||
return (t, s - q * t)
|
||||
return go(a, b)
|
||||
|
||||
|
||||
# TEST ----------------------------------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Tests of soluble and insoluble cases.'''
|
||||
|
||||
print(
|
||||
fTable(
|
||||
__doc__ + ':\n\n (moduli, residues) -> ' + (
|
||||
'Either solution or explanation\n'
|
||||
)
|
||||
)(repr)(
|
||||
either(compose(quoted("'"))(curry(add)('No solution: ')))(
|
||||
compose(quoted(' '))(repr)
|
||||
)
|
||||
)(uncurry(cnRemainder))([
|
||||
([10, 4, 12], [11, 12, 13]),
|
||||
([11, 12, 13], [10, 4, 12]),
|
||||
([10, 4, 9], [11, 22, 19]),
|
||||
([3, 5, 7], [2, 3, 2]),
|
||||
([2, 3, 2], [3, 5, 7])
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
# Left :: a -> Either a b
|
||||
def Left(x):
|
||||
'''Constructor for an empty Either (option type) value
|
||||
with an associated string.'''
|
||||
return {'type': 'Either', 'Right': None, 'Left': x}
|
||||
|
||||
|
||||
# Right :: b -> Either a b
|
||||
def Right(x):
|
||||
'''Constructor for a populated Either (option type) value'''
|
||||
return {'type': 'Either', 'Left': None, 'Right': x}
|
||||
# any :: (a -> Bool) -> [a] -> Bool
|
||||
|
||||
|
||||
def any_(p):
|
||||
'''True if p(x) holds for at least
|
||||
one item in xs.'''
|
||||
def go(xs):
|
||||
for x in xs:
|
||||
if p(x):
|
||||
return True
|
||||
return False
|
||||
return lambda xs: go(xs)
|
||||
|
||||
|
||||
# bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
|
||||
def bindLR(m):
|
||||
'''Either monad injection operator.
|
||||
Two computations sequentially composed,
|
||||
with any value produced by the first
|
||||
passed as an argument to the second.'''
|
||||
return lambda mf: (
|
||||
mf(m.get('Right')) if None is m.get('Left') else m
|
||||
)
|
||||
|
||||
|
||||
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
|
||||
def compose(g):
|
||||
'''Right to left function composition.'''
|
||||
return lambda f: lambda x: g(f(x))
|
||||
|
||||
|
||||
# curry :: ((a, b) -> c) -> a -> b -> c
|
||||
def curry(f):
|
||||
'''A curried function derived
|
||||
from an uncurried function.'''
|
||||
return lambda a: lambda b: f(a, b)
|
||||
|
||||
|
||||
# either :: (a -> c) -> (b -> c) -> Either a b -> c
|
||||
def either(fl):
|
||||
'''The application of fl to e if e is a Left value,
|
||||
or the application of fr to e if e is a Right value.'''
|
||||
return lambda fr: lambda e: fl(e['Left']) if (
|
||||
None is e['Right']
|
||||
) else fr(e['Right'])
|
||||
|
||||
|
||||
# fTable :: String -> (a -> String) ->
|
||||
# (b -> String) -> (a -> b) -> [a] -> String
|
||||
def fTable(s):
|
||||
'''Heading -> x display function ->
|
||||
fx display function ->
|
||||
f -> value list -> tabular string.'''
|
||||
def go(xShow, fxShow, f, xs):
|
||||
w = max(map(compose(len)(xShow), xs))
|
||||
return s + '\n' + '\n'.join([
|
||||
xShow(x).rjust(w, ' ') + (' -> ') + fxShow(f(x))
|
||||
for x in xs
|
||||
])
|
||||
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
|
||||
xShow, fxShow, f, xs
|
||||
)
|
||||
|
||||
|
||||
# numericProduct :: [Num] -> Num
|
||||
def numericProduct(xs):
|
||||
'''The arithmetic product of all numbers in xs.'''
|
||||
return reduce(mul, xs, 1)
|
||||
|
||||
|
||||
# partitionEithers :: [Either a b] -> ([a],[b])
|
||||
def partitionEithers(lrs):
|
||||
'''A list of Either values partitioned into a tuple
|
||||
of two lists, with all Left elements extracted
|
||||
into the first list, and Right elements
|
||||
extracted into the second list.
|
||||
'''
|
||||
def go(a, x):
|
||||
ls, rs = a
|
||||
r = x.get('Right')
|
||||
return (ls + [x.get('Left')], rs) if None is r else (
|
||||
ls, rs + [r]
|
||||
)
|
||||
return reduce(go, lrs, ([], []))
|
||||
|
||||
|
||||
# quoted :: Char -> String -> String
|
||||
def quoted(c):
|
||||
'''A string flanked on both sides
|
||||
by a specified quote character.
|
||||
'''
|
||||
return lambda s: c + s + c
|
||||
|
||||
|
||||
# uncurry :: (a -> b -> c) -> ((a, b) -> c)
|
||||
def uncurry(f):
|
||||
'''A function over a tuple,
|
||||
derived from a curried function.'''
|
||||
return lambda xy: f(xy[0])(xy[1])
|
||||
|
||||
|
||||
# zipWithEither :: (a -> b -> Either String c)
|
||||
# -> [a] -> [b] -> Either String [c]
|
||||
def zipWithEither(f):
|
||||
'''Either a list of results if f succeeds with every pair
|
||||
in the zip of xs and ys, or an explanatory string
|
||||
if any application of f returns no result.
|
||||
'''
|
||||
def go(xs, ys):
|
||||
ls, rs = partitionEithers(map(f, xs, ys))
|
||||
return Left(ls[0]) if ls else Right(rs)
|
||||
return lambda xs: lambda ys: go(xs, ys)
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
44
Task/Chinese-remainder-theorem/R/chinese-remainder-theorem.r
Normal file
44
Task/Chinese-remainder-theorem/R/chinese-remainder-theorem.r
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
mul_inv <- function(a, b)
|
||||
{
|
||||
b0 <- b
|
||||
x0 <- 0L
|
||||
x1 <- 1L
|
||||
|
||||
if (b == 1) return(1L)
|
||||
while(a > 1){
|
||||
q <- as.integer(a/b)
|
||||
|
||||
t <- b
|
||||
b <- a %% b
|
||||
a <- t
|
||||
|
||||
t <- x0
|
||||
x0 <- x1 - q*x0
|
||||
x1 <- t
|
||||
}
|
||||
|
||||
if (x1 < 0) x1 <- x1 + b0
|
||||
return(x1)
|
||||
}
|
||||
|
||||
chinese_remainder <- function(n, a)
|
||||
{
|
||||
len <- length(n)
|
||||
|
||||
prod <- 1L
|
||||
sum <- 0L
|
||||
|
||||
for (i in 1:len) prod <- prod * n[i]
|
||||
|
||||
for (i in 1:len){
|
||||
p <- as.integer(prod / n[i])
|
||||
sum <- sum + a[i] * mul_inv(p, n[i]) * p
|
||||
}
|
||||
|
||||
return(sum %% prod)
|
||||
}
|
||||
|
||||
n <- c(3L, 5L, 7L)
|
||||
a <- c(2L, 3L, 2L)
|
||||
|
||||
chinese_remainder(n, a)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*REXX program demonstrates Sun Tzu's (or Sunzi's) Chinese Remainder Theorem. */
|
||||
parse arg Ns As . /*get optional arguments from the C.L. */
|
||||
if Ns=='' | Ns=="," then Ns= '3,5,7' /*Ns not specified? Then use default.*/
|
||||
if As=='' | As=="," then As= '2,3,2' /*As " " " " " */
|
||||
say 'Ns: ' Ns
|
||||
say 'As: ' As; say
|
||||
Ns= space( translate(Ns, , ',')); #= words(Ns) /*elide any superfluous blanks from N's*/
|
||||
As= space( translate(As, , ',')); _= words(As) /* " " " " " A's*/
|
||||
if #\==_ then do; say "size of number sets don't match."; exit 131; end
|
||||
if #==0 then do; say "size of the N set isn't valid."; exit 132; end
|
||||
if _==0 then do; say "size of the A set isn't valid."; exit 133; end
|
||||
N= 1 /*the product─to─be for prod(n.j). */
|
||||
do j=1 for # /*process each number for As and Ns. */
|
||||
n.j= word(Ns, j); N= N * n.j /*get an N.j and calculate product. */
|
||||
a.j= word(As, j) /* " " A.j from the As list. */
|
||||
end /*j*/
|
||||
|
||||
do x=1 for N /*use a simple algebraic method. */
|
||||
do i=1 for # /*process each N.i and A.i number.*/
|
||||
if x//n.i\==a.i then iterate x /*is modulus correct for the number X ?*/
|
||||
end /*i*/ /* [↑] limit solution to the product. */
|
||||
say 'found a solution with X=' x /*display one possible solution. */
|
||||
exit 0 /*stick a fork in it, we're all done. */
|
||||
end /*x*/
|
||||
|
||||
say 'no solution found.' /*oops, announce that solution ¬ found.*/
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*REXX program demonstrates Sun Tzu's (or Sunzi's) Chinese Remainder Theorem. */
|
||||
parse arg Ns As . /*get optional arguments from the C.L. */
|
||||
if Ns=='' | Ns=="," then Ns= '3,5,7' /*Ns not specified? Then use default.*/
|
||||
if As=='' | As=="," then As= '2,3,2' /*As " " " " " */
|
||||
say 'Ns: ' Ns
|
||||
say 'As: ' As; say
|
||||
Ns= space( translate(Ns, , ',')); #= words(Ns) /*elide any superfluous blanks from N's*/
|
||||
As= space( translate(As, , ',')); _= words(As) /* " " " " " A's*/
|
||||
if #\==_ then do; say "size of number sets don't match."; exit 131; end
|
||||
if #==0 then do; say "size of the N set isn't valid."; exit 132; end
|
||||
if _==0 then do; say "size of the A set isn't valid."; exit 133; end
|
||||
N= 1 /*the product─to─be for prod(n.j). */
|
||||
do j=1 for # /*process each number for As and Ns. */
|
||||
n.j= word(Ns,j); N= N * n.j /*get an N.j and calculate product. */
|
||||
a.j= word(As,j) /* " " A.j from the As list. */
|
||||
end /*j*/
|
||||
@.= /* [↓] converts congruences ───► sets.*/
|
||||
do i=1 for #; _= a.i; @.i._= a.i; p= a.i
|
||||
do N; p= p + n.i; @.i.p= p /*build a (array) list of modulo values*/
|
||||
end /*N*/
|
||||
end /*i*/
|
||||
/* [↓] find common number in the sets.*/
|
||||
do x=1 for N; if @.1.x=='' then iterate /*locate a number. */
|
||||
do v=2 to #; if @.v.x=='' then iterate x /*Is in all sets ? */
|
||||
end /*v*/
|
||||
say 'found a solution with X=' x /*display one possible solution. */
|
||||
exit 0 /*stick a fork in it, we're all done. */
|
||||
end /*x*/
|
||||
|
||||
say 'no solution found.' /*oops, announce that solution ¬ found.*/
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#lang racket
|
||||
(require (only-in math/number-theory solve-chinese))
|
||||
(define as '(2 3 2))
|
||||
(define ns '(3 5 7))
|
||||
(solve-chinese as ns)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# returns x where (a * x) % b == 1
|
||||
sub mul-inv($a is copy, $b is copy) {
|
||||
return 1 if $b == 1;
|
||||
my ($b0, @x) = $b, 0, 1;
|
||||
($a, $b, @x) = (
|
||||
$b,
|
||||
$a % $b,
|
||||
@x[1] - ($a div $b)*@x[0],
|
||||
@x[0]
|
||||
) while $a > 1;
|
||||
@x[1] += $b0 if @x[1] < 0;
|
||||
return @x[1];
|
||||
}
|
||||
|
||||
sub chinese-remainder(*@n) {
|
||||
my \N = [*] @n;
|
||||
-> *@a {
|
||||
N R% [+] map {
|
||||
my \p = N div @n[$_];
|
||||
@a[$_] * mul-inv(p, @n[$_]) * p
|
||||
}, ^@n
|
||||
}
|
||||
}
|
||||
|
||||
say chinese-remainder(3, 5, 7)(2, 3, 2);
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
def chinese_remainder(mods, remainders)
|
||||
max = mods.inject( :* )
|
||||
series = remainders.zip( mods ).map{|r,m| r.step( max, m ).to_a }
|
||||
series.inject( :& ).first #returns nil when empty
|
||||
end
|
||||
|
||||
p chinese_remainder([3,5,7], [2,3,2]) #=> 23
|
||||
p chinese_remainder([10,4,9], [11,22,19]) #=> nil
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
def extended_gcd(a, b)
|
||||
last_remainder, remainder = a.abs, b.abs
|
||||
x, last_x = 0, 1
|
||||
while remainder != 0
|
||||
last_remainder, (quotient, remainder) = remainder, last_remainder.divmod(remainder)
|
||||
x, last_x = last_x - quotient*x, x
|
||||
end
|
||||
return last_remainder, last_x * (a < 0 ? -1 : 1)
|
||||
end
|
||||
|
||||
def invmod(e, et)
|
||||
g, x = extended_gcd(e, et)
|
||||
if g != 1
|
||||
raise 'Multiplicative inverse modulo does not exist!'
|
||||
end
|
||||
x % et
|
||||
end
|
||||
|
||||
def chinese_remainder(mods, remainders)
|
||||
max = mods.inject( :* ) # product of all moduli
|
||||
series = remainders.zip(mods).map{ |r,m| (r * max * invmod(max/m, m) / m) }
|
||||
series.inject( :+ ) % max
|
||||
end
|
||||
|
||||
p chinese_remainder([3,5,7], [2,3,2]) #=> 23
|
||||
p chinese_remainder([17353461355013928499, 3882485124428619605195281, 13563122655762143587], [7631415079307304117, 1248561880341424820456626, 2756437267211517231]) #=> 937307771161836294247413550632295202816
|
||||
p chinese_remainder([10,4,9], [11,22,19]) #=> nil
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
fn egcd(a: i64, b: i64) -> (i64, i64, i64) {
|
||||
if a == 0 {
|
||||
(b, 0, 1)
|
||||
} else {
|
||||
let (g, x, y) = egcd(b % a, a);
|
||||
(g, y - (b / a) * x, x)
|
||||
}
|
||||
}
|
||||
|
||||
fn mod_inv(x: i64, n: i64) -> Option<i64> {
|
||||
let (g, x, _) = egcd(x, n);
|
||||
if g == 1 {
|
||||
Some((x % n + n) % n)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn chinese_remainder(residues: &[i64], modulii: &[i64]) -> Option<i64> {
|
||||
let prod = modulii.iter().product::<i64>();
|
||||
|
||||
let mut sum = 0;
|
||||
|
||||
for (&residue, &modulus) in residues.iter().zip(modulii) {
|
||||
let p = prod / modulus;
|
||||
sum += residue * mod_inv(p, modulus)? * p
|
||||
}
|
||||
|
||||
Some(sum % prod)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let modulii = [3,5,7];
|
||||
let residues = [2,3,2];
|
||||
|
||||
match chinese_remainder(&residues, &modulii) {
|
||||
Some(sol) => println!("{}", sol),
|
||||
None => println!("modulii not pairwise coprime")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
create temporary table inputs(remainder int, modulus int);
|
||||
|
||||
insert into inputs values (2, 3), (3, 5), (2, 7);
|
||||
|
||||
with recursive
|
||||
|
||||
-- Multiply out the product of moduli
|
||||
multiplication(idx, product) as (
|
||||
select 1, 1
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
multiplication.idx+1,
|
||||
multiplication.product * inputs.modulus
|
||||
from
|
||||
multiplication,
|
||||
inputs
|
||||
where
|
||||
inputs.rowid = multiplication.idx
|
||||
),
|
||||
|
||||
-- Take the final value from the product table
|
||||
product(final_value) as (
|
||||
select max(product) from multiplication
|
||||
),
|
||||
|
||||
-- Calculate the multiplicative inverse from each equation
|
||||
multiplicative_inverse(id, a, b, x, y) as (
|
||||
select
|
||||
inputs.modulus,
|
||||
product.final_value / inputs.modulus,
|
||||
inputs.modulus,
|
||||
0,
|
||||
1
|
||||
from
|
||||
inputs,
|
||||
product
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
id,
|
||||
b, a%b,
|
||||
y - (a/b)*x, x
|
||||
from
|
||||
multiplicative_inverse
|
||||
where
|
||||
a>0
|
||||
)
|
||||
-- Combine residues into final answer
|
||||
select
|
||||
sum(
|
||||
(y % inputs.modulus) * inputs.remainder * (product.final_value / inputs.modulus)
|
||||
) % product.final_value
|
||||
from
|
||||
multiplicative_inverse, product, inputs
|
||||
where
|
||||
a=1 and multiplicative_inverse.id = inputs.modulus;
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
object ChineseRemainderTheorem extends App {
|
||||
|
||||
def chineseRemainder(n: List[Int], a: List[Int]): Option[Int] = {
|
||||
require(n.size == a.size)
|
||||
val prod = n.product
|
||||
|
||||
def iter(n: List[Int], a: List[Int], sm: Int): Int = {
|
||||
def mulInv(a: Int, b: Int): Int = {
|
||||
def loop(a: Int, b: Int, x0: Int, x1: Int): Int = {
|
||||
if (a > 1) loop(b, a % b, x1 - (a / b) * x0, x0) else x1
|
||||
}
|
||||
|
||||
if (b == 1) 1
|
||||
else {
|
||||
val x1 = loop(a, b, 0, 1)
|
||||
if (x1 < 0) x1 + b else x1
|
||||
}
|
||||
}
|
||||
|
||||
if (n.nonEmpty) {
|
||||
val p = prod / n.head
|
||||
|
||||
iter(n.tail, a.tail, sm + a.head * mulInv(p, n.head) * p)
|
||||
} else sm
|
||||
}
|
||||
|
||||
Try {
|
||||
iter(n, a, 0) % prod
|
||||
} match {
|
||||
case Success(v) => Some(v)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
println(chineseRemainder(List(3, 5, 7), List(2, 3, 2)))
|
||||
println(chineseRemainder(List(11, 12, 13), List(10, 4, 12)))
|
||||
println(chineseRemainder(List(11, 22, 19), List(10, 4, 9)))
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "bigint.s7i";
|
||||
|
||||
const func integer: modInverse (in integer: a, in integer: b) is
|
||||
return ord(modInverse(bigInteger conv a, bigInteger conv b));
|
||||
|
||||
const proc: main is func
|
||||
local
|
||||
const array integer: n is [] (3, 5, 7);
|
||||
const array integer: a is [] (2, 3, 2);
|
||||
var integer: num is 0;
|
||||
var integer: prod is 1;
|
||||
var integer: sum is 0;
|
||||
var integer: index is 0;
|
||||
begin
|
||||
for num range n do
|
||||
prod *:= num;
|
||||
end for;
|
||||
for key index range a do
|
||||
num := prod div n[index];
|
||||
sum +:= a[index] * modInverse(num, n[index]) * num;
|
||||
end for;
|
||||
writeln(sum mod prod);
|
||||
end func;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
func chinese_remainder(*n) {
|
||||
var N = n.prod
|
||||
func (*a) {
|
||||
n.range.sum { |i|
|
||||
var p = (N / n[i])
|
||||
a[i] * p.invmod(n[i]) * p
|
||||
} % N
|
||||
}
|
||||
}
|
||||
|
||||
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,18 @@
|
|||
proc ::tcl::mathfunc::mulinv {a b} {
|
||||
if {$b == 1} {return 1}
|
||||
set b0 $b; set x0 0; set x1 1
|
||||
while {$a > 1} {
|
||||
set x0 [expr {$x1 - ($a / $b) * [set x1 $x0]}]
|
||||
set b [expr {$a % [set a $b]}]
|
||||
}
|
||||
incr x1 [expr {($x1 < 0) * $b0}]
|
||||
}
|
||||
proc chineseRemainder {nList aList} {
|
||||
set sum 0; set prod [::tcl::mathop::* {*}$nList]
|
||||
foreach n $nList a $aList {
|
||||
set p [expr {$prod / $n}]
|
||||
incr sum [expr {$a * mulinv($p, $n) * $p}]
|
||||
}
|
||||
expr {$sum % $prod}
|
||||
}
|
||||
puts [chineseRemainder {3 5 7} {2 3 2}]
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
Private Function chinese_remainder(n As Variant, a As Variant) As Variant
|
||||
Dim p As Long, prod As Long, tot As Long
|
||||
prod = 1: tot = 0
|
||||
For i = 1 To UBound(n)
|
||||
prod = prod * n(i)
|
||||
Next i
|
||||
Dim m As Variant
|
||||
For i = 1 To UBound(n)
|
||||
p = prod / n(i)
|
||||
m = mul_inv(p, n(i))
|
||||
If WorksheetFunction.IsText(m) Then
|
||||
chinese_remainder = "fail"
|
||||
Exit Function
|
||||
End If
|
||||
tot = tot + a(i) * m * p
|
||||
Next i
|
||||
chinese_remainder = tot Mod prod
|
||||
End Function
|
||||
Public Sub re()
|
||||
Debug.Print chinese_remainder([{3,5,7}], [{2,3,2}])
|
||||
Debug.Print chinese_remainder([{11,12,13}], [{10,4,12}])
|
||||
Debug.Print chinese_remainder([{11,22,19}], [{10,4,9}])
|
||||
Debug.Print chinese_remainder([{100,23}], [{19,0}])
|
||||
End Sub
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
Module Module1
|
||||
|
||||
Function ModularMultiplicativeInverse(a As Integer, m As Integer) As Integer
|
||||
Dim b = a Mod m
|
||||
For x = 1 To m - 1
|
||||
If (b * x) Mod m = 1 Then
|
||||
Return x
|
||||
End If
|
||||
Next
|
||||
Return 1
|
||||
End Function
|
||||
|
||||
Function Solve(n As Integer(), a As Integer()) As Integer
|
||||
Dim prod = n.Aggregate(1, Function(i, j) i * j)
|
||||
Dim sm = 0
|
||||
Dim p As Integer
|
||||
For i = 0 To n.Length - 1
|
||||
p = prod / n(i)
|
||||
sm = sm + a(i) * ModularMultiplicativeInverse(p, n(i)) * p
|
||||
Next
|
||||
Return sm Mod prod
|
||||
End Function
|
||||
|
||||
Sub Main()
|
||||
Dim n = {3, 5, 7}
|
||||
Dim a = {2, 3, 2}
|
||||
|
||||
Dim result = Solve(n, a)
|
||||
|
||||
Dim counter = 0
|
||||
Dim maxCount = n.Length - 1
|
||||
While counter <= maxCount
|
||||
Console.WriteLine($"{result} = {a(counter)} (mod {n(counter)})")
|
||||
counter = counter + 1
|
||||
End While
|
||||
End Sub
|
||||
|
||||
End Module
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/* returns x where (a * x) % b == 1 */
|
||||
var mulInv = Fn.new { |a, b|
|
||||
if (b == 1) return 1
|
||||
var b0 = b
|
||||
var x0 = 0
|
||||
var x1 = 1
|
||||
while (a > 1) {
|
||||
var q = (a/b).floor
|
||||
var t = b
|
||||
b = a % b
|
||||
a = t
|
||||
t = x0
|
||||
x0 = x1 - q*x0
|
||||
x1 = t
|
||||
}
|
||||
if (x1 < 0) x1 = x1 + b0
|
||||
return x1
|
||||
}
|
||||
|
||||
var chineseRemainder = Fn.new { |n, a|
|
||||
var prod = n.reduce { |acc, i| acc * i }
|
||||
var sum = 0
|
||||
for (i in 0...n.count) {
|
||||
var p = (prod/n[i]).floor
|
||||
sum = sum + a[i]*mulInv.call(p, n[i])*p
|
||||
}
|
||||
return sum % prod
|
||||
}
|
||||
|
||||
var n = [3, 5, 7]
|
||||
var a = [2, 3, 2]
|
||||
System.print(chineseRemainder.call(n, a))
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
func MulInv(A, B); \Returns X where rem((A*X) / B) = 1
|
||||
int A, B;
|
||||
int B0, T, Q;
|
||||
int X0, X1;
|
||||
[B0:= B; X0:= 0; X1:= 1;
|
||||
if B = 1 then return 1;
|
||||
while A > 1 do
|
||||
[Q:= A / B;
|
||||
T:= B; B:= rem(A/B); A:= T;
|
||||
T:= X0; X0:= X1 - Q*X0; X1:= T;
|
||||
];
|
||||
if X1 < 0 then X1:= X1 + B0;
|
||||
return X1;
|
||||
];
|
||||
|
||||
func ChineseRem(N, A, Len);
|
||||
int N, A, Len;
|
||||
int P, I, Prod, Sum;
|
||||
[Prod:= 1; Sum:= 0;
|
||||
for I:= 0 to Len-1 do Prod:= Prod*N(I);
|
||||
for I:= 0 to Len-1 do
|
||||
[P:= Prod / N(I);
|
||||
Sum:= Sum + A(I) * MulInv(P,N(I)) * P;
|
||||
];
|
||||
return rem(Sum/Prod);
|
||||
];
|
||||
|
||||
int N, A;
|
||||
[N:= [ 3, 5, 7 ];
|
||||
A:= [ 2, 3, 2 ];
|
||||
IntOut(0, ChineseRem(N, A, 3)); CrLf(0);
|
||||
]
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
10 DIM n(3): DIM a(3)
|
||||
20 FOR i=1 TO 3
|
||||
30 READ n(i),a(i)
|
||||
40 NEXT i
|
||||
50 DATA 3,2,5,3,7,2
|
||||
100 LET prod=1: LET sum=0
|
||||
110 FOR i=1 TO 3: LET prod=prod*n(i): NEXT i
|
||||
120 FOR i=1 TO 3
|
||||
130 LET p=INT (prod/n(i)): LET a=p: LET b=n(i)
|
||||
140 GO SUB 1000
|
||||
150 LET sum=sum+a(i)*x1*p
|
||||
160 NEXT i
|
||||
170 PRINT FN m(sum,prod)
|
||||
180 STOP
|
||||
200 DEF FN m(a,b)=a-INT (a/b)*b: REM Modulus function
|
||||
1000 LET b0=b: LET x0=0: LET x1=1
|
||||
1010 IF b=1 THEN RETURN
|
||||
1020 IF a<=1 THEN GO TO 1100
|
||||
1030 LET q=INT (a/b)
|
||||
1040 LET t=b: LET b=FN m(a,b): LET a=t
|
||||
1050 LET t=x0: LET x0=x1-q*x0: LET x1=t
|
||||
1060 GO TO 1020
|
||||
1100 IF x1<0 THEN LET x1=x1+b0
|
||||
1110 RETURN
|
||||
|
|
@ -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