<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>euler / Drkcore</title><link>http://blog.kzfmix.com/euler</link><description>Programming, Music, Snowboarding</description><language>ja</language><lastBuildDate>Tue, 12 Jan 2010 10:48:37 +0919</lastBuildDate><item><title>project eulerをはじめた</title><link>http://blog.kzfmix.com/entry/1219058851</link><description>&lt;p&gt;今日は休日だったので子供の面倒をみつつ、&lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt;をはじめてみた。pythonで解いてる。今日一日で17問程解いたら&lt;a href="http://projecteuler.net/index.php?section=scores&amp;amp;country=Japan&amp;amp;page=2"&gt;japan ranking 200位&lt;/a&gt;丁度になった。&lt;/p&gt;

&lt;p&gt;ちょっと悩んだのはproblem 10で200万以下の素数の総和を求めるという問題。&lt;/p&gt;

&lt;p&gt;最初は素数リストで割り算してみて割り切れるものがなかったら素数リストにappendという単純な方法でやってみたけど、10万くらいで遅くなってしまった。&lt;/p&gt;

&lt;p&gt;というわけで篩で。200万までの奇数リストをつくって篩にかけていく。終了条件は最も大きい素数の二乗が200万を超えるかどうか。
で、できた素数のリストをreduceで畳んでprint&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;numlist = range(3,2000000,2)

def sieve(nums):
    prime_list = [2]
    while 1:
        prime = nums[0]
        prime_list.append(prime)
        if prime * prime &amp;gt; max(nums):
            prime_list = prime_list + nums[1:]
            break
        else:
            nums = [x for x in nums if x%prime != 0]
    return prime_list

print reduce(lambda x,y: x+y, sieve(numlist))
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Tue, 12 Jan 2010 10:48:37 +0919</pubDate><category>Python</category><category>euler</category></item><item><title>pythonでpermutation</title><link>http://blog.kzfmix.com/entry/1219147275</link><description>&lt;p&gt;Project Eulerを解いていくには篩とか素因数分解とか組み合わせ発生用の関数を良く使う。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://code.activestate.com/recipes/190465/"&gt;permutation用のジェネレータ&lt;/a&gt;を見つけた。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def permutations(L):
    if len(L) == 1:
        yield [L[0]]
    elif len(L) &amp;gt;= 2:
        (a, b) = (L[0:1], L[1:])
        for p in permutations(b):
            for i in range(len(p)+1):
                yield p[:i] + a + p[i:]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再帰の中でyieldが使われている場合の動きのイメージがまだピンとこないなぁ。&lt;/p&gt;

&lt;p&gt;それから、インデックスの範囲外は空リストが返ってくるからlispとかhaskellっぽく書けるのか。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; a = [1,2,3,4]
&amp;gt;&amp;gt;&amp;gt; a[1:]
[2, 3, 4]
&amp;gt;&amp;gt;&amp;gt; a[2:]
[3, 4]
&amp;gt;&amp;gt;&amp;gt; a[3:]
[4]
&amp;gt;&amp;gt;&amp;gt; a[4:]
[]
&amp;gt;&amp;gt;&amp;gt; a[5:]
[]
&amp;gt;&amp;gt;&amp;gt; a[:0]
[]
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Tue, 12 Jan 2010 10:47:48 +0919</pubDate><category>Python</category><category>euler</category></item><item><title>Project Euler Problem 48&amp;97</title><link>http://blog.kzfmix.com/entry/1219231860</link><description>&lt;p&gt;大きい数字の下位10桁を求める。桁溢れとかそんなんで数字があわなくなるので、欲しい桁以上の数字は捨てる。48(1^1+2^2...1000^1000)と97(大きい素数)はこれで解ける。&lt;/p&gt;

&lt;h3&gt;Problem 48&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;sum = 0
for i in range(1,1000):
    sum += reduce(lambda x,y: x*y%10000000000,[i] * i)

