読者です 読者をやめる 読者になる 読者になる

methaneのブログ

このブログに乗せているサンプルコードはすべてNYSLです。

PythonでBowling Score

program Python

http://blogs.itmedia.co.jp/hiranabe/2006/11/haskell_bowling_be41.html

ところで、今日発見した、Haskellの例は、大分様相が違う。Haskellのパターンマッチングを利用して、かなり簡便にこの「スコア計算ルール」を、そのまま表現できている、と感じる。言語には得意・不得意があることを改めて感じる瞬間である。

引用元の回答法を、Pythonで再表記するとこうなる。

def calc_score(points):
	if len(points) <= 3: return sum(points)
	if points[0] == 10:
		return sum(points[:3]) + calc_score(points[1:])
	elif points[0] + points[1] == 10:
		return sum(points[:3]) + calc_score(points[2:])
	else:
		return sum(points[:2]) + calc_score(points[2:])

def test(points):
	print points
	print calc_score(points)

if __name__ == '__main__':
	test([0]*20)
	test([10]*12)
	test([10,5,5]+[0]*17)
	test([3]*20)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
0
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
300
[10, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
30
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
60

この解法ですばらしい部分は、Haskellの強力さではない。作者が、ゲーム終端付近のスコア計算を、

if len(throw_points) <= 3: return sum(throw_points)

とできる事に気づいた点である。*1

この例において、言語の強力さはせいぜいリスト処理の強力さ程度*2にしか表れていない。Haskellだからとか、関数型だからとか、パターンマッチングがあるからスマートに解決できたと言われると、違和感を感じる。

*1:プログラマHaskell脳になっていたからこそ気づけた・・・と言えば、Haskellの功績になるかも

*2:リストから部分リストを簡単に抽出できるか