前回の記事で一区切りついたので、今回は第8回までの演習を総括し、解説と解答を掲載していきます。


第4回「型と変数について学ぼう(前編)」の解答解説

演習1

問題

以下の図形の面積を求めてください。

変数に領域a、b、cの値をそれぞれ代入してから、その面積の合計値を求めてください。

解説

変数の使い方の問題です。特に難しいところはありません。

解答

a = 5 * 3
b = 3 * 4
c = 7 * 1
print(a + b + c)

演習2

問題

演習1の面積を変数を使わないで求めてください。

解説

数式に慣れるための問題です。電卓のように数式の前側から計算していくのではなく、算数で習ったように「足し算より掛け算を優先」といったルールがあるのでそれに気をつけてください。

また () を使うことで計算の優先度を変えることができます。たとえば「1+3 * 2」は「1+6」として計算され7となりますが、「(1+3) * 2」は「4 * 2」として計算されるので8となります。

記号ごとの「結合優先度」を熟知していても、ややこしい計算であれば () でくくるなどして人が見てもわかりやすいコードを書いたほうがいいかもしれません。また、あまりに複雑な数式を書くのであればそれ自体を関数化するのもアリだと思います。

解答

print(5 * 3 + 3 * 4 + 7 * 1)

演習3

問題

まだ説明していない組み込み関数を利用して、以下の問題をクリアしてください。公式のドキュメントから関数を探す、検索エンジンを利用するなど手段は問いません。

  1. 文字列'123'を整数の123に変換する
  2. 文字列'123.4'を小数の123.4に変換する

解説

プログラミングをしていると「あれをやりたいのにどうやればいいかわからない」といった場面によく出くわします。それを解決することに慣れてもらうための問題です。一番簡単なのはGoogleなどで「適切なキーワード」で検索することです。たとえば「python 文字列 整数 変換」などというキーワードで検索すればすぐに答えが見つかるはずです。ドキュメントを頭から探すのは時間がかかるので、私はとりあえず検索エンジンで調べてしまうことが多いです。日本語で引っかからない場合でも、英語で検索すると出てくることがあります。

ただ、誰もブログやフォーラムなどに使い方を投稿していないマイナーな機能というのも存在します。たとえば非公式のライブラリを使うときなどがそうです。その際は単に検索するだけではなく、体系的にまとめられたドキュメントを読んで目的のものを探すことが必要となります。公式ドキュメントはわかりやすい部類なので、それで慣れてもらおうという意図もあります。

文字列から整数への変換に利用する関数はint()であり、文字列から小数(浮動小数点)への変換にはfloat()関数を利用します。それぞれ変換できないような文字列を渡すとエラーになるので注意してください。

解答

>>> int('123')
123
>>> float('123.4')
123.4

第5回「型と変数について学ぼう(後編)」の解答解説

演習1

問題

文字列 ' hello ' から前後の空白をすべて取り除いてください。

解説

文字列の前後から特定の文字列を取り除くのにはstrip関数を使います。引数に特定の文字を与えれば、それを取り除くことができます。引数を与えなければ空白、改行、タブなどを取り除きます。

解答

>>> '  hello    '.strip()
hello

演習2

問題

以下の図のCとDおよび2つの円をくっつけた領域をAとBを用いて表現してください。

解説

CはAでもありBでもあります。DはAでもBでもありません。2つの円をくっつけた領域はAかBです。ド・モルガンの法則と呼ばれている論理法則を知っておくと便利かもしれません。

解答

1. CはA and B
2. Dはnot A and not B もしくはnot(A or B)といえます。
3. 2つの円をくっつけた領域はA or Bです。

第6回「プログラムの制御構造を理解しよう - 条件分岐とループ処理」の解答解説

演習1

問題

[[1,5,3], [2,6,4]] はリストにリストが入っています。内側のリストの最大値をそれぞれ求めるプログラムを書いてください。

解説

リスト内のリストを処理するには、for文のなかにさらにfor文を記載します。for文のなかの最大値を求めるのはmax関数を使う方法もありますが、今回は最大値を探査するプログラムを自力で書きます。

解答

a = [[1,2,3], [4,5,6]]