print sum % 10000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Problem 97&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;def fact2():
    num = 1
    for i in range(7830457):
        num = num * 2 % 10000000000
    return num

print (1 + 28433 * fact2() ) % 10000000000
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Tue, 12 Jan 2010 10:47:34 +0919</pubDate><category>Python</category><category>euler</category></item><item><title>Project Euler lv.1</title><link>http://blog.kzfmix.com/entry/1219235895</link><description>&lt;p&gt;25問解いてレベル1&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.kzfmix.com/images/blog/eulerlv1.png" alt="euler lv.1" /&gt;&lt;/p&gt;

&lt;p&gt;多面体ゲット&lt;/p&gt;
</description><pubDate>Tue, 12 Jan 2010 10:47:22 +0919</pubDate><category>Python</category><category>euler</category></item><item><title>pythonのyield (project euler problem 24)</title><link>http://blog.kzfmix.com/entry/1220357074</link><description>&lt;p&gt;pythonのyieldって呼ばれるとメインに戻ってくるようなイメージがあったので再帰の終了条件でyieldがあると気持ち悪かったのだけど、&lt;a href="http://www.python.jp/doc/2.4/ref/yield.html"&gt;呼び出し側に返される&lt;/a&gt;らしい。&lt;/p&gt;

&lt;p&gt;というわけで、やっと理解したので、再帰でyieldをガンガンつかう。&lt;/p&gt;

&lt;p&gt;あと、状態の凍結と継続の違いがちょっとあやふやかも。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def permute(item):
    if len(item) == 1: yield item
    for i in range(len(item)):
        for x in  permute(item[:i]+item[i+1:]):
            yield item[i] + x

c=0
for i in permute("0123456789"):
    c += 1
    if c == 1000000:
        print i
        break
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Tue, 12 Jan 2010 10:46:54 +0919</pubDate><category>Python</category><category>euler</category></item><item><title>Project Euler Problem 41</title><link>http://blog.kzfmix.com/entry/1221133563</link><description>&lt;p&gt;1からnまでの連続した数をおのおの一つだけ桁にもつ素数のうち最大のものを探せ&lt;/p&gt;

&lt;p&gt;987654321から数を減らしながら素直に見つけていくという安直なコードを書いてサブミット。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import math

def make_primes(n):
    primes = [2]
    nums = range(3,n+1,2)
    while 1:
        prime = nums[0]
        if prime ** 2 &amp;gt; n:
            primes += nums
            return primes
        else:
            primes.append(prime)
            nums = [x for x in nums if x%prime != 0]
    return list(set(primes))

def permute(item):
    if len(item) == 1: yield item
    for i in range(len(item)):
        for x in  permute(item[:i]+item[i+1:]):
            yield item[i] + x

def is_prime(n):
    for j in primes:
        if j*j &amp;gt; n: return True
        if n%j == 0: return False
    return True

if __name__ == "__main__":
    num = 7654321
    primes = make_primes(int(math.sqrt(num)))

    for i in permute(str(num)):
        x = int(i)
        if x%2 != 0:
            if is_prime(x):
                print x
                break
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;それよりも&lt;a href="http://d.hatena.ne.jp/mzp/20080529"&gt;みずぴー日記&lt;/a&gt;のコメントが参考になった。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;「各桁の数を足した和が3の倍数ならその数自身も3の倍数」って性質から、素数のPanditital数はあるとすれば1桁か4桁か7桁に絞られるんじゃないでしょうか。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;えーなんでなんでー？？？？&lt;/p&gt;

&lt;p&gt;&lt;a href="http://questionbox.jp.msn.com/qa2100301.html?StatusCheck=ON"&gt;３の倍数&lt;/a&gt;のANo3をみてなるほどなーと感心した。&lt;/p&gt;
</description><pubDate>Tue, 12 Jan 2010 10:46:25 +0919</pubDate><category>Python</category><category>euler</category></item><item><title>Project Euler Problem 50</title><link>http://blog.kzfmix.com/entry/1221715099</link><description>&lt;p&gt;連続する素数リスト和が素数になるもののうち、100万までのなかからその並びが最も大きいものを探す。&lt;/p&gt;

