mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-12-03 18:01:09 +00:00
138 lines
2.9 KiB
Plaintext
138 lines
2.9 KiB
Plaintext
|
"""
|
|||
|
Project Euler Problem 104 : https://projecteuler.net/problem=104
|
|||
|
|
|||
|
The Fibonacci sequence is defined by the recurrence relation:
|
|||
|
|
|||
|
Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.
|
|||
|
It turns out that F541, which contains 113 digits, is the first Fibonacci number
|
|||
|
for which the last nine digits are 1-9 pandigital (contain all the digits 1 to 9,
|
|||
|
but not necessarily in order). And F2749, which contains 575 digits, is the first
|
|||
|
Fibonacci number for which the first nine digits are 1-9 pandigital.
|
|||
|
|
|||
|
Given that Fk is the first Fibonacci number for which the first nine digits AND
|
|||
|
the last nine digits are 1-9 pandigital, find k.
|
|||
|
"""
|
|||
|
|
|||
|
|
|||
|
def check(number: int) -> bool:
|
|||
|
"""
|
|||
|
Takes a number and checks if it is pandigital both from start and end
|
|||
|
|
|||
|
|
|||
|
>>> check(123456789987654321)
|
|||
|
True
|
|||
|
|
|||
|
>>> check(120000987654321)
|
|||
|
False
|
|||
|
|
|||
|
>>> check(1234567895765677987654321)
|
|||
|
True
|
|||
|
|
|||
|
"""
|
|||
|
|
|||
|
check_last = [0] * 11
|
|||
|
check_front = [0] * 11
|
|||
|
|
|||
|
# mark last 9 numbers
|
|||
|
for x in range(9):
|
|||
|
check_last[int(number % 10)] = 1
|
|||
|
number = number // 10
|
|||
|
# flag
|
|||
|
f = True
|
|||
|
|
|||
|
# check last 9 numbers for pandigitality
|
|||
|
|
|||
|
for x in range(9):
|
|||
|
if not check_last[x + 1]:
|
|||
|
f = False
|
|||
|
if not f:
|
|||
|
return f
|
|||
|
|
|||
|
# mark first 9 numbers
|
|||
|
number = int(str(number)[:9])
|
|||
|
|
|||
|
for x in range(9):
|
|||
|
check_front[int(number % 10)] = 1
|
|||
|
number = number // 10
|
|||
|
|
|||
|
# check first 9 numbers for pandigitality
|
|||
|
|
|||
|
for x in range(9):
|
|||
|
if not check_front[x + 1]:
|
|||
|
f = False
|
|||
|
return f
|
|||
|
|
|||
|
|
|||
|
def check1(number: int) -> bool:
|
|||
|
"""
|
|||
|
Takes a number and checks if it is pandigital from END
|
|||
|
|
|||
|
>>> check1(123456789987654321)
|
|||
|
True
|
|||
|
|
|||
|
>>> check1(120000987654321)
|
|||
|
True
|
|||
|
|
|||
|
>>> check1(12345678957656779870004321)
|
|||
|
False
|
|||
|
|
|||
|
"""
|
|||
|
|
|||
|
check_last = [0] * 11
|
|||
|
|
|||
|
# mark last 9 numbers
|
|||
|
for x in range(9):
|
|||
|
check_last[int(number % 10)] = 1
|
|||
|
number = number // 10
|
|||
|
# flag
|
|||
|
f = True
|
|||
|
|
|||
|
# check last 9 numbers for pandigitality
|
|||
|
|
|||
|
for x in range(9):
|
|||
|
if not check_last[x + 1]:
|
|||
|
f = False
|
|||
|
return f
|
|||
|
|
|||
|
|
|||
|
def solution() -> int:
|
|||
|
"""
|
|||
|
Outputs the answer is the least Fibonacci number pandigital from both sides.
|
|||
|
>>> solution()
|
|||
|
329468
|
|||
|
"""
|
|||
|
|
|||
|
a = 1
|
|||
|
b = 1
|
|||
|
c = 2
|
|||
|
# temporary Fibonacci numbers
|
|||
|
|
|||
|
a1 = 1
|
|||
|
b1 = 1
|
|||
|
c1 = 2
|
|||
|
# temporary Fibonacci numbers mod 1e9
|
|||
|
|
|||
|
# mod m=1e9, done for fast optimisation
|
|||
|
tocheck = [0] * 1000000
|
|||
|
m = 1000000000
|
|||
|
|
|||
|
for x in range(1000000):
|
|||
|
c1 = (a1 + b1) % m
|
|||
|
a1 = b1 % m
|
|||
|
b1 = c1 % m
|
|||
|
if check1(b1):
|
|||
|
tocheck[x + 3] = 1
|
|||
|
|
|||
|
for x in range(1000000):
|
|||
|
c = a + b
|
|||
|
a = b
|
|||
|
b = c
|
|||
|
# perform check only if in tocheck
|
|||
|
if tocheck[x + 3] and check(b):
|
|||
|
return x + 3 # first 2 already done
|
|||
|
return -1
|
|||
|
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
print(f"{solution() = }")
|