for i in a:
    max_value = i[0]
    for j in i:
        if(j > max_value):
            max_value = j
    print(max_value)

補足

リストのなかに「同じ長さのリスト群」が格納されているデータ構造はよく利用されます。2次元配列だとか、Matrix構造などと呼ばれているもので、図にすると以下のようになります。

普通のリストはそのリスト長が要素数となります。つまり1次元なデータなわけです。一方、リストのなかにリストがある場合は「外側のリスト長×内側のリスト長」が要素数となるので2次元なデータになります。同様にリストのなかにリストがあり、そのなかにまたリストがある場合は3次元です。

どの要素にアクセスするかは、

リスト名[一番外側のインデックス番号][2番目に外側のインデックス番号]

というように、外側のインデックス番号から順に指定していきます。インデックス番号を指定しないとリストそのものをとってきます。たとえば以下のようになります。

>>> a = [[1,2,3], [4,5,6], [7,8,9]]
>>> a
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> a[1]
[4, 5, 6]
>>> a[1][1]
5
>>> a[1][1][1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object has no attribute '__getitem__'

当然、2次元のデータで3次元のポイントを指定したらエラーとなります。あたりまえですね。

最後のfor文が具体的に2次元のデータをどのように探査するか見てみます。3次元以上でも基本は同じです。

a = [[1,2,3], [4,5,6], [7,8,9]]
for i in a:
    print('loop1: ' + str(i))
    for j in i:
        print('loop2: ' + str(j))

これを実行すると次のようになります。

loop1: [1, 2, 3]
loop2: 1
loop2: 2
loop2: 3
loop1: [4, 5, 6]
loop2: 4
loop2: 5
loop2: 6
loop1: [7, 8, 9]
loop2: 7
loop2: 8
loop2: 9

外側のfor文は「リストのなかのリスト」を取得してきてグルグル回し、内側のfor文は取得されたリストの中身をグルグル回しています。こういうのをイテレート処理というんでしたね。

演習2

問題

1から100までの整数で、

  • 3の倍数の時はFizz
  • 5の倍数の時はBuzz
  • 3の倍数でもあり5の倍数でもあるときはFizzBuzz

と表示するプログラムを書いてください。

解説

「3の倍数」はつまり「3で割り切れる数」ということです。剰余(余り)の計算が0となれば、それは割り切れるということです。3も5も素数なので、3でも5でも割り切れるということは、15でも割り切れるということです。1から100までの整数を作るにはrange関数を使います。

解答

for i in range(1,101):
    if(i%15 == 0):
        print(str(i) + ': Fizz Buzz')
    elif(i % 3 == 0):
        print(str(i) + ': Fizz')
    elif(i % 5 == 0):
        print(str(i) + ': Buzz')

第7回「関数とモジュールを使いこなそう」の解答解説

演習1

問題

絶対値を返す関数my_absを作成してください。この関数内では標準ライブラリなどで提供されているabs関数などは使わないでください。

解説

関数を作成する簡単な問題です。ひとつの引数を受け取り、絶対値を返す関数を作ります。絶対値は、

  • 値Xが正ならX自体が絶対値
  • 値Xが負なら、それに-1をかけた値が絶対値

として求められます。

解答

def my_abs(x):
    if(x < 0):
        x *= -1
    return x

print(my_abs(5))
print(my_abs(-3))

演習2

問題

引数で与えた数だけフィボナッチ数を配列で返す関数my_fiboを作成してください。フィボナッチ数については調べればすぐにわかるはずです。

解説

フィボナッチ数は、1、1、2、3、5、8、13……というようにN番目の数字はN-1番目+N-2番目の合計値というようにして求められる数です。最初は1、1からスタートします。

解答

def my_fibo(x):
    if(x < 3):
        return [1,1]

    fibo_list = [1,1]
    for i in range(2, x):
        fibo_i = fibo_list[i-1] + fibo_list[i-2]
        fibo_list.append(fibo_i)
    return fibo_list

print(my_fibo(8))
print(my_fibo(1))

演習3

問題

演習1、2で作成した関数もしくは自分で適当に作成した関数をモジュール化し、それを別ファイルから利用してみてください。import文、from文の両方を使ってみてください。

解説

モジュール化するにはPythonのプログラムファイルにわけるだけで大丈夫です。モジュールimportをすると、そのモジュール内の中身(関数など)を使えるようになります。

解答

<モジュールとなるファイル my_module.py>

def my_abs(x):
    if(x < 0):
        x *= -1
    return x

def my_fibo(x):
    if(x < 3):
        return [1,1]

    fibo_list = [1,1]
    for i in range(2, x):
        fibo_i = fibo_list[i-1] + fibo_list[i-2]
        fibo_list.append(fibo_i)
    return fibo_list

if(__name__ == '__main__'):
    print(my_abs(5))
    print(my_abs(-3))
    print(my_fibo(8))
    print(my_fibo(1))

<importの利用>

>>> import my_module
>>> my_module.my_abs(-3)
3
>>> my_module.my_fibo(8)
[1, 1, 2, 3, 5, 8, 13, 21]

<fromの利用>

>>> from my_module import *
>>> my_abs(-3)
3
>>> my_fibo(8)
[1, 1, 2, 3, 5, 8, 13, 21]

第8回「ユーザーからプログラムへの入力をする方法」の解答解説

演習1

問題

コマンドライン引数で与えた2つの整数を足したものを表示するプログラムを作ってください。引数が2つ以外の場合はエラー表示して処理を中断させてください。

ヒント:文字列の足し算とならないように、引数の値を正数に変換する必要があります。

解説

コマンドライン引数を取得するにはsys.argvを使います。引数の数のチェックにはsys.argvの長さを確認すれば大丈夫です。文字列から整数への変換にはint()関数を使います。

解答

import sys

if(len(sys.argv) != 3):
    print('Error')
    exit()

a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)

