MojoでProject Euler 8

https://projecteuler.net/problem=8

毎回13個の数字を掛け算すればよいですが、もう少し頑張れば計算量を減らせます。0が13個の間に何個あるのかと最後の0のあと積を記憶しておけばよいです。

# e008.mojo
import sys

struct ProductGenerator:
    var L: Int
    var ds: DynamicVector[Int]
    var num_zeros: Int
    var product: Int
    var i: Int
    
    fn __init__(inout self, L: Int, ds: DynamicVector[Int], nz: Int, p: Int):
        self.L = L
        self.ds = ds
        self.num_zeros = nz
        self.product = p
        self.i = -1
    
    fn next(inout self) -> Int:
        self.i += 1
        if self.i != 0 and self.ds[self.i-1] == 0:
            self.num_zeros -= 1
        elif self.i != 0 and self.num_zeros == 0:
            self.product /= self.ds[self.i-1]
        
        if self.ds[self.i+self.L-1] == 0:
            self.num_zeros += 1
            self.product = 1
            return 0
        else:
            self.product *= self.ds[self.i+self.L-1]
            if self.num_zeros == 0:
                return self.product
            else:
                return 0
    
    @staticmethod
    fn create(s: String, L: Int) raises -> ProductGenerator:
        var ds = DynamicVector[Int]()
        for i in range(len(s)):
            ds.push_back(atol(s[i]))
        
        var nz = 0
        var p = 1
        for i in range(L-1):
            if ds[i] == 0:
                nz += 0
                p = 1
            else:
                p *= ds[i]
        return ProductGenerator(L, ds, nz, p)

fn f(str_digits: String, L: Int) raises -> Int:
    var pg = ProductGenerator.create(str_digits, L)
    var max_p = 0
    for i in range(len(str_digits) - L + 1):
        let p = pg.next()
        if p > max_p:
            max_p = p
    return max_p

fn main() raises:
    let str_digits = (
        '73167176531330624919225119674426574742355349194934' +
        '96983520312774506326239578318016984801869478851843' +
        '85861560789112949495459501737958331952853208805511' +
        '12540698747158523863050715693290963295227443043557' +
        '66896648950445244523161731856403098711121722383113' +
        '62229893423380308135336276614282806444486645238749' +
        '30358907296290491560440772390713810515859307960866' +
        '70172427121883998797908792274921901699720888093776' +
        '65727333001053367881220235421809751254540594752243' +
        '52584907711670556013604839586446706324415722155397' +
        '53697817977846174064955149290862569321978468622482' +
        '83972241375657056057490261407972968652414535100474' +
        '82166370484403199890008895243450658541227588666881' +
        '16427171479924442928230863465674813919123162824586' +
        '17866458359124566529476545682848912883142607690042' +
        '24219022671055626321111109370544217506941658960408' +
        '07198403850962455444362981230987879927244284909188' +
        '84580156166097919133875499200524063689912560717606' +
        '05886116467109405077541002256983155200055935729725' +
        '71636269561882670428252483600823257530420752963450')
    
    let args = sys.argv()
    let L = atol(args[1])
    print(f(String(str_digits), L))