第1回

プログラムの基本要素、変数、繰り返し、条件分岐を一通り学ぶ。リストを配列的に用いる。乱数で遊ぶ。

(2021/11/05 最終修正)

演習0:Pythonの基礎を一通り

あまり細かい事は説明せず、必要最小限の説明をするという姿勢で Pythonの基礎を一通り解説する。

構想中。

変数・input()・print()

変数という概念は、あらゆるプログラミング言語に存在する。変数が無いプログラミング言語は想像できない。

変数は、数値であるとか、文字列であるとかを記憶する箱によく例えられる。そのような箱に、数値や文字列を入れたり出したりしつつ、計算等を行って有用な仕事をするのがプログラムである。

変数名は英数字からなるが、英字を最初にもってくる。大文字小文字の区別はある。

Python には、変数の型がある。ただ、わかりにくいともいえるし、意識しなくても良いともいえるが、間違ったプログラムを書いてしまうリスクがある。次は変数の例である。

a = 20

b = 32.1

c = "ABC"

d = "23.4"

変数 a の型は、

type(a)

でわかる。変数の内容は print 文で表示する。

print(a)

数値を文字列に変換したい場合がある。また、逆もある。

str(a)

によって、数値 20 が 文字列 "20" となる。

float(d)

で、文字列 "23.4" が、数値(実数型)23.4 に変換される。

float(c) はエラーになる。

a = input("Input a : ")

で、キーボードから入力した”文字列”が変数 a にはいる。a が数値を表す文字列の場合、

b = float(a) や b = int(a) で変換する。

基本的な演算は、四則演算が +, -, *, / である。それから、よく使うものとして % があり、a%b で a を b で割ったあまりが得られる。

次の動画で適当に例を示しながら解説する。

動画作成中

条件分岐(if文)・条件式

条件分岐がないプログラミング言語は無い。条件分岐があってこそのプログラムであるから。基本的に、上記の変数の内容が様々な計算によって変化するが、その内容に従って、その後の処理を変えることが通常であって、その時に条件分岐が行われる。

基本的な構文は、


if 条件式 :

実行すること1

実行すること2

実行すること・・・・

実行することは、様々な文である。条件式が真(True)であれば、赤い部分の文が順に実行され、その後青い文が実行される。条件式が、偽(False)であれば実行されず、青の文にうつる。少し複雑なものとしては、


if 条件式 :

実行すること1

実行すること2

実行すること・・・・

else :

実行することA

実行することB

実行すること・・・・


というのがある。この場合、条件式が真(True)であれば、赤い部分の文が順に実行され、その後青い文が実行される。条件式が、偽(False)であれば else : 下の緑色の文が順に実行され、その後青い文が実行される。最初の例は、else が無いバージョンとも言える。


if 条件式1 :

実行すること1

実行すること2

実行すること・・・・

elif 条件式2 :

実行することA

実行することB

実行すること・・・・

else :

実行することα

実行することβ

実行すること・・・・

この場合、条件式1が真(True)であれば、赤い部分の文が順に実行され、その後青い文が実行される。条件式2が真(True)であれば、緑の部分の文が順に実行され、その後青い文が実行される。それ以外であれば else : 下の紫色の文が順に実行され、その後青い文が実行される。

この elif はいくつでも足すことができる。大体こんな感じ。

条件式

重要なのは、条件式で、通常数値の大小関係を扱う。

a == b

は a, b の中の数値が等しい場合に真となる条件式であり、そのような比較するための記号(関係演算子、比較演算子)には次の様なものがある。

>, >=, <, <=, ==, !=

最後の != は等しくない場合に真となる関係演算子である。

論理演算子を使って、複雑な条件を記述できる。例えば、数値の入った a, b, c の三つの変数があったときに、

a > b and b > c

で a> b かつ b > c という条件式となる。

a > b or b > c

で a > b または b > c という条件式となる。例えば、 n が西暦の年号(整数)であるとき、n が

「4で割り切れ かつ 100で割り切れない年」 または 「400で割り切れる年」

であれば、n年はうるう年であるが、その条件式は、次の様になる。なお、% は割ったあまりを求める演算子である。


if (n%4 == 0 and n%100 != 0) or n%400 == 0:

print("うるう年")

次の動画で適当に例を示しながら解説する。

動画作成中

繰り返し文(for文, while文)

毎度の事だが、繰り返し分の無いプログラミング言語は無い。何故なら、コンピュータが特に有用なのは、簡単な計算を高速に文句も言わずに繰り返す事ができるからだ。Python では、 for 文と while 文が使える。


for i in range(0, 100):

print(i)

のように使う。この場合、画面には 0から99の通知が表示される。for のあとに i とあるが、こちらが繰り返し文で使われる変数で、 in の後にあるモノから一つづつ代入される。この場合には、 range(0, 100) であるから、0から99の数値が i に都度代入される。これと同じ事を while を使って書くと、


i = 0

while i < 100:

print(i)

i = i + 1

whle の次に条件式が書かれる。条件式が真(True)である間、内容が繰り返される。この場合、画面に i の内容を表示し、i を一つ増やす。例えば次も同じ事であるが、 break 文を使って繰り返しを抜ける処理を書いている。


