プログラミングのカリキュラムを勝手に作ろうぜ☆（＾ｑ＾）

プログラマーとは、考古学なのか。　目の前に進むのではなく、他人が作ったソースを理解するのが仕事になる。
今日やるのは　Python 2.7 (32bit)。　わたしの書き方は Python 3+ とごじゃまぜになっている。

# 1. ハローワールド。

定番。

C:\MuzudhoDrive\projects_python\hello.py

```python:
### この書き方は Python 3 用で、うまく動いたのは　引数が１個だったから　らしい。
print("Hello, world!!!")

### 2.7ではこう書くらしい。
### print "Hello, world!!!"
```


からの

```terminal:
C:\Program Files (x86)\pgAdmin 4\v3\web>cd C:\MuzudhoDrive\projects_python

C:\MuzudhoDrive\projects_python>python hello
python: can't open file 'hello': [Errno 2] No such file or directory

C:\MuzudhoDrive\projects_python>python hello.py
Hello, world!!!
```

これは瞬殺。

# 2. for文で定番のあれ。 単一行コメント、複数行コメント。

```python:
'''
Multiline comment.
'''
for i in range(10):
	for j in range(i):
		print("*"), # Comma except new line.
	print("")
```

```terminal:
C:\MuzudhoDrive\projects_python>python for.py

*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
```

プログラミング界のラテン言語の　C言語　から入ると　なんだか　わけわからん風習感ある。

# 3. 連想配列、またはディクショナリ型。

```python:
"""
Free format in parenthesis.
"""
fruits = 	{	"apple": 0,
				"banana": 1,
				"casava": 2 # キャッサバ（芋）はフルーツではないらしい。foods の方が良かった。
			}
print("It is a "),
print(fruits["apple"]),
print(".")
print("It is a "),
print(fruits["banana"]),
print(".")
print("It is a "),
print(fruits["casava"]),
print(".")
```

print文連打つら……。

- コメントをもらったぜ。数を 0, 1, 2 とかにするより　98, 198, 298 みたいな値段にして ~~a 98 Yen~~（値段の前の冠詞は不要）  98 Yen. と表示する方が　覚えやすいよな。


```terminal:

C:\MuzudhoDrive\projects_python>python dictionary.py
It is a  0 .
It is a  1 .
It is a  2 .
```

- It is 98 Yen. みたいに改造して遊べだぜ。

# 4. 配列と、書式付き文字列。

```python:
fruits = 	[	"apple",
				"banana",
				"casava" # キャッサバ（芋）はフルーツではないらしい。foods の方が良かった。
			]

print("This is a {}. That is a {}. It is a {}.".format(fruits[0], fruits[1], fruits[2]))
```

書式付き文字列は C# にも Java にも JavaScript にも Rust にもある。

```terminal:

C:\MuzudhoDrive\projects_python>python format.py
This is a apple. That is a banana. It is a casava.
```

複雑なことの方が習得容易で、簡単なことほど習得困難なのは　コンピューターもそう思っている。


# 5 Fizz Buzz と if-else文 と日本語UTF-8対応。

むずかしいので　簡単なルールに変えて、やる。

```
# coding: utf-8
'''
改造版 Fizz Bazz
	0 から自然数を数えていくが、
	3 で割り切れる場合は 「cat」、
	5 で割り切れる場合は 「human」、
	3と5のどちらでも割り切れる場合は 「catman」 と言うこと。
'''

for i in range(0,100):
	if (i==0):
		print(i),
	elif (i%15==0):
		print("catman"),
	elif (i%3==0):
		print("cat"),
	elif (i%5==0):
		print("human"),
	else:
		print(i),
```

```
C:\MuzudhoDrive\projects_python>python fizz-buzz.py
0 1 2 cat 4 human cat 7 8 cat human 11 cat 13 14 catman 16 17 cat 19 human cat 22 23 cat human 26 cat 28 29 catman 31 32 cat 34 human cat 37 38 cat human 41 cat 43 44 catman 46 47 cat 49 human cat 52 53 cat human 56 cat 58 59 catman 61 62 cat 64 human cat 67 68 cat human 71 cat 73 74 catman 76 77 cat 79 human cat 82 83 cat human 86 cat 88 89 catman 91 92 cat 94 human cat 97 98 cat
```

ここらへんは　まだ簡単。


# 6 バブルソート

バブルソートから　べつに得られる新たな知見もないが、ソートの中で説明が簡単なので一応やっておこう。

