MojoでProject Euler 20

https://projecteuler.net/problem=20

DynamicVectorに__iter__()が実装されたようです。ただし、所有権は放棄しないので、Reference型を返します。これをデリファレンスするには、

for e in v:
    print(e[])

のようにします。

from math import max
import sys


#################### BigInteger ####################

struct BigInteger(CollectionElement):
    var v: DynamicVector[Int]
    
    fn __init__(inout self, v: DynamicVector[Int]):
        self.v = v
    
    fn __copyinit__(inout self, other: BigInteger):
        self.v = other.v
    
    fn __moveinit__(inout self, owned other: BigInteger):
        self.v = other.v^
    
    fn __add__(self, other: BigInteger) -> BigInteger:
        var v = DynamicVector[Int]()
        var carry = 0
        for i in range(max(self.v.size, other.v.size)):
            var d1 = self.v[i] if i < self.v.size else 0
            var d2 = other.v[i] if i < other.v.size else 0
            var n = d1 + d2 + carry
            v.push_back(n % 10)
            carry = n // 10
        if carry > 0:
            v.push_back(carry)
        return BigInteger(v)
    
    fn __mul__(self, other: Int) -> BigInteger:
        var v = DynamicVector[Int]()
        var carry = 0
        for d in self.v:
            var n = d[] * other + carry
            v.push_back(n % 10)
            carry = n // 10
        while carry > 0:
            var r = carry % 10
            carry //= 10
            v.push_back(r)
        return BigInteger(v)
    
    fn __str__(self) -> String:
        var s: String = ""
        for i in range(self.v.size-1, -1, -1):
            s += String(self.v[i])
        return s
    
    @staticmethod
    fn create(n: Int) -> BigInteger:
        var v = DynamicVector[Int]()
        v.push_back(n)
        return BigInteger(v)
    
    @staticmethod
    fn parse(s: String) -> BigInteger:
        var v = DynamicVector[Int]()
        for i in range(len(s)-1, -1, -1):
            v.push_back(ord(s[i]) - 48)
        return BigInteger(v)


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

fn sum(v: DynamicVector[Int]) -> Int:
    var s = 0
    for i in range(v.size):
        s += v[i]
    return s

fn f(N: Int) -> Int:
    var b = BigInteger.create(1)
    for n in range(1, N+1):
        b = b * n
    return sum(b.v)

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