SimplePrograms - Python Wiki
https://wiki.python.org/moin/SimplePrograms
の 21番目のプログラムは、33行の数字当てゲームです。
import random
guesses_made = 0
name = input('Hello! What is your name?\n')
number = random.randint(1, 20)
print ('Well, {0}, I am thinking of a number between 1 and 20.'.format(name))
while guesses_made < 6:
guess = int(input('Take a guess: '))
guesses_made += 1
if guess < number:
print ('Your guess is too low.')
if guess > number:
print ('Your guess is too high.')
if guess == number:
break
if guess == number:
print ('Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made))
else:
print ('Nope. The number I was thinking of was {0}'.format(number))
例によって、prog-33.py というファイルにして実行してみます。
$ python3 prog-33.py
Hello! What is your name?
espiya
Well, espiya, I am thinking of a number between 1 and 20.
Take a guess: 5
Your guess is too low.
Take a guess: 10
Your guess is too high.
Take a guess: 8
Your guess is too high.
Take a guess: 6
Good job, espiya! You guessed my number in 4 guesses!
$
6回までに1から20までの数を当てるゲームですね。
6回で当てられないと、
Nope. The number I was thinking of was 6
$
となります。
さすがに最後のプログラムとなると新しい機能はほとんど使われていませんね。
その中で、random モジュールが使われています。
https://docs.python.org/ja/3/library/random.html#module-random
このモジュールでは様々な分布をもつ擬似乱数生成器を実装しています。
整数用に、ある範囲からの一様な選択があります。シーケンス用には、シーケンスからのランダムな要素の一様な選択、リストのランダムな置換をインプレースに生成する関数、順列を置換せずにランダムサンプリングする関数があります。
実数用としては、一様分布、正規分布 (ガウス分布)、対数正規分布、負の指数分布、ガンマおよびベータ分布を計算する関数があります。角度の分布を生成するにはフォン・ミーゼス分布が利用できます。
ほとんど全てのモジュール関数は、基礎となる関数 random() に依存します。この関数はランダムな浮動小数点数を半開区間 0.0 <= X < 1.0 内に一様に生成します。Python は中心となる乱数生成器としてメルセンヌツイスタを使います。これは 53 ビット精度の浮動小数点を生成し、周期は 2**19937-1 です。本体は C で実装されていて、高速でスレッドセーフです。メルセンヌツイスタは、現存する中で最も広範囲にテストされた乱数生成器のひとつです。しかしながら、メルセンヌツイスタは完全に決定論的であるため、全ての目的に合致しているわけではなく、暗号化の目的には全く向いていません。
以前、LINEのAIチャット君の紹介で出てきたように、random()の乱数生成方法はメルセンヌツイスタを使っているのですね。注意書きにもあるように、メルセンヌツイスタは決定論的なので、使用するシードに工夫が必要ですが、生成される乱数はOS提供の乱数に比べれば非常に良いと考えられるので、乱数が必要なプログラムでは十分使えますね。この中で、
random.randint(a, b)
a <= N <= b であるようなランダムな整数 N を返します。randrange(a, b+1) のエイリアスです。
を使って、1から20までの乱数を生成して答えとするわけです。
クイズなので、input() で入力を、print() で出力をするプログラムですね。
整数入力の時は、 int(input(.....)) と覚えておきます。
while ループ内の if 文ですが、elif や continue を使いたいと思う気がしますが、
SimplePrograms ではいずれも使っていませんでした。
さて、出力ですが、
https://docs.python.org/ja/3.8/tutorial/inputoutput.html#input-and-output
によると、
・ フォーマット済み文字列リテラル を使うには、開き引用符や三重の開き引用符の前に f あるいは F を付けて文字列を始めます。 この文字列の内側では、文字 { と文字 } の間に Python の式が書け、その式から変数やリテラル値が参照できます。
・ 文字列の str.format() メソッドは、もう少し手間がかかります。 ここでも { と } を使って変数に代入する場所の印を付けて、細かいフォーマットの指示を出せますが、フォーマットされる対象の情報を与える必要があります。
フォーマット済み文字リテラル (短くして f-string とも呼びます) では、文字列の頭に f か F を付け、式を {expression} と書くことで、 Python の式の値を文字列の中に入れ込めます。
これを、いつくか試してみます。
>>> a = 10
>>> b = 100
>>>
>>> print(f'A is {a}, B is {b}.')
A is 10, B is 100.
>>>
>>> print('A is {a00}, B is {b00}.'.format(a00=a, b00=b))
A is 10, B is 100.
>>>
>>> print('A is {0}, B is {1}.'.format(a, b))
A is 10, B is 100.
>>>
>>> print('A is {a}, B is {b}.'.format(a, b))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'a'
>>>
>>> print('A is {a}, B is {b}.'.format(a = a, b = b))
A is 10, B is 100.
>>>
エラーになる例は間違えそうなので、一番最後の例の形で覚えておくことにします。
SimplePrograms では、f-string が出てこなくて、str.format() のみ使っているので、
何かあるのかもしれませんね。
以上、SimplePrograms の21の各プログラムを見てきましたが、入門としてはちょっと変わった?機能を使うことがあり、これを Python プログラミングで使った方が良いという考え方があるような気がしました。特に入門時に docstring を使えるようにする(ちょっと大変と思うなら、生成AIを使う)ことは、プログラミングに有用だと感じました。
今後も何かあれば、Python について試して見たいと思います。
https://wiki.python.org/moin/SimplePrograms
の 21番目のプログラムは、33行の数字当てゲームです。
import random
guesses_made = 0
name = input('Hello! What is your name?\n')
number = random.randint(1, 20)
print ('Well, {0}, I am thinking of a number between 1 and 20.'.format(name))
while guesses_made < 6:
guess = int(input('Take a guess: '))
guesses_made += 1
if guess < number:
print ('Your guess is too low.')
if guess > number:
print ('Your guess is too high.')
if guess == number:
break
if guess == number:
print ('Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made))
else:
print ('Nope. The number I was thinking of was {0}'.format(number))
例によって、prog-33.py というファイルにして実行してみます。
$ python3 prog-33.py
Hello! What is your name?
espiya
Well, espiya, I am thinking of a number between 1 and 20.
Take a guess: 5
Your guess is too low.
Take a guess: 10
Your guess is too high.
Take a guess: 8
Your guess is too high.
Take a guess: 6
Good job, espiya! You guessed my number in 4 guesses!
$
6回までに1から20までの数を当てるゲームですね。
6回で当てられないと、
Nope. The number I was thinking of was 6
$
となります。
さすがに最後のプログラムとなると新しい機能はほとんど使われていませんね。
その中で、random モジュールが使われています。
https://docs.python.org/ja/3/library/random.html#module-random
このモジュールでは様々な分布をもつ擬似乱数生成器を実装しています。
整数用に、ある範囲からの一様な選択があります。シーケンス用には、シーケンスからのランダムな要素の一様な選択、リストのランダムな置換をインプレースに生成する関数、順列を置換せずにランダムサンプリングする関数があります。
実数用としては、一様分布、正規分布 (ガウス分布)、対数正規分布、負の指数分布、ガンマおよびベータ分布を計算する関数があります。角度の分布を生成するにはフォン・ミーゼス分布が利用できます。
ほとんど全てのモジュール関数は、基礎となる関数 random() に依存します。この関数はランダムな浮動小数点数を半開区間 0.0 <= X < 1.0 内に一様に生成します。Python は中心となる乱数生成器としてメルセンヌツイスタを使います。これは 53 ビット精度の浮動小数点を生成し、周期は 2**19937-1 です。本体は C で実装されていて、高速でスレッドセーフです。メルセンヌツイスタは、現存する中で最も広範囲にテストされた乱数生成器のひとつです。しかしながら、メルセンヌツイスタは完全に決定論的であるため、全ての目的に合致しているわけではなく、暗号化の目的には全く向いていません。
以前、LINEのAIチャット君の紹介で出てきたように、random()の乱数生成方法はメルセンヌツイスタを使っているのですね。注意書きにもあるように、メルセンヌツイスタは決定論的なので、使用するシードに工夫が必要ですが、生成される乱数はOS提供の乱数に比べれば非常に良いと考えられるので、乱数が必要なプログラムでは十分使えますね。この中で、
random.randint(a, b)
a <= N <= b であるようなランダムな整数 N を返します。randrange(a, b+1) のエイリアスです。
を使って、1から20までの乱数を生成して答えとするわけです。
クイズなので、input() で入力を、print() で出力をするプログラムですね。
整数入力の時は、 int(input(.....)) と覚えておきます。
while ループ内の if 文ですが、elif や continue を使いたいと思う気がしますが、
SimplePrograms ではいずれも使っていませんでした。
さて、出力ですが、
https://docs.python.org/ja/3.8/tutorial/inputoutput.html#input-and-output
によると、
・ フォーマット済み文字列リテラル を使うには、開き引用符や三重の開き引用符の前に f あるいは F を付けて文字列を始めます。 この文字列の内側では、文字 { と文字 } の間に Python の式が書け、その式から変数やリテラル値が参照できます。
・ 文字列の str.format() メソッドは、もう少し手間がかかります。 ここでも { と } を使って変数に代入する場所の印を付けて、細かいフォーマットの指示を出せますが、フォーマットされる対象の情報を与える必要があります。
フォーマット済み文字リテラル (短くして f-string とも呼びます) では、文字列の頭に f か F を付け、式を {expression} と書くことで、 Python の式の値を文字列の中に入れ込めます。
これを、いつくか試してみます。
>>> a = 10
>>> b = 100
>>>
>>> print(f'A is {a}, B is {b}.')
A is 10, B is 100.
>>>
>>> print('A is {a00}, B is {b00}.'.format(a00=a, b00=b))
A is 10, B is 100.
>>>
>>> print('A is {0}, B is {1}.'.format(a, b))
A is 10, B is 100.
>>>
>>> print('A is {a}, B is {b}.'.format(a, b))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'a'
>>>
>>> print('A is {a}, B is {b}.'.format(a = a, b = b))
A is 10, B is 100.
>>>
エラーになる例は間違えそうなので、一番最後の例の形で覚えておくことにします。
SimplePrograms では、f-string が出てこなくて、str.format() のみ使っているので、
何かあるのかもしれませんね。
以上、SimplePrograms の21の各プログラムを見てきましたが、入門としてはちょっと変わった?機能を使うことがあり、これを Python プログラミングで使った方が良いという考え方があるような気がしました。特に入門時に docstring を使えるようにする(ちょっと大変と思うなら、生成AIを使う)ことは、プログラミングに有用だと感じました。
今後も何かあれば、Python について試して見たいと思います。