i = 0

while True:

print(i)

i = i + 1

if i >= 100:

break

多重の繰り返し文が書ける

for i in range(1, 5):

for j in range(1, 3):

print(i, j)

内側の繰り返し文(この場合 j に関するもの)が先に実行される。これは2重ループと呼ばれるが、3重ループ以上も同様に書ける。ただ、通常3重くらいまでだろう。

動画作成中

配列変数・関数

配列は大抵のプログラミング言語にある。ただ、無いと不便である。Python には、通常の言語で言うところの配列は無いと言えるかも知れないが、リストを配列のように使う事ができる。

a = [0]*3

とすると、a[0], a[1], a[2] の3つの変数が作られる。それぞれの中身は 0 という数値になる。

a = [1.0]*3

とすれば、それぞれの中身は 1.0 という数値になる。配列変数は、繰り返し文と合わせて使われることが多い。

a = [0]*10

a[0] = 1

a[1] = 1

for i in range(2, 10):

a[i] = a[i - 1] + a[i - 2]

print(a[9])

といった使い方ができる。これは、所謂フィボナッチ数列を計算するコードである。

上記はリストを配列のように使っているが、NumPy というパッケージ(拡張機能のようなもの)を使い、 NumPy 配列を使う事が多い。実際、Python 関係の書籍やWeb上の情報では、NumPyを使っている場合が多い。その場合、プログラムの最初で NumPy を利用する宣言をする必要がある事と、配列変数の宣言の仕方が異なるだけで、使い方は変わらない(違う事もあるが、あまり意識しなくても良い場合が多い)。

NumPy を利用する為に、以下の一行がプログラムの最初の方に必要になる。

import numpy as np

その上で、先のプログラムは次の様になる。

a = [0]*10

a = np.zeros(10)

で置き換わった。但し、厳密に同じでは無く、上の例では 55 と出るが、次の例では 55.0 となる。np.zeros で作成した配列は実数型となるためである。細かい事は、他の情報源を見て欲しい。


import numpy as np


a = np.zeros(10)

a[0] = 1

a[1] = 1

for i in range(2, 10):

a[i] = a[i - 1] + a[i - 2]

print(a[9])

ついでに、2次元配列についても触れておく。


A = np.zeros((100, 100))

とすれば、100x100の配列を作成でき、変数の値は全て 0.0 となる。配列の要素は A[1][4] というふうに参照する。これで行列Aの1行4列目の要素を参照できる。(配列の添え字は0からはじまるので、0行3列目という言い方を許していただいた場合の言い方。それを許さないというのであれば、2行5列目の要素ということになる。)


A = np.zeros((101, 101))

と宣言すると、A[0][0], A[0][1], ...., A[0][99],.....,A[100][100] と101x101の配列となる。

こちらは、おまけ回にある内容である。

動画作成中

基礎のまとめ

上記が基礎で、プログラムは上記の基礎の組み合わせでしか無い。

基礎を組み合わせた演習として並べ替え(ソーティング)をしてみよう。ソーティングアルゴリズムは様々なものがあり、実用上はクイックソートなどのより高度なものを用いることになるし、Pythonであれば組み込みの機能を使えば良いが、ここでもプログラミングを学ぶという観点から、最も単純な方法で並べ替えを行う。

作成中

演習1:画面に1から6の整数値をランダムに表示するプログラムを作成

乱数を使う時に、random モジュールを用いる。(他にもある。例えば、NumPy。)

import random

random モジュールでよく使うもの二つ。

  • random.uiform(a, b) : [a, b] の一様乱数(実数値)

  • random.randint(a, b) : [a, b] の一様乱数(整数値)

数値変数を文字列型に変換

  • str(a) : a が数値で無い場合にはエラーとなる


Code1.py : 1つの擬似乱数(一様乱数)の発生と表示(random関数)

# Code1.py

import random


float_rand = random.uniform(0.0, 100.0)

int_rand = random.randint(1, 6)


print("float_rand = " + str(float_rand))

print("int_rand = " + str(int_rand))

for 文の典型的な使い方。


for i in range(0, 10):
print(i)

画面には、0 から 9 の数値が出る。次の様なリストと絡む場合もある。


N = [10, 100, 100]

for i in N:

print(i)

画面には、10, 100, 100 がでる。


Code2.py : 複数の擬似乱数の発生と表示(擬似乱数 + 繰り返し文(for文))

# Code2.py

import random


for i in range(0, 10):

float_rand = random.uniform(1.0, 6.0)

int_rand = random.randint(1, 6)


print("i = ", i)

print("float_rand = " + str(float_rand))

print("int_rand = " + str(int_rand))

演習2:擬似サイコロを1000回ふり、それぞれの目が出る回数を数える

変数に足し込んでいく処理。ここでの、

count = count + 1

の使い方は大事である。例えば、1から10 の数値を足し合わせたい場合、つまり、次の計算は、

次の様に書けるが、


c = 0

for i in range(1, 11):

c = c + i