```
# coding: utf-8
'''
バブルソート
	0. ばらばらな数字を横一列に10個ならべ、交換マンは左端の数のところに居る。
	1. 左端から、右隣と比べて　左の方が小さければ　左右交換する。
	2. 交換マンは左に１個移動し、(1)を行う。これを交換マンは 右端-1番目まで繰り返す。
	3. ２週目は交換マンは左端に戻り、右端-2番目まで (1)～(2)を繰り返す。
	4. 交換マンのスタート地点が　右端-1 番目になるまで繰り返す。
'''

ball = [9,8,7,6,5,4,3,2,1,0]

for round in range(0,9):
	for line in range(0,9-round):
		if (ball[line] > ball[line+1]):
			temp = ball[line]
			ball[line] = ball[line+1]
			ball[line+1] = temp
        ### 下行は print("{} {} {}".format(round, line, ball)) という書き方があるようだぜ。
		print("{} {} [{},{},{},{},{},{},{},{},{},{}]".format(round, line, ball[0], ball[1], ball[2], ball[3], ball[4], ball[5], ball[6], ball[7], ball[8], ball[9]))
	print("Go back!")
print("Finished.")
```

アルゴリズムは、C言語でも Javaでも Rustでも同じなので　言語が変わっても　文法が違うぐらいしか感じない。


```
C:\MuzudhoDrive\projects_python>python bubble.py
0 0 [8,9,7,6,5,4,3,2,1,0]
0 1 [8,7,9,6,5,4,3,2,1,0]
0 2 [8,7,6,9,5,4,3,2,1,0]
0 3 [8,7,6,5,9,4,3,2,1,0]
0 4 [8,7,6,5,4,9,3,2,1,0]
0 5 [8,7,6,5,4,3,9,2,1,0]
0 6 [8,7,6,5,4,3,2,9,1,0]
0 7 [8,7,6,5,4,3,2,1,9,0]
0 8 [8,7,6,5,4,3,2,1,0,9]
Go back!
1 0 [7,8,6,5,4,3,2,1,0,9]
1 1 [7,6,8,5,4,3,2,1,0,9]
1 2 [7,6,5,8,4,3,2,1,0,9]
1 3 [7,6,5,4,8,3,2,1,0,9]
1 4 [7,6,5,4,3,8,2,1,0,9]
1 5 [7,6,5,4,3,2,8,1,0,9]
1 6 [7,6,5,4,3,2,1,8,0,9]
1 7 [7,6,5,4,3,2,1,0,8,9]
Go back!
2 0 [6,7,5,4,3,2,1,0,8,9]
2 1 [6,5,7,4,3,2,1,0,8,9]
2 2 [6,5,4,7,3,2,1,0,8,9]
2 3 [6,5,4,3,7,2,1,0,8,9]
2 4 [6,5,4,3,2,7,1,0,8,9]
2 5 [6,5,4,3,2,1,7,0,8,9]
2 6 [6,5,4,3,2,1,0,7,8,9]
Go back!
3 0 [5,6,4,3,2,1,0,7,8,9]
3 1 [5,4,6,3,2,1,0,7,8,9]
3 2 [5,4,3,6,2,1,0,7,8,9]
3 3 [5,4,3,2,6,1,0,7,8,9]
3 4 [5,4,3,2,1,6,0,7,8,9]
3 5 [5,4,3,2,1,0,6,7,8,9]
Go back!
4 0 [4,5,3,2,1,0,6,7,8,9]
4 1 [4,3,5,2,1,0,6,7,8,9]
4 2 [4,3,2,5,1,0,6,7,8,9]
4 3 [4,3,2,1,5,0,6,7,8,9]
4 4 [4,3,2,1,0,5,6,7,8,9]
Go back!
5 0 [3,4,2,1,0,5,6,7,8,9]
5 1 [3,2,4,1,0,5,6,7,8,9]
5 2 [3,2,1,4,0,5,6,7,8,9]
5 3 [3,2,1,0,4,5,6,7,8,9]
Go back!
6 0 [2,3,1,0,4,5,6,7,8,9]
6 1 [2,1,3,0,4,5,6,7,8,9]
6 2 [2,1,0,3,4,5,6,7,8,9]
Go back!
7 0 [1,2,0,3,4,5,6,7,8,9]
7 1 [1,0,2,3,4,5,6,7,8,9]
Go back!
8 0 [0,1,2,3,4,5,6,7,8,9]
Go back!
Finished.
```

