計算練習スクリプトを作ってみた @Python3

 最近は、より根本的な部分での処理能力…要するに暗算能力をもっと磨きたいと思っている。何度かこのブログにも書いてるけど。

 つーことで、計算問題を出題するスクリプトを書いてみた。ご丁寧に問題を解くのにかかった時間まで表示される。

 最初、加減乗除の各算ごとに数式生成関数を書いてみたのだが、どれも似たような処理ばかりだと途中で気付きやめてしまった。
 んで、新たに各算モードを備えてモードごとに挙動を変えるように工夫して、一つの関数で済むようにしてみた。

 どちらの項も整数のみ。割り算は割り切れる問題のみ出題するように工夫した。
 まずは単純な形式から始めないとくじけてしまう。弱い人間であります。(´・ω・`)
#!/usr/bin/python3
# -*- coding: utf-8 -*-

# 計算練習スクリプト
# 二項を加減乗除する、すなわち a+b、a-b、a*b、a/b の形式の計算問題を出題する。


import time

STR_QUESTION = "{} {} {} = "
MSG_RIGHT = "That's right! b(・∀・) < GJ!!"
MSG_WRONG = "Oh, that's wrong...(´・ω・`) < Correct answer is {}."

OPERATOR_DICT = {'add': '+', 'sub': '-', 'mul': '*', 'div': '/'}

def practice(operator, a, b):
if operator not in OPERATOR_DICT:
raise ValueError("Invalid argument '{}'".format(operator))

if not (isinstance(a, int) and isinstance(b, int)):
raise ValueError("Invalid argument. Both a and b must be an integer.")

d = (a + b) if (operator == 'add') or (operator == 'sub') else (a * b)
c, a = (d, a) if (operator == 'add') or (operator == 'mul') else (a, d)

starttime = time.time()
ans = input(STR_QUESTION.format(a, OPERATOR_DICT[operator], b))
stoptime = time.time() - starttime

print("{} [{}sec]\n".format(MSG_RIGHT if int(ans) == c else MSG_WRONG.format(c),
int(stoptime)))

 引数operator には OPERATOR_DICTのアイテムのどれかを入れる。
 引数a と b に数値をいれてやれば式が表示される。そのまま答えを入力すれば、正誤と所要時間(秒単位)が表示される。
practice('mul', 11, 12)

 実行してみるとこんな感じになる。それにしても適当な名前である(;^ω^)
$ python3 keisan.py
11 * 12 =
 間違えたとき
11 * 12 = 122
Oh, that's wrong...(´・ω・`) < Correct answer is 132. [2sec]
 正解のとき
11 * 12 = 132
That's right! b(・∀・) < GJ!! [2sec]

---

 直接定数を関数呼び出しのときに記述するのは好ましくない。それにいつも同じ数字が出てしまうではないか。
 しかし心配ご無用。引数a と b に random.randint() なんかでランダムな数値を食わせてやれば、実行のたびに違う式が表示される。
 まあ practice() 内でランダムな数字をジェネレートするようにしてやるのも手ではあるが、それはそれで関数の規模がでかくなりすぎてイマイチだし、そうやって機能追加するたびに柔軟性が減っていく。

 とはいえいちいち random.randint(云々) と書くのも面倒だし、頭が悪そうな感じになってしまうので、食わせる数字を一定の範囲でランダムにジェネレートする関数を作ってみた。数値が二つ返されるので、アンパックで食わせる形になる。これも practice() の引数の食い方を変えればアンパックしなくてもいいのだが、これまた柔軟性から考えるとンなことせんでええ、という結論となった。それに practice() を変える方が面倒くさい。
import random

def gen_randomval(minval, maxval):
rd = random.SystemRandom()
return (rd.randint(minval, maxval), rd.randint(minval, maxval))
 random.SystmRandom() を使っているのは、いっぺん使ってみようという好奇心だけである。環境によっては使えないらしい。幸い日常使いのWindowsXP(デスクトップ)と、LMDE(ラップトップ)では大丈夫だった。

 作った gen_randomval() を用いてやると、こんな感じになる。
if __name__ == '__main__':
minval = 11
maxval = 19

for op in OPERATOR_DICT.keys():
practice(op, *gen_randomval(minval, maxval))
 とりあえずこれで、実行のたびにランダムに加減乗除の問題が順に出題されるようにはなった。ただし必ずしも加→減→乗→除の順番通りじゃないけど。
 辞書だからしゃーないわ。面倒なのでもうこれ以上は手を入れない。

---

 かくして、急ごしらえではあるが当初の目的は達成した。

 ただ、非常にプリミティブな形ではある。
 コマンドライン引数を取れるようにして、もっと動作に柔軟性を持たせたい。という訳で、今はもっといい感じになるべく、今回のスクリプトを基に新たに書いているところ。色々試してみたい標準ライブラリもあるしな。

 「若者よ、書を捨てよ、実際に(動く)プログラムを書こう」といったところだね。
 え、「若者」じゃないだろって?  サーセンwwwwwwww
posted by kengpong at 12:54Comment(0)TrackBack(0)

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 0

この記事へのコメント


この記事へのトラックバック