print(c)

これがわかりにくい人は多いようだ。自分で似たような問題を考えて、確認した方が良い。


Code3.py : 1の目が出る回数を数え、1の目が出る確率を表示する

# Code3.py

import random


count = 0

for i in range(0, 1000):

int_rand = random.randint(1, 6)

if int_rand == 1:

count = count + 1


print(count, count/1000.0)

Code4.py : サイコロ関数を作って使う

# Code4.py

import random


N = 1000


def dice():

return random.randint(1, 6)


count = 0

for i in range(0, N):

int_rand = dice()

if int_rand == 1:

count = count + 1


print(count, count/float(N))

リストの配列的使い方

a = [0]*4

これによって、a[0], a[1], a[2], a[3] の4つの変数が作られる(と考える)。例えば、

a[2] = 4

のように使える。繰り返し文と合わせて、

for i in range(0, 5):

a[i] = i

という風な使い方ができる。他言語の配列のように使える。


Code5.py : 配列(リスト)を使う

# Code5.py

import random


N = 10000


def dice():

return random.randint(1, 6)


# c[0], c[1], ..., c[5]

c = [0]*6


for i in range(0, N):

r = dice()

c[r - 1] = c[r - 1] + 1


print(c)

Code6.py : それぞれの目が出る確率を求める

# Code6.py

import random


N = 10000


def dice():

return random.randint(1, 6)


# c[0], c[1], ..., c[5]

c = [0]*6


for i in range(0, N):

r = dice()

c[r - 1] = c[r - 1] + 1


for i in range(0, 6):

print(str(i+1) + "の目がでる確率は" + str(c[i]/float(N)) + "です。")

演習3:1次元ランダムウォーク

Code7.py : 1次元ランダムウォークを可視化する。(matplotlib の利用)

# Code7.py

import random

import matplotlib.pyplot as plt


def dice2():

return random.randint(0, 1)


T = 100

N = 100000

dist = [0]*T*2

x = [0]*T*2

#pos = [0]*T


for n in range(0, 2*T):

x[n] = -100 + n


for n in range(0, N):

p = 0

for t in range(0, T):

#pos[t] = p

d = dice2()

if d == 0:

p += 1

else:

p -= 1

#plt.plot(pos)

dist[p + T] += 1


plt.bar(x, dist)

plt.show()

上の Code7.py の動画の途中、4:16あたりで Python プログラムが動かないような部分がありますが、利用しているパソコンでmatplotlib モジュールを初めて使ったため時間がかかったようです。そのまま置いておけば動いたのですが、 Ctrl+c で停止することをしてしまいました。なお、プログラムの動作がおかしい場合に強制終了するには Controlキーを押しながら c を押すことで強制終了できます。今回は、先の理由のため停止の必要はありませんが停止してしまったということです。ただ、このようなことも起こりうるので、そのままカットせず載せています。

演習4:モンティホール問題

  • 問題の概要

  • 3つの扉のどれかに商品を入れる(司会者側)

  • 3つの扉の一つを選ぶ(回答者)

  • 回答者の選んだ扉以外の2つの扉の商品の入っていない扉を選ぶ(司会者)

  • 選んだ扉を変更する(または変更しない)

  • 結果をカウント

  • これらを複数回繰り返し、商品獲得率を表示

  • (付録)配列(リスト)を使ったバージョン


Code8.py : 選択変更しない場合

# Code8.py

import random


def dice3():

return random.randint(0, 2)


N = 10000

win = 0


for n in range(0, N):

prize = dice3()

player = dice3()


if prize == player:

win += 1


print(win/float(N))

Code9.py : 選択変更する場合

# Code9.py

import random


def dice3():

return random.randint(0, 2)


N = 10000

win = 0


for n in range(0, N):

prize = dice3()

player = dice3()


while True:

chair = dice3()

if chair != prize and chair != player:

break

while True:

new = dice3()

if new != player and new != chair:

break

player = new

if prize == player:

win += 1


print(win/float(N))

Code10.py : リストを使った場合

# Code10.py

import random


def dice3():

return random.randint(0, 2)


N = 10000

win = 0


for n in range(0, N):

doors = [0, 1, 2]

prize = dice3()

player = dice3()

doors.remove(prize)

if prize != player:

doors.remove(player)


chair = doors[random.randint(0, len(doors) - 1)]


doors = [0, 1, 2]

doors.remove(player)

doors.remove(chair)

new = doors[0]


player = new

if prize == player:

win += 1


print(win/float(N))

課題

モンティホール問題は扉が3つであったがその数を増やしたり、商品が複数ある等バリエーションが考えられる。そういったバリエーションのシミュレーションコードを書いてみよう。できるだろうか?

もしもこれができないとすれば、上記の演習が効果的に身についていないと思われ、今後もプログラミングができるようにはならないと思うので、マイルストーンとして挑戦すべきだとおもうのでやってみよう。

できない場合には、上記の演習をしっかり理解していない、またはプログラミングに向いていないということで後者と諦めてしまう場合には、そもそも向いていない。プログラミングはある程度楽しめないと上達はしない。