Upload
fumihito-yokoyama
View
1.237
Download
0
Embed Size (px)
DESCRIPTION
2011/07/30 発表したスライド sourceは、 https://bitbucket.org/tututen/pysap3.1/
Citation preview
Pythonでやるショートコーディング
momo_*(@tututen)1
2011年7月30日土曜日
自己紹介
2
2011年7月30日土曜日
自己紹介
3
• 北海道北見市在住
• Python歴は約半年
• つまみ食いプログラマ
• お仕事ではC言語でサーバ書き書き
2011年7月30日土曜日
北見ってどこ?
4札幌←→北見間 294km(高速道路を使用しない)
2011年7月30日土曜日
対戦者募集中!
5
• パネルでポン対戦者募集中!!
• ニコニコ代表タグ
• 友達がいないとこうなります
• 人間やめましたシリーズ
2011年7月30日土曜日
ATTENTION
6
2011年7月30日土曜日
お約束
7
• これから書くことはPEP8を無視しています
• 「Pythonっぽくない」かも
• Pythonの基本技術は省くよ!(オライリーが何とかしてくれる)
• 「もっと短く書けるよ」という意見歓迎
2011年7月30日土曜日
ショートコーディングとは?
8
2011年7月30日土曜日
ショートコーディングとは
9
• 「コードゴルフ」というのが一般的
2011年7月30日土曜日
ショートコーディングとは
10
• 「コードゴルフ」というのが一般的
• より少ないバイト数で所与の課題をプログラミングする遊び。より少ない打(鍵)数を競うところがゴルフに似ているところからの命名(hatena keyword 引用)
2011年7月30日土曜日
ショートコーディングとは
11
• 「コードゴルフ」というのが一般的
• より少ないバイト数で所与の課題をプログラミングする遊び。より少ない打(鍵)数を競うところがゴルフに似ているところからの命名(hatena keyword 引用)
• ショートコーディング攻略wikiなるものがある
2011年7月30日土曜日
Pythonでよく言われていること
12
2011年7月30日土曜日
Pythonでは多くのユーザによって書かれた同一の仕事をするプログラムは、だいたいどれも同じようなコードに収束する。(wikipedia 引用)
13
2011年7月30日土曜日
本当に?
14
2011年7月30日土曜日
例:偶数のリスト作成
15
2011年7月30日土曜日
偶数のリスト作成
16
• range(0, max_value, 2)
2011年7月30日土曜日
偶数のリスト作成
17
• range(0, max_value, 2)
• [i * 2 for i in range(num)]
2011年7月30日土曜日
偶数のリスト作成
18
• range(0, max_value, 2)
• [i * 2 for i in range(num)]
• a = []for i in range(num): a.append(i * 2)
2011年7月30日土曜日
いくつも道がある!
19
2011年7月30日土曜日
いくつでも抜け道がある!
20
2011年7月30日土曜日
3目並べ
21
2011年7月30日土曜日
3目並べ
22
• 別称:OXゲーム
• 基礎プログラミングの集大成
• ループ文
• 条件分岐
• 入出力処理
2011年7月30日土曜日
3目並べの流れ
23
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
3目並べの流れ
24
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
フィールドの初期化
25
2011年7月30日土曜日
フィールドの初期化
26
• フィールドをリストで管理
• 1次元、2次元を使用するのは個々人の好みが分れる
• フィールドの中で管理するのは数字か?文字か?
2011年7月30日土曜日
フィールドの初期化
27
• フィールドをリストで管理
• 1次元、2次元を使用するのは個々人の好みが分れる
‣ 私は1次元での管理が好き
• フィールドの中で管理するのは数字か?文字か?
2011年7月30日土曜日
フィールドの初期化
28
• フィールドをリストで管理
• 1次元、2次元を使用するのは個々人の好みが分れる
‣ 私は1次元での管理が好き
• フィールドの中で管理する値は数値か?文字か?
‣ 数値を使用することが多いが、今回は文字を使用
2011年7月30日土曜日
フィールドの初期化
29
• field = []for i in range(9): field.append(‘_‘)
2011年7月30日土曜日
フィールドの初期化
30
• field = []for i in range(9): field.append(‘_‘)
• field = [‘_‘ for i in range(9)]
2011年7月30日土曜日
フィールドの初期化
31
• field = []for i in range(9): field.append(‘_‘)
• field = [‘_‘ for i in range(9)]
• field = [‘_‘] * 9
2011年7月30日土曜日
3目並べの流れ
32
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
フィールドの表示
33
2011年7月30日土曜日
フィールドの表示
34
• 現在の3x3のフィールド
• O or Xのターン表示
‣1と−1で管理する
2011年7月30日土曜日
フィールドの表示
35
• turn = 1for x range(3): for y range(3): print field[x + y * 3], print ‘’if turn == 1: print ‘o turn’else : print ‘x turn’
2011年7月30日土曜日
フィールドの表示
36
• turn = 1for x range(3): for y range(3): print field[x + y * 3], print ‘’if turn == 1: print ‘o turn’else : print ‘x turn’
2011年7月30日土曜日
フィールドの表示
37
• turn = 1print “%s%s%s¥n%s%s%s¥n%s%s%s” % tuple(field)if turn == 1: print ‘o turn’else : print ‘x turn’
2011年7月30日土曜日
フィールドの表示
38
• turn = 1print “%s%s%s¥n%s%s%s¥n%s%s%s” % tuple(field)if turn == 1: print ‘o turn’else : print ‘x turn’
2011年7月30日土曜日
フィールドの表示
39
• turn = 1print “%s%s%s¥n%s%s%s¥n%s%s%s” % tuple(field)marks = ‘_ox’print ‘%s turn’ % marks[turn]
✴marks[1] == ‘o’
✴marks[-1] == marks[2] == ‘x’
2011年7月30日土曜日
3目並べの流れ
40
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
座標入力
41
2011年7月30日土曜日
座標入力
42
• raw_inputでOK
• intにコンバートする必要あり
• エラー処理をどうするか
• 値範囲のチェック(0<=x<=2、 0<=y<=2)
2011年7月30日土曜日
座標入力
43
• while(True): try: x = int(raw_input(‘x(0-2) -> ‘)) y = int(raw_input(‘y(0-2) -> ‘)) except: continue if 0 <= x <= 2 and 0 <= y <= 2: break
2011年7月30日土曜日
座標入力
44
• while(True): try: x = int(raw_input(‘x(0-2) -> ‘)) y = int(raw_input(‘y(0-2) -> ‘)) except: continue if 0 <= x <= 2 and 0 <= y <= 2: break
2011年7月30日土曜日
座標入力
45
• while(True): inp = lambda n: raw_input(‘%s(0-2) -> ‘%n) x, y = inp(‘x’), inp(‘y’) try: x = int(x) y = int(y) except: continue vr = lambda n: 0 <= n <= 2 if vr(x) and vr(y): break
2011年7月30日土曜日
座標入力
46
• while(True): inp = lambda n: raw_input(‘%s(0-2) -> ‘%n) x, y = inp(‘x’), inp(‘y’) vr = lambda n: 0 <= n <= 2 if vr(x) and vr(y): break try: x = int(x) y = int(y) except: continue
2011年7月30日土曜日
座標入力
47
• while(True): inp = lambda n: raw_input(‘%s(0-2) -> ‘%n) x, y = inp(‘x’), inp(‘y’) vr = lambda n: len(n)==1 and ‘0’ <= n <= ‘2’ if vr(x) and vr(y): breaktry: x = int(x) y = int(y)except: continue
2011年7月30日土曜日
座標入力
48
• while(True): inp = lambda n: raw_input(‘%s(0-2) -> ‘%n) x, y = inp(‘x’), inp(‘y’) vr = lambda n: len(n)==1 and ‘0’ <= n <= ‘2’ if vr(x) and vr(y): breaktry: x = int(x) y = int(y)except: continue
2011年7月30日土曜日
座標入力
49
• while(True): inp = lambda n: raw_input(‘%s(0-2) -> ‘%n) x, y = inp(‘x’), inp(‘y’) vr = lambda n: len(n)==1 and ‘0’ <= n <= ‘2’ if vr(x) and vr(y): breakx, y = int(x), int(y)
2011年7月30日土曜日
座標入力
50
• inp = lambda n: raw_input(‘%s(0-2) -> ‘%n)vr = lambda n: len(n)==1 and ‘0’ <= n <= ‘2’while(True): x, y = inp(‘x’), inp(‘y’) if vr(x) and vr(y): breakx, y = int(x), int(y)
2011年7月30日土曜日
座標入力
51
• while(True): try: x = int(raw_input(‘x(0-2) -> ‘)) y = int(raw_input(‘y(0-2) -> ‘)) except: continue if 0 <= x <= 2 and 0 <= y <= 2: break
2011年7月30日土曜日
座標入力
52
• inp = lambda n: raw_input(‘%s(0-2) -> ‘%n)vr = lambda n: len(n)==1 and ‘0’ <= n <= ‘2’while(True): x, y = inp(‘x’), inp(‘y’) if vr(x) and vr(y): breakx, y = int(x), int(y)
2011年7月30日土曜日
3目並べの流れ
53
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
マスにマーク(O or X)が置けるか
54
2011年7月30日土曜日
マスのチェック
55
• 指定した座標に空白があるかどうか
• すでに置かれていたら座標入力からやり直す
2011年7月30日土曜日
マスのチェック
56
• if field[x + y * 3] != ‘_’: continue
2011年7月30日土曜日
マスのチェック
57
• if field[x + y * 3] != ‘_’: continue
• フィールドは各一文字なのでif field[x + y * 3] - ‘_’: continueとか、出来ますが、この辺は最後のチューニングで
2011年7月30日土曜日
マスのチェック
58
• if field[x + y * 3] != ‘_’: continue
• フィールドは各一文字なのでif field[x + y * 3] - ‘_’: continueとか、出来ますが、この辺は最後のチューニングで
• 短くなる方法募集!
2011年7月30日土曜日
3目並べの流れ
59
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
勝利判定
60
2011年7月30日土曜日
勝利判定
61
• 8ラインの3要素ずつ比較する
• すべての値が同一場合、置いた人の勝利(スペースは除く)
2011年7月30日土曜日
勝利判定
62
• 8ラインの3要素ずつ比較する
• すべての値が同一場合、置いた人の勝利(スペースは除く)
• 勝利判定を制するコードゴルファーは、OXゲームを制す
2011年7月30日土曜日
なぜ難しい?
63
• ループで回すのが難しい
0 1 2
3 4 5
6 7 8
0,1,23,4,56,7,80,3,61,4,72,5,80,4,82,4,6
2011年7月30日土曜日
なぜ難しい?
64
• ループで回すのが難しい
0 1 2
3 4 5
6 7 8
0,1,23,4,56,7,80,3,61,4,72,5,80,4,82,4,6
n,n+1,n+2
n,n+3,n+6
????
2011年7月30日土曜日
なぜ難しい?
65
• ループで回すのが難しい
0 1 2
3 4 5
6 7 8
0,1,23,4,56,7,80,3,61,4,72,5,80,4,82,4,6
n,n+1,n+2
n,n+3,n+6
????
わからん!
2011年7月30日土曜日
なぜ難しい?
66
• ループで回すのが難しい
0 1 2
3 4 5
6 7 8
0,4,81,4,72,4,63,4,50,1,26,7,80,3,62,5,8
n,4,8-n
n,n+1,n+2
n,n+3,n+6
2011年7月30日土曜日
なぜ難しい?
67
• ループで回すのが難しい
0 1 2
3 4 5
6 7 8
0,4,81,4,72,4,63,4,50,1,26,7,80,3,62,5,8
n,4,8-n
n,n+1,n+2
n,n+3,n+6
要素数が合わない!
2011年7月30日土曜日
解決策
68
• 調べるラインを増やす(重複部分をつくる)
0 1 2
3 4 5
6 7 8
0,4,81,4,72,4,60,1,23,4,56,7,80,3,61,4,72,5,8
n,4,8-n
n,n+1,n+2
n,n+3,n+6
2011年7月30日土曜日
勝利判定
69
• for i in range(3): if (field[i] != ‘_’ and field[i] == field[i + 1] and field[i] == field[i + 2]): judge = True if (field[4] != ‘_’ and field[4] == field[i] and field[4] == field[8 - i]): judge = True...
2011年7月30日土曜日
勝利判定
70
• for i in range(3): if (field[i] != ‘_’ and field[i] == field[i + 1] and field[i] == field[i + 2]): judge = True if (field[4] != ‘_’ and field[4] == field[i] and field[4] == field[8 - i]): judge = True...
2011年7月30日土曜日
勝利判定
71
• mark = ‘ ox’[turn]for i in range(3): if [mark]*3 == [field[i], field[i+1],field[i+2]]: judge = True if [mark]*3 == [field[i],field[4],field[8-i]]: judge = True if [mark]*3 == [field[i], field[i+3],field[i+6]]: judge = True...
2011年7月30日土曜日
勝利判定
72
• mark = ‘ ox’[turn]jl = lambda line: [mark]*3 == linefor i in range(3): if jl([field[i], field[i+1],field[i+2]]): judge = True if jl([field[i],field[4],field[8-i]]): judge = True if jl([field[i], field[i+3],field[i+6]]): judge = True...
2011年7月30日土曜日
勝利判定
73
• mark = ‘ ox’[turn]jl = lambda line: [mark]*3 == linefor i in range(3): if jl([field[i], field[i+1],field[i+2]]): judge = True if jl([field[i],field[4],field[8-i]]): judge = True if jl([field[i], field[i+3],field[i+6]]): judge = True...
2011年7月30日土曜日
勝利判定
74
• mark = ‘ ox’[turn]jl = lambda line: [mark]*3 == linefor i in range(3): if jl(field[i*3:i*3+3]): judge = True if jl(field[i:9-i:4-i]): judge = True if jl(field[i::3]): judge = True
2011年7月30日土曜日
勝利判定
75
• mark = ‘ ox’[turn]jl = lambda line: [mark]*3 == linejudge = Falsefor i in range(3): judge = judge or jl(field[i*3:i*3+3]) judge = judge or jl(field[i:9-i:4-i]) judge = judge or jl(field[i::3])
2011年7月30日土曜日
3目並べの流れ
76
• フィールド初期化• フィールド表示• 座標入力• マスにマーク(O or X)が置けるか• 縦横斜に同じマークが3つ並んでるか• 余白はまだあるか• 次ターンに移行• ゲームの結果を表示
{ここでル|プ
2011年7月30日土曜日
余白の判定
77
2011年7月30日土曜日
余白の判定
78
• for 文で回して、if 文で空白を見つけたら、ループを抜ける
2011年7月30日土曜日
余白の判定
79
• for 文で回して、if 文で空白を見つけたら、ループを抜ける
• とかやっちゃうと、駆け出しPythonista
ということが。。。
2011年7月30日土曜日
余白の判定
80
• space_flag = Falsefor val in field: if val == ‘_’: space_flag = Trueif not space_flag: break
2011年7月30日土曜日
余白の判定
81
• space_flag = Falsefor val in field: if val == ‘_’: space_flag = Trueif not space_flag: break
2011年7月30日土曜日
余白の判定
82
• space_flag = Falsefor val in field: if val == ‘_’: space_flag = Trueif not space_flag: break
• if not ‘_’ in field: break
2011年7月30日土曜日
ターンの移行
83
2011年7月30日土曜日
ターンの移行
84
• ここはマスの空白判定同様書くことがない
• 数字(1,ー1)でターン保持
‣ turn*=-1
‣ turn=-turn
2011年7月30日土曜日
ターンの移行
85
• ここはマスの判定同様書きようがない
• 数字(1,ー1)でターン保持
‣ turn*=-1
‣ turn=-turn
‣ t*=-1
‣ t=-t
2011年7月30日土曜日
ゲームの結果表示
86
2011年7月30日土曜日
ゲームの結果表示
87
• judgeのフラグで引き分けかそれ以外かを見極める
• 勝敗判定時に使ったmarkを使うと良い
2011年7月30日土曜日
ゲームの結果表示
88
• if judge: print ‘%s win’ % markelse: print ‘draw’
2011年7月30日土曜日
ゲームの結果表示
89
• if judge: print ‘%s win’ % markelse: print ‘draw’
• print (‘%s win’ % mark) if judge else ‘draw’
2011年7月30日土曜日
短くなったソース
90
• まずはじめに、Pythonの基本機能をそれほど使って無いソースを見てみましょう。
2011年7月30日土曜日
短くなったソース
91
• まずはじめに、Pythonの基本機能をそれほど使って無いソースを見てみましょう。
• 次に、これらのコーディングを駆使したソースコードを見てみましょう。
2011年7月30日土曜日
短くなったソース
92
• まずはじめに、Pythonの基本機能をそれほど使って無いソースを見てみましょう。
• 次に、これらのコーディングを駆使したソースコードを見てみましょう。
• さぁ、これで君も立派なコードゴルファーだ
2011年7月30日土曜日
Fin
93
2011年7月30日土曜日