Project Euler
프로젝트 오일러 033
이상한 약분이 가능한 분수 찾기
1분
##wordpress
##Import 2024-10-22 00:39
이상한 약분하기
문제에서 예를 든 ‘진부한 경우’가 조금 모호할 수 있습니다. 30/50과 같이 분모와 분자의 1의 자리가 모두 0인 경우만 말하는 것인지, 다른 ‘진부한’ 경우가 있을지를 좀 생각해봐야 합니다. 각 자리 숫자를 a, b, k로 “ak” / “bk”로 표시하는 경우 실제 수는 (10a + k) / (10b + k)이므로, 이 때 같은 숫자를 지웠을 때 비율이 같아지는 것을 만족하는 k는 0밖에 없습니다. 즉 진부한 경우는 분모와 분자의 끝자리가 모두 0인 경우만 해당합니다.
제외해야할 진부한 경우에 대한 정의만 명확하다면 나머지는 매우 간단합니다.
- 기약분수 형태로 비교해야 하는 문제가 있지만,
Fraction을 사용하면 해결됩니다. - 분모 분자에서 같은 숫자는 분모, 분자에서 각각 10의 자리와 1의 자리에 등장할 수 있으므로, 모든 경우를 다 비교해봅니다.
- 제거하고 남은 숫자가 분모에서는 0이면 계산할 수 없으므로 이 부분도 체크해야 합니다.
from fractions import Fraction
from functools import reduce
def test(x: int, y: int) -> bool:
o = Fraction(x, y)
a, b = divmod(x, 10)
c, d = divmod(y, 10)
if 0 < b == d:
# 1의 자리가 같음. 단 0은 안됨
return o == Fraction(a, c)
if b == c and d > 0:
# 분자의 1의 자리와 분모의 10의 자리가 같음
return o == Fraction(a, d)
if a == c and b > 0 and d > 0:
# 분자의 10의 자리와 분모의 10의 자리가 같음
return o == Fraction(b, d)
if 0 < a and a == d and b > 0 and c > 0:
return o == Fraction(b, c)
return False
def main():
res = [Fraction(x, y) for x in range(10, 99) for y in range(x + 1, 100)
if test(x, y)]
print(reduce(lambda x, y: x * y, res).denominator)
main()