95 lines
2.3 KiB
Python
95 lines
2.3 KiB
Python
|
|
||
|
def odd(n):
|
||
|
return n % 2 == 1
|
||
|
|
||
|
def is_square(n):
|
||
|
""" From the internet. I should implement my own version of this. """
|
||
|
## Trivial checks
|
||
|
if type(n) != int: ## integer
|
||
|
return False
|
||
|
if n < 0: ## positivity
|
||
|
return False
|
||
|
if n == 0: ## 0 pass
|
||
|
return True
|
||
|
|
||
|
## Reduction by powers of 4 with bit-logic
|
||
|
while n&3 == 0:
|
||
|
n=n>>2
|
||
|
|
||
|
## Simple bit-logic test. All perfect squares, in binary,
|
||
|
## end in 001, when powers of 4 are factored out.
|
||
|
if n&7 != 1:
|
||
|
return False
|
||
|
|
||
|
if n==1:
|
||
|
return True ## is power of 4, or even power of 2
|
||
|
|
||
|
## Simple modulo equivalency test
|
||
|
c = n%10
|
||
|
if c in {3, 7}:
|
||
|
return False ## Not 1,4,5,6,9 in mod 10
|
||
|
if n % 7 in {3, 5, 6}:
|
||
|
return False ## Not 1,2,4 mod 7
|
||
|
if n % 9 in {2,3,5,6,8}:
|
||
|
return False
|
||
|
if n % 13 in {2,5,6,7,8,11}:
|
||
|
return False
|
||
|
|
||
|
## Other patterns
|
||
|
if c == 5: ## if it ends in a 5
|
||
|
if (n//10)%10 != 2:
|
||
|
return False ## then it must end in 25
|
||
|
if (n//100)%10 not in {0,2,6}:
|
||
|
return False ## and in 025, 225, or 625
|
||
|
if (n//100)%10 == 6:
|
||
|
if (n//1000)%10 not in {0,5}:
|
||
|
return False ## that is, 0625 or 5625
|
||
|
else:
|
||
|
if (n//10)%4 != 0:
|
||
|
return False ## (4k)*10 + (1,9)
|
||
|
|
||
|
## Babylonian Algorithm. Finding the integer square root.
|
||
|
## Root extraction.
|
||
|
s = (len(str(n))-1) // 2
|
||
|
x = (10**s) * 4
|
||
|
A = {x, n}
|
||
|
while x * x != n:
|
||
|
x = (x + (n // x)) >> 1
|
||
|
if x in A:
|
||
|
return False
|
||
|
A.add(x)
|
||
|
return True
|
||
|
|
||
|
|
||
|
def euler_094():
|
||
|
n_max = 10 ** 9
|
||
|
n, total_peri = 2, 0
|
||
|
while n < n_max:
|
||
|
n += 2
|
||
|
for b2, c in [(n, n + 1), (n, n - 1)]:
|
||
|
b = b2 // 2
|
||
|
a_squared = c * c - b * b
|
||
|
|
||
|
if not is_square(a_squared):
|
||
|
continue
|
||
|
|
||
|
peri = 2 * c + b2
|
||
|
# print("b2={} c={} peri={}".format(b2, c, peri))
|
||
|
|
||
|
if peri > n_max:
|
||
|
return total_peri
|
||
|
|
||
|
total_peri += peri
|
||
|
|
||
|
if b2 > 10000:
|
||
|
n = int(n * 3.725) - 5
|
||
|
if odd(n):
|
||
|
n -= 1
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
solution = euler_094()
|
||
|
print("e094.py: " + str(solution))
|
||
|
assert(solution == 518408346)
|
||
|
|