LoginSignup
6
7

More than 5 years have passed since last update.

「退屈なことはPythonにやらせよう」の演習を解く。( [3.11.1], [3.11.2], [4.10.1], [4.10.2] )

Last updated at Posted at 2018-12-23
本記事は下書きリストから掘り出された個人的アーカイヴの1つです. 公開時期と執筆時期の間には,ある程度の開きがあります.

オライリー本「退屈なことはPythonにやらせよう 初版第1刷」の各演習プロジェクトを自分なりに解いたものです.

かなり前に書いたやつです.下書きリストに残ってたのですが,誰かの役に立つかも知れないので,一応公開しておきます


ルール

演習時に使用する文法等は,基本的にその演習ページまでの内容に沿って書くものとしています.
例えば「演習の時点でfor文は説明されたけれど,while文と累算代入演算子は説明されていない」という場合,

x = 100
y = 0
while y > -131071:
    x -= 1
    y = (x ** 3) - (3 * x ** 2) + (x - 1)
print('when x=' + str(x) + ', y=' + str(y))

と書きたいところを

x = 100
y = 0
for i in range(10000):  # edited
    x = x - 1           # edited
    y = (x ** 3) - (3 * x ** 2) + (x - 1)
    if y <= -131071:    # inserted
        break           # inserted
print('when x=' + str(x) + ', y=' + str(y))

と書く,といった具合です.


演習【3.11.1】コラッツ数列 (p.78)

■ 要件

  • numberというパラメータを1つ持つcollatz()という名前の関数を書く
  • numberが偶数なら,collatz()number / 2を戻り値にする
  • numberが奇数なら,collatz()3 * number + 1を戻り値にする
  • ユーザーに整数を入力してもらい,その数をcollatz()に渡して呼び出す
  • collatz()が1を返すまで,その戻り値をcollatz()自身に渡し,呼び出し続ける
  • 入力を促す文章,入力値,collatz()の戻り値,を表示する
    e.g.
    image.png

■ 実装例

def collatz(number):             # まず関数を定義
    if number % 2 == 0:          # 入力が偶数なら実行
        number /= 2              # number = number / 2 を累算代入演算子で
    else:                        # 入力が奇数(number % 2 != 0)なら実行
        number = 3 * number + 1  # そのまま
    return int(number)           # 2で割ったときにfloat型になったのをint型に直す


print('input a number: ')        # ここから実行される
n = int(input())                 # 入力の受け付け+文字列から整数に変換
while n != 1:                    # 入力が1か,collatz()の返り値が1になるまでループ
    n = collatz(n)               # collatz()自身に値を返す
    print(n)                     # 毎回返り値を表示させる


input()                          # コマンドプロンプトを閉じさせない(Windows)
                                 # 空行(lintを静かにさせる)

最後のinput()は,.pyファイルを開いて実行させるときのTipsです.(input()があれば,入力があるまで,プログラムが一時停止状態になる-->Enterを押すと,input()の行が実行されますが,値を返す先がないので,プログラムへの影響なしに,次の行へ移り,そのままプログラムが終了します)
IDLEなどの即時実行できる環境がある人は気にしなくても大丈夫です.

演習【3.11.2】入力の妥当性検証(p.78)

■ 要件(3.11.1への追加)

  • ユーザーの入力が整数でない場合を判定するよう,try - except文を追加
  • 尚,int()関数に文字列を渡すと,ValueError例外が起こる
  • except節では,整数値の入力を促す文章を表示する

■ 実装例

def collatz(number):
    if number % 2 == 0:
        number /= 2
    else:
        number = 3 * number + 1
    return int(number)


print('input a number: ')
while True:                      #常にTrue: breakが出るまで無限ループ
    try:
        n = int(input())         #ここでエラーが出たら,即時except節へ(ループする)
        break                    #エラーが出なかったら,ループを抜ける
    except ValueError:
        print('input a integer!')#ループ終端なので,実行後自動でcontinue(while文の先頭へ)
while n != 1:
    n = collatz(n)
    print(n)


input()     # PAUSE

不正な入力がないかをチェックするためのtry&exceptを,whileで囲み,エラーがなくなるまでループするようにしました.最初から入力が正常なら1回目で検証用ループを脱出(break)します.

演習【4.10.1】カンマ付け (p.107)

