mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-24 21:41:08 +00:00
d407476531
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
142 lines
2.9 KiB
Python
142 lines
2.9 KiB
Python
"""
|
||
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.
|
||
"""
|
||
|
||
import sys
|
||
|
||
sys.set_int_max_str_digits(0) # type: ignore
|
||
|
||
|
||
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 _ 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 _ 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 _ 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() = }")
|