以下の内容はhttps://inamori.hateblo.jp/entry/2024/12/14/163450より取得しました。


MojoでProject Euler 80

https://projecteuler.net/problem=80

2なら 2 \times 10^{200}にして、平方根を取って小数点以下を切り捨てます。

import sys


#################### 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

fn copy_list[T: CollectionElement](a: List[T]) -> List[T]:
    return sublist(a, 0, len(a))

fn sublist[T: CollectionElement](a: List[T], first: Int, last: Int) -> List[T]:
    var b = List[T]()
    for i in range(first, last):
        b.append(a[i])
    return b

fn reverse_list[T: CollectionElement](a: List[T]) -> List[T]:
    var b = List[T]()
    for i in range(len(a) - 1, -1, -1):
        b.append(a[i])
    return b

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


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

@value
struct BigInteger(Stringable):
    var v: List[Int]
    
    fn copy(self) -> BigInteger:
        var v = copy_list(self.v)
        return BigInteger(v)
    
    fn __eq__(self, other: BigInteger) -> Bool:
        if len(self.v) != len(other.v):
            return False
        for i in range(len(self.v)):
            if self.v[i] != other.v[i]:
                return False
        return True
    
    fn __ne__(self, other: BigInteger) -> Bool:
        return not self.__eq__(other)
    
    fn __lt__(self, other: BigInteger) -> Bool:
        if len(self.v) != len(other.v):
            return len(self.v) < len(other.v)
        for i in range(len(self.v)-1, -1, -1):
            if self.v[i] != other.v[i]:
                return self.v[i] < other.v[i]
        return False
    
    fn __gt__(self, other: BigInteger) -> Bool:
        if len(self.v) != len(other.v):
            return len(self.v) > len(other.v)
        for i in range(len(self.v)-1, -1, -1):
            if self.v[i] != other.v[i]:
                return self.v[i] > other.v[i]
        return False
    
    fn __ge__(self, other: BigInteger) -> Bool:
        if len(self.v) != len(other.v):
            return len(self.v) > len(other.v)
        for i in range(len(self.v)-1, -1, -1):
            if self.v[i] != other.v[i]:
                return self.v[i] > other.v[i]
        return True
    
    fn __add__(self, other: BigInteger) -> BigInteger:
        var v = List[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.append(n % 10)
            carry = n // 10
        if carry > 0:
            v.append(carry)
        return BigInteger(v)
    
    # 非負になる前提
    fn __sub__(self, other: BigInteger) -> BigInteger:
        var v = List[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.append(n % 10)
            carry = n // 10
        if v.size > 1 and v[v.size-1] == 0:
            var tmp = v.pop()   # 受けないとwarning
        
        while len(v) > 1 and v[len(v)-1] == 0:
            _ = v.pop(len(v)-1)
        
        return BigInteger(v)
    
    fn __mul__(self, other: Int) -> BigInteger:
        var v = List[Int]()
        var carry = 0
        for d in self.v:
            var n = d[] * other + carry
            v.append(n % 10)
            carry = n // 10
        while carry > 0:
            var r = carry % 10
            carry //= 10
            v.append(r)
        return BigInteger(v)
    
    fn __rmul__(self, other: Int) -> BigInteger:
        return self * other
    
    fn __mul__(self, other: BigInteger) -> BigInteger:
        var L1 = len(self.v)
        var L2 = len(other.v)
        var v = initialize_list(L1 + L2 - 1, 0)
        for i in range(L1):
            for j in range(L2):
                v[i+j] += self.v[i] * other.v[j]
        
        var carry = 0
        for i in range(L1 + L2 - 1):
            v[i] += carry
            carry = v[i] // 10
            v[i] = v[i] % 10
        while carry > 0:
            v.append(carry % 10)
            carry //= 10
        return BigInteger(v)
    
    fn less_than(self, other: BigInteger, offs: Int) -> Bool:
        if len(self.v) != len(other.v) + offs:
            return len(self.v) < len(other.v) + offs
        for i in range(len(other.v)-1, -1, -1):
            if self.v[i+offs] != other.v[i]:
                return self.v[i+offs] < other.v[i]
        return False
    
    fn div(self, other: BigInteger, offs: Int) -> Int:
        for i in range(1, 10):
            if self.less_than(other * i, offs):
                return i - 1
        else:
            return 9
    
    fn shift(self, offs: Int) -> BigInteger:
        var v = List[Int]()
        for _ in range(offs):
            v.append(0)
        for d in self.v:
            v.append(d[])
        return BigInteger(v)
    
    fn __floordiv__(self, other: BigInteger) -> BigInteger:
        var v = List[Int]()
        var dividend = self.copy()
        var offs = len(self.v) - len(other.v)
        if self.less_than(other, offs):
            offs -= 1
        for i in range(offs, -1, -1):
            var d = dividend.div(other, i)
            dividend = dividend - (other * d).shift(i)
            v.append(d)
        return BigInteger(reverse_list(v))
    
    fn __str__(self) -> String:
        if len(self.v) == 0:
            return "0"
        
        var s: String = ""
        for i in range(self.v.size-1, -1, -1):
            if self.v[i] < 10:
                s += chr(self.v[i] + 48)
            else:
                s += chr(self.v[i] + 87)
        return s
    
    @staticmethod
    fn create(owned n: Int) -> BigInteger:
        var v = List[Int]()
        while n > 0:
            var d = n % 10
            n //= 10
            v.append(d)
        return BigInteger(v)


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

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

fn sqrt(n: BigInteger) -> BigInteger:
    var one = BigInteger.create(1)
    var two = BigInteger.create(2)
    var x = (n + one) // two
    while True:
        var x1 = (x + n // x) // two
        if x1 >= x:
            return x
        x = x1

fn f(N: Int, L: Int) -> Int:
    var s = 0
    var r = 1
    for n in range(1, N+1):
        if r * r == n:
            r += 1
            continue
        var big_n = BigInteger.create(n).shift(L * 2 - 2)
        var big_r = sqrt(big_n)
        for d in big_r.v:
            s += d[]
        print(n, s)
    return s

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



以上の内容はhttps://inamori.hateblo.jp/entry/2024/12/14/163450より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14