■ 要件

  • spam = ['apple', 'bananas', 'tofu', 'cats']のようなリストがあるとき,
  • 'apple, bananas, tofu and cats'と返すような関数
  • 関数には,任意のリスト値を渡しても良いようにする

■ 実装例

def f(arg):                                # display like [0], [1], ..., [-2] and [-1]
    a = len(arg)                           # あとでループ幅に使うために,受け取ったリストの長さを代入
    o = ''                                 # 返り値に使うstr型変数を用意
    for i in range(a):                     # arg[0]からarg[-1]までを操作
        if i == (a - 1):                   # 最後の入力分
            o += arg[i]                    # --> そのまま出力文字列に追加
        elif i == (a - 2):                 # 最後から2番目の入力分
            o += arg[i] + ' and '          # --> andを付けて出力文字列に追加
        else:                              # 最後から3番目までは
            o += arg[i] + ', '             # --> カンマを付ける
    return o


print('Input something and press "Enter" to continue\n\
or input "end" if the list is over.')
spam = []                                  # 入力データを受け取るリストを用意
while True:
    print('\n' + '- input: ', end='')
    w = input()
    if w == 'end':                          # endが入力されたら,リストの追加をやめる
        print('\nThe list you made: ' + str(spam) + '\n')
        break                               # 作成したリストを表示したあと,ループから抜ける
    spam.append(w)                          # 随時,入力をリストに追加
print('\n--> ' + f(spam))                   # 関数f()にspamを渡し,返り値を表示させる

input()                                     # PAUSE

f(arg)のif文とelif文は入れ替わっても問題ないですが,if文が,処理を上から順番に,飛ばさずに実行するということを踏まえると,「arg[-1]->arg[-2]->その他」の順番が気持ちいいです.
入力が1単語のときはそれをそのまま返し,2単語だけのときはA and Bの形で表示するようになっています.

ちなみに,\nは改行文字です.時々出てくるend=''は,出力文字列の後ろに何もつけない指定をしています(デフォルトだと改行が入る).あと', 'とか' and 'というように,空白文字を前後につけたり...sep=','を今回使わなかったのは,問題文にapple, bananas, tofu and catsではなく,'apple, bananas, tofu and cats'(:1つの文字列)を返せと書いてあったからです.

関数の内部状態が分かるように,関数内に適宜input()を入れたものがこちら:
image.png
', '' and 'が適宜挿入されている流れが分かると思います.

演習【4.10.2】文字絵グリッド (p.107)

■ 要件

  • 左のようなリストから,右のような表示をせよ(行列の転置みたいなやつ)
    image.png
  • ※実際の問題ではドットでしたが,見ずらかったのでハイフンにしています.

■ 実装例

grid = [['_', '_', '_', '_', '_', '_'],
        ['_', '0', '0', '_', '_', '_'],
        ['0', '0', '0', '0', '_', '_'],
        ['0', '0', '0', '0', '0', '_'],
        ['_', '0', '0', '0', '0', '0'],
        ['0', '0', '0', '0', '0', '_'],
        ['0', '0', '0', '0', '_', '_'],
        ['_', '0', '0', '_', '_', '_'],
        ['_', '_', '_', '_', '_', '_']]

i = 0                                 #---------┐
for j in range(len(grid[i])):         #         |
    for n in range(len(grid)):        #---┐     |
        print(grid[n][j], end='')     #   ├※1  ├※2
    print('\n')                       #---┘     |
    i += 1                            #---------┘

input()                               # PAUSE

grid[i][j]とおき,

※1の発想...

  1. grid[0][j]~grid[-1][j]というふうに,
    jを固定し,iを動かすループが必要
  2. (iを動かす=行のインデックスを回す)
  3. len(grid)をrange()に入れたfor文を回す:
    jは固定(外ループに依存)しつつ,iを回す(グリッドの行数分,縦移動)
  4. 横移動なしで縦移動し,一番したについたら,改行文字を入れる

※2の発想...

  1. iは固定(外ループ?に依存)しつつ,jを回す(グリッドの列数分,横移動)
  2. iも回さないといけないけど,for i in range(len(grid))を一番外のループに書くと,同じようなループが3重になって見た目がすっきりしないので,jループ内のカウンタi += 1iを回し,その外に初期値i = 0を置く

というように,内側から順番に考えるとやりやすかったです.
休憩を入れてから取り組むとスムーズに解けました.詰んだときは,とりあえず別のことをしましょう!


今回は以上です.

気が向いたら続き書きます

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7