MojoでProject Euler 49

https://projecteuler.net/problem=49

10進で表した数字をソートした数をキーに素数を集めます。ただし降順に並べます。例えば、1320なら3210です。昇順だと123になってしまい違う桁の数も同じキーになってしまいます。
問題なのは4つの数が等差数列になるかですが、5桁で早くもそういう数が出てきました。

from collections import Dict
import sys


#################### List ####################

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("[]")

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

fn insert_list[T: CollectionElement](inout v: List[T], e: T, i: Int):
    v.append(e)
    for k in range(len(v) - 1, i, -1):
        v[k] = v[k-1]
    v[i] = e

fn combinations_core[T: CollectionElement](a: List[T],
                                            n: Int, k: Int) -> List[List[T]]:
    if n == 0:
        return List[List[T]](List[T]())
    
    var vs = List[List[T]]()
    for k1 in range(k, len(a) - n + 1):
        var v = combinations_core(a, n-1, k1+1)
        for w in v:
            insert_list(w[], a[k1], 0)
            vs.append(w[])
    return vs

fn combinations[T: CollectionElement](a: List[T], n: Int) -> List[List[T]]:
    return combinations_core(a, n, 0)


#################### library ####################

fn make_prime_table(N: Int) -> List[Int]:
    var a = initialize_list(N+1, True)
    for p in range(2, N+1):
        if p * p > N:
            break
        elif not a[p]:
            continue
        
        for n in range(p*p, N+1, p):
            a[n] = False
    
    var ps = List[Int]()
    for n in range(2, N+1):
        if a[n]:
            ps.append(n)
    return ps

fn digits(owned n: Int) -> List[Int]:
    var ds = List[Int]()
    while n > 0:
        var d = n % 10
        ds.append(d)
        n //= 10
    return ds


#################### process ####################

fn sort_number(n: Int) -> Int:
    var ds = digits(n)
    sort(ds)
    var m = 0
    for i in range(len(ds)-1, -1, -1):
        m = m * 10 + ds[i]
    return m

fn classify(N: Int, primes: List[Int]) -> Dict[Int, List[Int]]:
    var dic = Dict[Int, List[Int]]()
    for p in primes:
        if p[] < 10**(N-1):
            continue
        var m = sort_number(p[])
        if m in dic:
            try:
                dic[m].append(p[])
            except:
                pass
        else:
            dic[m] = List[Int](p[])
    return dic

fn is_arithmetic(v: List[Int]) -> Bool:
    var d = v[1] - v[0]
    for k in range(2, len(v)):
        if v[k] - v[k-1] != d:
            return False
    return True

fn f(N: Int, M: Int):
    var primes = make_prime_table(10**N)
    var dic = classify(N, primes)
    for ns in dic.values():
        for v in combinations(ns[], M):
            if is_arithmetic(v[]):
                var s = String("")
                for n in v[]:
                    s += str(n[])
                print(s)

fn main() raises:
    var args = sys.argv()
    var N = atol(args[1])
    var M = atol(args[2])
    f(N, M)