MojoでProject Euler 29(1)

https://projecteuler.net/problem=29

 a^bなら (a, b)としてダブりを排除します。ただし、 aがべき乗数ならべき乗を外に出します。例えば、 64^2 = 2^{12}とします。
MojoでSetを使うには、KeyElementを継承します。

from collections import Set, KeyElement
import sys


#################### Power ####################

@value
struct Power(KeyElement):
    var b: Int
    var e: Int
    
    fn __init__(inout self, b: Int, e: Int):
        self.b = b
        self.e = e
    
    fn pow(p: Power, e: Int) -> Power:
        return Power(p.b, p.e * e)
    
    fn __hash__(self) -> Int:
        var a = DTypePointer[DType.int8].alloc(2)
        a[0] = self.b
        a[1] = self.e
        var h = hash(a, 2)
        a.free()
        return h
    
    fn __eq__(self, other: Self) -> Bool:
        return self.b == other.b and self.e == other.e
    
    fn __str__(self) -> String:
        return str(self.b) + "^" + str(self.e)


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

fn make_power_table(N: Int) -> DynamicVector[Power]:
    var v = DynamicVector[Power]()
    for n in range(N+1):
        v.push_back(Power(n, 1))
    
    for n in range(2, N+1):
        var b = v[n].b
        var e = v[n].e
        if e != 1:
            continue
        var m = b
        for e1 in range(2, N):
            m *= b
            if m > N:
                break
            v[m] = Power(b, e1)
    return v

fn f(N: Int) -> Int:
    var table = make_power_table(N)
    var s = Set[Power]()
    for n in range(2, N+1):
        var a = table[n]
        for b in range(2, N+1):
            s.add(a.pow(b))
    return len(s)

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