慣れてくると多分　.sort(ball) とか書くだけで　勝手にやってくれるのだろう。
アルゴリズムなんて　覚えなくていいじゃん、という人は　オーダーを覚えよう。


#7 乱数と数当てゲーム、標準入出力

これも定番中の定番、大定番。　バイナリサーチを覚えてしまうと瞬殺だが　そんなことは気にしない。
標準入出力は Python でどう書くのか調べよう。

「数当てゲーム」
http://www.tsg.ne.jp/TT/tsg/c/mansaku/P02.html

「Pythonで競技プログラミングする時に知っておきたいtips(入出力編)」
https://qiita.com/lethe2211/items/6cbade2bc547649bc040

```
# coding: utf-8
'''
数当てゲーム
	0. 0～99 のうち、どれか１つをコンピューターが選んで隠しておく。
	1. プレイヤーは、0～99 の数を 1つ入力し、コンピューターが隠している数を当てる。
	2. 外れたら、入力した数が　コンピューターの隠している数より小さいか、大きいかだけのヒントをくれる。
	3. 計10回　挑戦できる。
'''

import random

seacret = random.randint(0,99)

print("Please, input a number.")
for round in range(0,9):
	n = input()
	if (seacret == n):
		print("Perfect!")
		break
	elif (n < seacret):
		print("It's small.")
	elif (seacret < n):
		print("It's big.")
	print("Please, retry input a number.")
print("Finished.")
```

乱数というライブラリをインポートすることを覚えた。

```
C:\MuzudhoDrive\projects_python>python number-guessing.py
Please, input a number.
10
It's small.
Please, retry input a number.
50
It's small.
Please, retry input a number.
70
Perfect!
Finished.
```

本当に 10まで挑戦できるのかとか、ユニットテストの作成とか、
0～99の数を入れるよう促すように、ユーザーインターフェースの改善とか
やりたくなるが、とりあえず　先に進む。


# 8. 　じゃんけんゲームと　論理演算。　日本語出力。

グー、チョキー、パーの　三つ巴になっているのを、 && を使って分岐しよう、という趣旨だぜ。
数学マンは && を使うより簡単にやってしまうだろう……、そんな段階ではない。
統計マンは　人間の出す手を記録して　２０回勝負したら　絶対勝ち越せないマシンを作ろうとかするだろうが　そんな段階でもない……。

「じゃんけんゲーム」
http://www.ics.kagoshima-u.ac.jp/edu/katuyoukiso/vc/step4.html

```
# coding: utf-8
'''
じゃんけんゲーム
	0. グー、チョキ、パーを入力する。 一例： グーは g、チョキは t、パーは p とする。
	1. コンピューターもランダムに グー、チョキ、パー を出す。
	2. 勝敗を表示する。 グーはチョキに勝ち、チョキはパーに勝ち、パーはグーに勝つ。
	3. 備考：　なるべく論理演算を使った練習をすること。
'''

import random

# u を付けると、日本語（マルチバイト文字）を出せるようだ。
print u"[g], [t], [p]キーのいずれかを押せだぜ☆（＾～＾） g はグー、 t はチョキ、 p はパー　だぜ☆（＾～＾）"

# g t p のいずれかが入力される。入力チェックは省く。
human = raw_input();

# 0はグー、1はチョキ、2はパーとする。　Python に定数は無いらしい。えーっ。
COM_GOO = 0
COM_TYOKI = 1
COM_PAA = 2
computer = random.randint(0,2)

# コンピューターが出した手も表示する。
# Python に switch構文は無いらしい。 if文連打でやる。
if (computer == COM_GOO):
	print "com: g"
elif (computer == COM_TYOKI):
	print "com: t"
else:
	print "com: p"

print "----------"


# とりあえず コンピューター勝ちパターンから。 わかりづら……。
if (human == "g" and computer == COM_PAA) or (human == "t" and computer == COM_GOO) or (human == "p" and computer == COM_TYOKI):
	print "You lose!"
# 次に 人間勝ちパターン。
elif (human == "g" and computer == COM_TYOKI) or (human == "t" and computer == COM_PAA) or (human == "p" and computer == COM_GOO):
	print "You win!"
# 一応、引き分けパターンも。
elif (human == "g" and computer == COM_GOO) or (human == "t" and computer == COM_TYOKI) or (human == "p" and computer == COM_PAA):
	print "Draw."
# それ以外は、無効試合。
else:
	print "No game!"
print "Finished."
```