&lt;p&gt;2,3,5...と和をとって100万までの素数の最大値を超えたところが並びの最大。ここからwindowをずらして和をもとめ素数が見つかったらそれが最大。見つからなかったらwindowサイズを一つ小さくしながら同じ事を繰り返す。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def make_primes(n):
    primes = [2]
    nums = range(3,n+1,2)
    while 1:
        prime = nums[0]
        if prime ** 2 &amp;gt; n:
            primes += nums
            return primes
        else:
            primes.append(prime)
            nums = [x for x in nums if x%prime != 0]
    return primes

def c_sum(i,n):
    return reduce(lambda x,y:x+y,primes[i:i+n+1])

def check_max():
    for i in range(1,len(primes)):
        if c_sum(0,i) &amp;gt; primes[-1]:
            return len(primes[:i])

if __name__ == "__main__":
    primes = make_primes(1000000)
    print "primes are %d" % len(primes)

    cm = check_max()
    print "max windowsize %d" % cm

    max = 0
    pl = cm
    for x in range(1,pl):
        window = pl - x
        print "checking length %d..." % window
        for j in reversed(range(x)):
            num = c_sum(j,window)
            if num in primes:
                max = num
                print num
                print primes[j:j+window+1]
                if max &amp;gt; 0: break
        if max &amp;gt; 0: break
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Thu, 18 Sep 2008 14:18:45 +0919</pubDate><category>euler</category></item><item><title>Project Euler Problem 63&amp;99</title><link>http://blog.kzfmix.com/entry/1221649426</link><description>&lt;h3&gt;problem 63&lt;/h3&gt;

&lt;p&gt;n乗したらn桁がなるような数字はいくつあるか?&lt;/p&gt;

&lt;p&gt;10以上は考えなくてよいのだけど、一応100まで数えてみた。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;count = 0
for i in range(1,100):
    if len(str(i)) &amp;gt; 1: break

    j = 1
    while(1):
        n = i ** j
        if len(str(n)) &amp;lt; j: break
        # print n,i,j
        j += 1
        count += 1

print count
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;problem 99&lt;/h3&gt;

&lt;p&gt;対数変換して比較するだけなのでlog10で。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import math
f = open("base_exp.txt")

n    = 0
max  = 0
maxn = 0
for l in f:
    n += 1
    a,b = l[:-2].split(',')
    x = math.log(int(a)) * int(b)
    if max &amp;lt; x:
        max = x
        maxn = n
print maxn,max
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;これで、&lt;a href="http://projecteuler.net/index.php?section=profile&amp;amp;profile=kzfm"&gt;level2&lt;/a&gt;の六面体に昇進&lt;/p&gt;
</description><pubDate>Wed, 17 Sep 2008 20:05:40 +0919</pubDate><category>euler</category></item><item><title>Project Euler Problem 45</title><link>http://blog.kzfmix.com/entry/1221570655</link><description>&lt;p&gt;Triangle, pentagonal, and hexagonal numbersを同時に満たす数をもとめる。&lt;/p&gt;

&lt;p&gt;Triangleとhexagonalの関係は一個おきだとすぐにわかるので、数字を比較して小さいほうの数をnextさせるようにしてみた。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def tri():
    i = 1
    while(1):
        yield i*(i+1)/2
        i += 2

def penta():
    j = 1
    while(1):
        yield j*(3*j-1)/2
        j += 1

t = tri()
p = penta()

thn = t.next()
pn  = p.next()

while(1):
    if thn &amp;gt; pn:
        pn  = p.next()
    elif pn &amp;gt; thn:
        thn = t.next()
    else:
        print thn
        pn  = p.next()
        thn = t.next()
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Tue, 16 Sep 2008 22:11:39 +0919</pubDate><category>euler</category></item></channel></rss>