summaryrefslogtreecommitdiff
path: root/euler_700.py
blob: 876b35d2ef6b22e7259ac6476dac2652b3d760ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env python

# we use two method to get the Eulercoins
# 1. iterate over the sequence
# 2. find the *n* such that for a given number *a*, mul*n=a (mod g)

mul = 1504170715041707
mod = 4503599627370517

# gcdrev(a,b)=(g,a',b')
# - g is gcd(a,b)
# - a'a+b'b=g
# gcdrev_ calculates one (a',b') answer, while gcdrev() makes a'>=0

def gcdrev_(a,b):
    if a == 0 and b == 0:
        raise ValueError

    if a == 0:
        return b,0,1

    if b == 0:
        return a,1,0

    q = a // b
    g,aa,bb = gcdrev_(b,a%b)
    return g,bb,(aa-q*bb)

def gcdrev(a,b):
    if b <= 0:
        raise ValueError

    g,x0,y0 = gcdrev_(a,b)
    if x0 < 0:
        t = (-x0 + b - 1) // b
        x = x0 + t * b
        y = y0 - t * a
        return g,x,y
    else:
        t = x0 // b
        x = x0 - t * b
        y = y0 + t * a
        return g,x,y

def main():
    sum_of_coins = 0
    g,r,_ = gcdrev(mul,mod) # actually g is 1

    # we use the second method, until the smallest n is smaller than the coin
    print("======== First run ========")
    coin = g
    n_min = mod
    while coin < n_min:
        n = coin * r % mod
        if n < n_min:
            n_min = n
            sum_of_coins = sum_of_coins + coin
            print("n = {}, coin = {}".format(n, coin))

        coin = coin + g

    # then use the first method, until n >= n_min
    print("======== Second run ========")
    mincoin = mod
    n = 1
    coin = mul % mod
    while n < n_min:
        if coin < mincoin:
            sum_of_coins = sum_of_coins + coin
            mincoin = coin
            print("n = {}, coin = {}".format(n,coin))

        n = n + 1
        coin = (coin + mul) % mod

    print(sum_of_coins)

if __name__ == "__main__":
    main()