Problem 57 - Project Euler

30分プログラム、その334。Problem 57 - Project Euler

2の平方根は無限に続く連分数で表すことができる.

√ 2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213...

最初の4回の繰り返しを展開すると以下が得られる.

  • 1 + 1/2 = 3/2 = 1.5
  • 1 + 1/(2 + 1/2) = 7/5 = 1.4
  • 1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...
  • 1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...

次の3つの項は99/70, 239/169, 577/408である. 第8項は1393/985である. これは分子の桁数が分母の桁数を超える最初の例である.

最初の1000項を考えたとき, 分子の桁数が分母の桁数を超える項はいくつか?

そのまま書いて走らせたら、980項付近で"RuntimeError: maximum recursion depth exceeded in cmp"って言われた。あともう少し頑張ってくれてもいいのに。

使い方

$ python problem57.py

ソースコード

#! /usr/bin/python
# -*- mode:python; coding:utf-8 -*-
#
# problem57.py -
#
# Copyright(C) 2008 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2008/07/06 22:51:36
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#
from math import log10 

def gcd(n,m):
    if m == 0:
        return n
    else:
        return gcd(m,n % m)

class Ratio():
    def __init__(self,num,denom=1):
        n = gcd(num,denom)
        self.num = num/n
        self.denom = denom/n

    def __add__(self,other):
        return Ratio(self.num*other.denom+other.num*self.denom,
                        self.denom * other.denom)

    def __div__(self,other):
        return Ratio(self.num*other.denom,
                     self.denom*other.num)

    def __repr__(self):
        return "%s/%s" % (self.num,self.denom)


memo = {}
def makeFrac(n):
    if n in memo:
        return memo[n]
    elif n == 0:
        return Ratio(0)
    else:
        return Ratio(1) / (Ratio(2,1)+makeFrac(n-1))

def makeNum(n):
    return Ratio(1)+makeFrac(n)

def isSatisfy(r):
    return int(log10(r.num)) > int(log10(r.denom))

count = 0
for n in xrange(1,1001):
    if isSatisfy(makeNum(n)):
        count += 1
        print n

print "answer:",count