他の言語にある　あれ、Python で　どうやって書くの、ということが増えてきた。
Qiitaの下の方のコメント欄に　Python風の　switch の代わりの書き方が　コメントされているぜ☆（＊＾～＾＊）


# 9. 再帰ループで回文。

わたしまけましたわ　が最初に思いついたんで　それでいく。

「Python入門 - 関数」
http://www.tohoho-web.com/python/function.html

関数の次のコードで　インデントが無いとエラーが出るんだが　言わんとしていることが分からない。
関数とは別のコードだから　インデントを消したらいいんじゃないのか……。

```
# coding: utf-8
'''
回文
    0. わたしまけましたわ　のように、前から読んでも　後ろから読んでも同じもの。
    1. 備考：　再帰関数の練習をする。
'''

# 後ろ半分を入れる。
phrase = [u"け", u"ま", u"し", u"た", u"わ"]

# 関数を作る。
# この関数は、配列の最後から先頭に進んで、先頭から最後に戻るような動きをする。
def kaibun(depth):
    if (0 < depth):
        print phrase[depth],
		# depth が 0　より大きい内は、自分を何度も繰り返す。
        kaibun(depth - 1)
	# 呼び出した順とは逆順に、if文から抜けて、ここが実行される。
    print phrase[depth],
		
# 関数を呼び出す。　配列の長さ 5 から 1を引いた数を入れる。この数は配列の最後の要素 u"わ" に当たる。
kaibun(len(phrase)-1)
```

インデントに苦しみながら　なんとか　動くコードが書けた。

後ろから読むという、少し　ひねった　作り方をしているが、
関数の中に depth < len(phrase) と書いたら len( ) 関数を何回も呼び出すので、ケチって 0 < depth と書いている。
関数の中で　関数を呼び出す回数を　極力減らす、というのは　探索プログラムの高速化に役に立つ。
ベンチマーク測ってないけど　こっちの方がいいだろ。

```
C:\MuzudhoDrive\projects_python>python recursive.py
わ た し ま け ま し た わ
```

べつに回文作るのに　再帰する関数　使わなくてもいいんだけどな。

# 10 ぴったり１０秒。

「Pythonで一定時間ごとに処理を実行する」
https://qiita.com/kurogelee/items/0e5fd8b6a1d1f169179a

時計を作るというよりは、ライブラリを import して使う、ということを覚える。乱数で　すでにやっているが……。

「python 現在時刻取得」
https://qiita.com/mykysyk@github/items/e15d7b2b1a988b8e29d4

それにしても　見た目は時計にしたい。　と思ったんだが　時計作っても　おもんないんで
ストップウォッチを作ることにした。

```
# coding: utf-8
'''
タイマー（１０秒後に ぴったり止めよう）
    0. 何かキーを押したら計測開始。
    1. もう１回キーを押すとストップ。ぴったり１０秒なら嬉しい。
	2. おまけ：　最初の５秒間だけ、１秒間隔で経過が分かるヒントを出す。
'''

import os, sys, time
from datetime import datetime


# Windows版の書き方をする。 Linux や Max はまた別らしい。
if os.name == 'nt':
    import msvcrt
else:
    print(u"このプログラムは Windows以外には 対応していないぜ☆（＾ｑ＾）")
    sys.exit()        


print(u"ぴったり10秒後に何かキーを押せだぜ☆（＾～＾） 何かキーを押したら開始だぜ☆（＾ｑ＾）")
msvcrt.getch()
print(u"スタート！")


# 開始時間（秒）。
startTime = time.time()
# ヒントを出す秒。
hintSeconds = 1

# ループ。
playing = True
while playing:
    # 経過時間（秒）。
    erapsed = time.time() - startTime;
    if (hintSeconds < 6 and hintSeconds - 0.01 < erapsed and erapsed <= hintSeconds):
        # ヒントで 分:秒 表示。
        print(datetime.now().strftime("%M:%S"))
        hintSeconds = hintSeconds + 1

    # キーが押されたか判定する。ブロッキングしない。
    if (msvcrt.kbhit()):
        # 入力が有った。
		if 9.99 < erapsed and erapsed < 11.00:
			print u"Perfect! 終了するぜ☆（＾ｑ＾）"
			playing = False
		else:
			print erapsed, u"秒だぜ。惜しかったな☆（＾～＾） 終了するぜ☆（＾ｑ＾）"
			playing = False
```

プラットフォーム依存なのか。嬉しくないな……。
ところで　インデントは　タブではダメなことに今気づいた。空白４つにした。

