mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 23:11:09 +00:00
4700297b3e
* Enable ruff RUF002 rule * Fix --------- Co-authored-by: Christian Clauss <cclauss@me.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)
|
|
|
|
|
|
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() = }")
|