Project Euler 504 Square on the Inside

projecteuler.net

1<=a,b,c,d<=mに対して(a,0)(0,b)(-c,0)(0,-d)で囲まれた四角形内部の格子点の個数(境界を含まない)は
{\displaystyle
\frac{ab+bc+cd+da-gcd(a,b)-gcd(b,c)-gcd(c,d)-gcd(d,a)}{2}+1
}

証明:
例えばa=4,b=2として下の図形を考える.
f:id:umashika5555:20161123014957p:plain
まずa*bの長方形の格子点の個数を考える.すると(x軸の点5個)*(y軸の点3個)=15個である.
これは(a+1)*(b+1)を計算している.
次に境界線上の点を数える. この直線上で格子点を通るのはgcd(a,b)+1個.
これらを同様に全てに適応すると
{\displaystyle
\frac{(a+1)(b+1)-gcd(a,b)-1+(b+1)(c+1)-gcd(b,c)-1+\\(c+1)(d+1)-gcd(c,d)-1+(d+1)(a+1)-gcd(d,a)-1}{2}\\-(a+b+c+d)+1
}

 -(a+b+c+d)+1は重複して数えている点を1回分引いている. それだけだと原点が入らなくなるので+1


参考にしたページ
examist.jp

Project Euler 345 Matrix Sum

N-Queen問題の斜め無い版(N-飛車問題?,N-ルーク問題?)のアルゴリズムで考えられうる盤面を全て用意しそのマスに配置された数字の合計の中で最大のモノを探せばよい.

サンプルの5*5盤面では1秒以内で出来たが15*15では時間がかかって出来なかった.

もっと早いアルゴリズムを考え中.

gist.github.com

追記 : すぐ

itertools.permutaionsを使えば上のように考える必要なかった.

Project Euler 145 How many reversible numbers are there below one-billion?

projecteuler.net

 単純な解放

奇数の判定はビット演算を計算する.

n&1==1ならnは奇数, (not n&1)==1ならnは偶数

 

d.hatena.ne.jp

↑参考にしたい解答

 

gist.github.com

 

 

Project Euler 329 Prime Frog

projecteuler.net

Pythonで分数型を用いたいときは

fractions.Fraction(分子,分母)で出来る.

 

1. 500以下の全てのマスを素数素数でないか区別する.

 

2. 次にマスが素数であれば"P"と鳴く確率は2/3, "N"と鳴く確率は1/3

 マスが素数でなければ"P"と鳴く確率は1/3, "N"と鳴く確率は2/3

 これを辞書に記憶しておく.

 d=dict()

 d[(5,"P")]=Fraction(2,3)   d[(5,"N")]=Fraction(1,3)

 d[(6,"P")]=Fraction(1,3) d[(6,"N")]=Fraction(2,3)みたいに

 

3. あるマスi に関してそのマスから始めたときに"string"と鳴く確率を求める

 メモ化再帰を用いる.

 マスが1なら右しかいけないのでPr=d[(1,string[0])]*func(i+1,string[1:])

 マスが500なら左しかいけないのでPr=d[(500,string[0])]*func(i-1,string[1:])

 マスが2~499なら左右どちらもいけるので

 Pr=d[(i,string[0])]*( func(i+1,string[1:])*0.5 + func(i-1,string[1:])*0.5) )である

 これはiマスでstrnigの先頭一文字目("P","N")の確率*(二文字目以降の確率)である.

 2~499では左右どちらかに行くのに0.5の確率を考慮する.

 

gist.github.com

 

Pythonチュートリアルまとめ

Pythonチュートリアル(Python2.x対応)で自分が知らなかったこと, なんとなくは知っていたけど使っていなかった知識で特に重要そうなものをメモしておく.

 

dir()関数

>>>import sys

>>>dir(sys)

sysモジュールがどのような名前を定義しているのかを確認できる

 

例外の処理

>>>while True:

          try:

             x = int(input())

             break

          except ValueError:

             print("数字を入力しろ")

入力として数字を入力すればbreakでwhile文が終わるが, 例えば文字列を入力するとint()へ変換できずValueErrorが生じるtry文はエラーが生じた地点でexcept文へ移動しexcept 文のオプションValueErrorと今回出たエラー(ValueError)と比較一致していたら,except文を実行する.

except(RuntimeError, TypeError, detail)のようにエラー処理を複数指定できる.

 

クリーンアップ

def divide(x,y):

  try:

    result = x/y

  except ZeroDevisionError:

    print("ゼロで割った")

  else:

    print(result)

  finally:

    print("finally")

 

>>>division(2,1)

2 ←エラー処理でない∧ZeroDivisionErrorでもない(当たり前)のでelse文が実行

finally ←finallyが実行

>>>division(2,0)

ゼロで割った  ←ZeroDivisionErrorが実行

finally  ←finallyが実行

>>>division("2","0")

finally ←"2"/"0"は出来ないのでエラーが出てtry文から抜けて例外処理へ, ZeroDivisionErrorでないelseは実行されないfinallyへ

エラーの文がつらつら

 

ジェネレータ

def reverse(string):

    for i in range(len(string)-1,-1,-1):

      yield string[i]

 

>>>for c in reverse('vocky')

          print(c,end="")

ykcov

これはreverse('vocky')で

'vocky'[4]

'vocky'[3]

'vocky'[2]

'vocky'[1]

'vocky'[0]

の順でcに入るということ

 

 

5puzzle

ゲーム理論の課題でA*探索を実装した.

↓コード

gist.github.com

 

↓実行結果

f:id:umashika5555:20161030020036p:plain

紙とペンを使って実行したもの同じになった.

g:=世代 h:=盤面Aの各マスの盤面Goalへのマンハッタン距離の和 f:=h+g

として[f,g,"前回に移動した向き",盤面]のデータ構造でPriority-Queueを用いて求めた.

 

実装している中で幾つか重要なことに気づいた.

1. Python のPriority-Queueは小さいものから出ていく.

 C++は大きいものからだったようなきがする. 大きい順に出したいときは-1倍して入れれば良い.

2. リストのスコープについて

 f:id:umashika5555:20161030020722p:plain

このコードの実行結果は

 f:id:umashika5555:20161030020752p:plain

こうなる. C++とかだと関数内だけにしか適用されないのでこのミスに1時間程気づかず痛い目を見た.

もとのリストに変更を加えずリストの要素をいじりたいときは B=list(A)のようにして新たなリストBをつくるとよい. B=Aとしてしまうと, BはAを参照するという意味になってしまいBも同じく変化してしまう.

 

ex) 

>>>A=[1,2,3,4]

>>>B=A

>>>C=list(A)

>>>A[0]="a"  #リストの要素をいじる

>>>A

["a",2,3,4]

>>>B

["a",2,3,4]  #Aと同じ

>>>C

[1,2,3,4]  #変化しない(オリジナルのA)

>>>A=[5,6,7,8]  #新たなリストの定義, 要素をいじってるわけではない

>>>B

["a",2,3,4]  #Bはそのまま

 

Python(5)

【リストのメソッド】

  • append(x) 
  • extend(L): リストの末尾に与えられたリストL全アイテムを追加する
  • insert(i,x): リストA[i]にxを挿入する
  • pop([i]): A[i]を返す, A[i]はなくなる
  • index(x): 最初にあるxのインデックスを返す
  • count(x)
  • sort()
  • reverse()