https://projecteuler.net/problem=86
ä¾ã ã¨ãã¾ãã辺ã5ã¨3ã ãã8ã§ã6ã¨ç´è§ã«ãªã£ã¦æ辺ã10ã¨ãªãã¾ããç´æ¹ä½ã®æãé·ã辺ãç´è§ä¸è§å½¢ã®ä¸ã¤ã®è¾ºã§æ®ãã®è¾ºã®åã§ç´è§ãæãã¾ãã
ãªã®ã§ãç´è§ä¸è§å½¢ãæãé·ã辺ã«ãªãé·ããå°ããã»ãããåæããã¨ããã§ãããã®éã(3, 4, 5), (4, 3, 5)ã¨åãç´è§ä¸è§å½¢ã§ãã©ã¡ããç´æ¹ä½ã®æãé·ã辺ã«ãªããã§åããã¨çµã¿ããããªãã¾ãã
import sys #################### library #################### fn gcd(n: Int, m: Int) -> Int: if m == 0: return n else: return gcd(m, n % m) #################### HeapQueue #################### struct HeapQueue[T: ComparableCollectionElement]: var a: List[T] fn __init__(inout self): self.a = List[T]() fn is_empty(self) -> Bool: return len(self.a) == 0 fn pop(inout self) -> T: var top = self.a[0] self.a[0] = self.a.pop() var N = self.a.size var i = 0 while i < N-1: var j1 = i*2+1 var j2 = i*2+2 var j: Int = 0 if j1 >= N: break elif j2 == N: j = j1 else: if self.a[j1] <= self.a[j2]: j = j1 else: j = j2 if self.a[j] < self.a[i]: self.swap(i, j) i = j else: break return top fn push(inout self, e: T): self.a.append(e) var i = self.a.size - 1 while i > 0: var j = (i-1) // 2 if self.a[j] <= self.a[i]: break else: self.swap(i, j) i = j fn swap(inout self, i: Int, j: Int): var tmp = self.a[i] self.a[i] = self.a[j] self.a[j] = tmp^ #################### RightTriangle #################### @value struct RightTriangle(Comparable): var l: Int var m: Int var n: Int var is_b: Bool # 2lmnã対象ã fn a(self) -> Int: return self.l * (self.m**2 - self.n**2) fn b(self) -> Int: return 2 * self.l * self.m * self.n fn value(self) -> Int: return self.b() if self.is_b else self.a() fn __lt__(self, other: RightTriangle) -> Bool: return self.value() < other.value() fn __le__(self, other: RightTriangle) -> Bool: return self.value() <= other.value() fn __eq__(self, other: RightTriangle) -> Bool: return self.value() == other.value() fn __ne__(self, other: RightTriangle) -> Bool: return self.value() != other.value() fn __gt__(self, other: RightTriangle) -> Bool: return self.value() > other.value() fn __ge__(self, other: RightTriangle) -> Bool: return self.value() >= other.value() #################### process #################### fn nexts(tri: RightTriangle) -> List[RightTriangle]: var tris = List[RightTriangle]() tris.append(RightTriangle(tri.l+1, tri.m, tri.n, tri.is_b)) if tri.l > 1: pass elif tri.is_b: if tri.n <= 2: tris.append(RightTriangle(1, tri.m+2, tri.n, True)) for n in range(tri.n+2, tri.m, 2): if gcd(tri.m, n) == 1: tris.append(RightTriangle(tri.l, tri.m, n, True)) break else: if tri.n == tri.m - 1 and tri.m >= 3: tris.append(RightTriangle(1, tri.m+1, tri.n+1, False)) for n in range(tri.n-2, 0, -2): if gcd(tri.m, n) == 1: tris.append(RightTriangle(tri.l, tri.m, n, False)) break return tris fn count_cuboids(tri: RightTriangle) -> Int: if tri.is_b: if tri.b() > tri.a(): return tri.a() // 2 else: return max(0, tri.a() // 2 - (tri.a() - tri.b() - 1)) else: if tri.a() > tri.b(): return tri.b() // 2 else: return max(0, tri.b() // 2 - (tri.b() - tri.a() - 1)) fn f(N: Int) -> Int: var counter = 0 var pq = HeapQueue[RightTriangle]() pq.push(RightTriangle(1, 2, 1, True)) pq.push(RightTriangle(1, 2, 1, False)) pq.push(RightTriangle(1, 3, 2, True)) pq.push(RightTriangle(1, 3, 2, False)) var M = 0 while counter < N: var tri = pq.pop() var a = tri.a() var b = tri.b() counter += count_cuboids(tri) M = tri.value() var tris = nexts(tri) for tri1 in tris: pq.push(tri1[]) return M fn main() raises: var args = sys.argv() var N = atol(args[1]) print(f(N))