Project Euler Problem 93 Solution

Project Euler Problem 93 Solution

Square Digit Chains

by {BetaProjects} | Project Euler & HackerRank

Project Euler Problem 93 Statement

Solution

HackerRank version

Given a set of $m$ distinct digits, $S$, find the largest possible integer $n$ such that each integer from $1$ to $n$ is expressible using elements of $S$ and following the above rules. If $1$ is also not expressible, output $0$ instead.

Python Source Code

from functools import lru_cache
from itertools import combinations
from math import gcd

def simplify(n, d):
    if d == 0:
        return None  # Avoid division by zero
    g = gcd(abs(n), abs(d)) * (-1 if d < 0 else 1)
    return n // g, d // g

def generate_rational(m, n):
    results = set()
    if m and n:
        results.update({
            simplify(m[0] * n[1] + n[0] * m[1], m[1] * n[1]),
            simplify(m[0] * n[0], m[1] * n[1]),
            simplify(m[0] * n[1], m[1] * n[0]),
            simplify(n[0] * m[1], n[1] * m[0]),
            simplify(m[0] * n[1] - n[0] * m[1], m[1] * n[1]),
            simplify(n[0] * m[1] - m[0] * n[1], n[1] * m[1])
        })
    return {r for r in results if r}

def fold_digits(digits):
    return sum(1 << d for d in digits)

@lru_cache(None)
def arithmetic_exp(bitmask):
    digits = [i for i in range(10) if (bitmask >> i) & 1]
    if len(digits) == 1:
        return {simplify(digits[0], 1)}
    result = set()
    for i in range(1, len(digits)):
        for sel in combinations(digits, i):
            a = fold_digits(sel)
            b = bitmask ^ a
            for m in arithmetic_exp(a):
                for n in arithmetic_exp(b):
                    result.update(generate_rational(m, n))
    return result

def main():
    n = int(input())
    digits = list(map(int, input().split()))
    bitmask = fold_digits(digits)
    rationals = arithmetic_exp(bitmask)
    numbers = {r[0] for r in rationals if r and r[1] == 1 and r[0] >= 0}
    r = 0
    while r + 1 in numbers:
        r += 1
    print(r)

if __name__ == "__main__":
    main()	

Last Word