https://projecteuler.net/problem=74
辿っていくとρ型になるのですが、すでにあと何歩進めるか分かっているノードに突き当たったら、そこで終了できます。
import sys #################### library #################### fn make_factorial_table(N: Int) -> List[Int]: var a = List[Int]() a.append(1) for n in range(1, N+1): a.append(a[n-1] * n) return a fn digits(owned n: Int) -> List[Int]: var ds = List[Int]() while n > 0: var d = n % 10 n //= 10 ds.append(d) return ds fn frequency[T: KeyElement](v: List[T]) -> Dict[T, Int]: var freq = Dict[T, Int]() for e in v: var f = freq.get(e[], 0) freq[e[]] = f + 1 return freq #################### List #################### fn initialize_list[T: CollectionElement](N: Int, init: T) -> List[T]: var a = List[T](capacity=N) for n in range(N): a.append(init) return a trait Printable(CollectionElement, Stringable): pass fn print_list[T: Printable](a: List[T]): if a.size > 0: var s = "[" + str(a[0]) for i in range(1, a.size): s += ", " + str(a[i]) s += "]" print(s) else: print("[]") #################### process #################### var facts = List[Int]() fn step(n: Int) -> Int: var ds = digits(n) var s = 0 for d in ds: s += facts[d[]] return s fn find_rho(n: Int, a: List[Int], dists: List[Int]) -> List[Int]: var rho = List[Int](n) var p = a[n] var q = a[p] # 2歩ずつ進む rho.append(p) while p != q: if dists[p] != 0: # すでに確定したノードに突き当たる return rho p = a[p] q = a[a[q]] rho.append(p) rho.append(a[p]) return rho fn update_rho(rho: List[Int], inout dists: List[Int]): var L = len(rho) var pt = rho[L-1] # loopの始点はどこか? var k = 0 while rho[k] != pt: k += 1 for i in range(L-1): if i < k: dists[rho[i]] = L - i else: dists[rho[i]] = L - k - 1 fn update_I(rho: List[Int], inout dists: List[Int]): var L = len(rho) var pt = rho[L-1] # loopの始点はどこか? var k = 0 while rho[k] != pt: if dists[rho[k]] != 0: break k += 1 for i in range(k): dists[rho[i]] = k - i + dists[rho[k]] fn dist_naive(owned n: Int) -> Int: var s = Set[Int]() while n not in s: s.add(n) n = step(n) return len(s) fn max_number(N: Int) -> Int: if N < 10**7: return max(N, 2+6*facts[9]) else: return N fn f(N: Int) -> Int: facts = make_factorial_table(9) var M = max_number(N) var a = initialize_list(M+1, 0) for n in range(M+1): a[n] = step(n) var dists = initialize_list(M+1, 0) for n in range(1, M+1): if dists[n] != 0: continue var rho = find_rho(n, a, dists) if dists[rho[len(rho)-1]] == 0: # ρ型 update_rho(rho, dists) else: # I型 update_I(rho, dists) var counter = 0 for n in range(N+1): if dists[n] == 61: counter += 1 return counter fn main() raises: var args = sys.argv() var N = atol(args[1]) print(f(N))