```
C:\MuzudhoDrive\projects_python>python timer.py
ぴったり10秒後に何かキーを押せだぜ☆（＾～＾） 何かキーを押したら開始だぜ☆（＾ｑ＾）
スタート！
57:16
57:17
57:18
57:19
57:20
9.81299996376 秒だぜ。惜しかったな☆（＾～＾） 終了するぜ☆（＾ｑ＾）

C:\MuzudhoDrive\projects_python>python timer.py
ぴったり10秒後に何かキーを押せだぜ☆（＾～＾） 何かキーを押したら開始だぜ☆（＾ｑ＾）
スタート！
57:31
57:32
57:33
57:34
57:35
Perfect! 終了するぜ☆（＾ｑ＾）
```

でき上がりのもので　遊べた方が　おもろいだろ。



# 11. ゲームセレクト

メニューを作って、別のプログラムを呼び出すことにする。

```
# coding: utf-8
'''
キーボードで選択して、他のスクリプトを実行しよう。
    0. 「0」を入力したら bubble.py、「1」を入力したら dictionary.py、……を実行するようにする。
'''


# 無限ループ
while True:
	# この printf と if-elif 連打の部分を短くまとめる方法は このQiita記事のコメントに書かれている。
	print("Please, input number.")
	print("0: bubble.py")
	print("1: dictionary.py")
	print("2: fizz-buzz.py")
	print("3: for.py")
	print("4: format.py")
	print("5: game-select.py (*RECURSIVE*)") # 再帰する。
	print("6: hello.py")
	print("7: janken.py")
	print("8: number-guessing.py")
	print("9: recursive.py")
	print("10: stopwatch-10sec.py")
	print("99: QUIT")
	number = input()

	if (number == 0):
		# bubble.py を読み込む。拡張子は外す。 importをループの中で何回も使っていいのか知らないが……☆（＾～＾）
		import bubble
		
	elif (number == 1):
		# dictionary.py を読み込む。拡張子は外す。
		import dictionary

	elif (number == 2):
		# ファイル名にハイフンが付いていると、インポートできない。
		execfile('fizz-buzz.py')
		
	elif (number == 3):
		# ファイル名が予約語だと、インポートできない。
		execfile('for.py')
		
	elif (number == 4):
		import format
		
	elif (number == 5):
		execfile('game-select.py') # 再帰する。
		
	elif (number == 6):
		import hello
		
	elif (number == 7):
		import janken
		
	elif (number == 8):
		execfile('number-guessing.py')

	elif (number == 9):
		import recursive
		
	elif (number == 10):
		execfile('stopwatch-10sec.py')

	elif (number == 99):
		# 終了する。
		break

print('Finished.')
```

import を何回も呼び出していいものなのか　知らないが……☆（＾～＾）

```
C:\MuzudhoDrive\projects_python>python game-select.py
Please, input number.
0: bubble.py
1: dictionary.py
2: fizz-buzz.py
3: for.py
4: format.py
5: game-select.py (*RECURSIVE*)
6: hello.py
7: janken.py
8: number-guessing.py
9: recursive.py
10: stopwatch-10sec.py
99: QUIT
2
0 1 2 cat 4 human cat 7 8 cat human 11 cat 13 14 catman 16 17 cat 19 human cat 22 23 cat human 26 cat 28 29 catman 31 32 cat 34 human cat 37 38 cat human 41 cat 43 44 catman 46 47 cat 49 human cat 52 53 cat human 56 cat 58 59 catman 61 62 cat 64 human cat 67 68 cat human 71 cat 73 74 catman 76 77 cat 79 human cat 82 83 cat human 86 cat 88 89 catman 91 92 cat 94 human cat 97 98 cat Please, input number.
0: bubble.py
1: dictionary.py
2: fizz-buzz.py
3: for.py
4: format.py
5: game-select.py (*RECURSIVE*)
6: hello.py
7: janken.py
8: number-guessing.py
9: recursive.py
10: stopwatch-10sec.py
99: QUIT
6
Hello, world!!!
Please, input number.
0: bubble.py
1: dictionary.py
2: fizz-buzz.py
3: for.py
4: format.py
5: game-select.py (*RECURSIVE*)
6: hello.py
7: janken.py
8: number-guessing.py
9: recursive.py
10: stopwatch-10sec.py
99: QUIT
99
Finished.
```

メニューがあると　便利なこともあるからな。

# 12.