<呼び出し>

% python test.py 5 8
13

演習2

問題

標準入力で受け取った文字列を“echo: 文字列”として表示するするプログラムを書いてください。exitと入力されるとプログラムが終了します。以下のようなイメージです。

python test.py
Hello
echo: Hello
Python
echo: Python
exit

解説

標準入力にはraw_input()関数を使います。入力された文字列がexitなら終了し、そうでなければ'echo: 'という文字列に入力された文字列を結合して表示します。

解答

while(True):
    text = raw_input()
    if(text == 'exit'):
        break
    print('echo: ' + text)

演習3

問題

標準入力で受け取ったPythonのプログラム(一行)を実行するプログラムを書いてください。exitと入力されるとプログラムが終了します。

% python test.py 
please input 1 line program or exit.
print('hello')
hello

please input 1 line program or exit.
a = 5 + 5 

please input 1 line program or exit.
print(a)
10

please input 1 line program or exit.
exit
%

解説

演習2とほとんど同じですが、受け取った文字列をexec()関数で実行します。

解答

while(True):
    print('please input 1 line program or exit.')
    text = raw_input()
    if(text == 'exit'):
        break
    exec(text)
    print('')

次回の内容

次回はPythonから少し離れて実際のアプリケーションの開発例を紹介したいと思います。この連載ではPythonやプログラミングについて比較的ミクロな視点で取り扱っていますが、もっと大きな視点で「こうやって実際のサービスを組む」といったような話題を取りあげます。その次からは通常の連載内容に戻り、今まで扱わなかったものの重要な型について扱っていきます。

執筆者紹介

伊藤裕一(ITO Yuichi)

シスコシステムズでの業務と大学での研究活動でコンピュータネットワークに6年関わる。専門はL2/L3 Switching とデータセンター関連技術およびSDN。TACとしてシスコ顧客のテクニカルサポート業務に従事。社内向けのソフトウェア関連のトレーニングおよびデータセンタとSDN関係の外部講演なども行う。

もともと仮想ネットワーク関連技術の研究開発に従事していたこともあり、ネットワークだけでなくプログラミングやLinux関連技術にも精通。Cisco社内外向けのトラブルシューティングツールの開発や、趣味で音声合成処理のアプリケーションやサービスを開発。

Cisco CCIE R&S, Red Hat Certified Engineer, Oracle Java Gold,2009年度 IPA 未踏プロジェクト採択

詳細(英語)はこちら