2013年4月14日日曜日

開発環境

初めてのコンピュータサイエンス(Jennifer CampbellPaul GriesJason MontojoGreg Wilson(著)長尾 高弘(翻訳))の12章(各種ツール)の12.7(練習問題)1~11を解いてみる。

1.

引数の数が多いときなどに、引数の順序を気にしなくてよくなる名前付き引数の機能が役に立つ。

2

-1などの整数は、リストの有効な添字だから。

3.

コード(BBEdit)

sample.py

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

def f(**values):
    for k, v in values.items():
        print(k, v)
    print()
if __name__ == '__main__':
    f(red=0.5, green=0.5)
    f(red=0.2, green=0.6,blue=0.2)
    d = {'red':0.4,'green':0.2, 'blue':0.4, 'balance':1}
    f(**d)

入出力結果(Terminal)

$ ./sample.py
green 0.5
red 0.5

blue 0.2
green 0.6
red 0.2

blue 0.4
balance 1
green 0.2
red 0.4

$

4.

  1. 2線が交わらない場合。[[0.0, 0.0], [1.0, 1.0]]と[[1.0, 0.0], [2.0, 1.0]]、出力値はNone
  2. 2線が1点で交わる場合。[[0.0, 0.0], [1.0, 1.0]]と[[1.0, -1.0], [-1.0, 1.0]]、出力値は[0.0, 0.0]
  3. 2線が1点(各線の両端のいずれかで接している)で交わる場合。[[0.0, 0.0], [1.0, 1.0]]と[[2.0, 2.0], [1.0, 1.0]]、出力値は[1.0, 1.0]
  4. 2線が部分的に重なる場合。[[0.0, 0.0], [2.0, 2.0]]と[[1.0, 1.0], [3.0, 3.0]]、出力値は[[0.0, 0.0], [2.0, 2.0]]
  5. 2線の全体が重なる(一致)する場合。[[0.0, 0.0], [1.0, 1.0]]と[[1.0, 1.0], [0.0, 0.0]]、出力値は[[0.0, 0.0], [1.0, 1.0]]
  6. 引数が線ではない場合。"python"と10、結果は例外発生

5.

  1. [[0, 0.0], [1.0, 1.0]]
  2. [[0.0, 0], [1.0, 1.0]]
  3. [[0.0 0.0], [1, 1.0]]
  4. [[0.0, 0.0], [1.0, 1]]
  5. [[0.0, 0.0], [1, 1.0]]
  6. [[1.0, 1.0], [1.0, 1.0]]と[[0.0, 0.0], [1.0, 1.0]]
  7. [[0.0, 0.0], [1.0, 1.0]]と[[1.0, 1.0], [1.0, 1.0]]

有効な入力に対して正しい答えを返すことのテストの方が重要。(な気がする。。)

6.

4種類。

第1引数を固定した場合と、第2引数を固定した場合のそれぞれ2種類ずつで合わせて4種類。

7.

コード(BBEdit)

sample.py

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

def average(values):
    res = 0
    for x in values:
        res += x
    return res / len(values)

test_cases = [
    [0.0, [0.0]],
    [0.0, [-1.0, 1.0]],
    [1.0, [0.0, 2.0]],
    [2.0, [0.0, 1.0, 2.0, 3.0, 4.0]]
]

passes = failures = 0
for expected, values in test_cases:
    actual = average(values)
    if actual == expected:
        passes += 1
    else:
        failures += 1
print("合格: {0}".format(passes))
print("不合格: {0}".format(failures))

入出力結果(Terminal)

$ ./sample.py
合格: 4
不合格: 0
$

テストのどこが失敗してるか分からず。。

8.

  1. グラスボックステスト(関数の実装を見てテストする)だと心理的な先入観の影響を受けやすくなるので、ブラックボックステストを採用した方が良い結果が得られる場合が多い。
  2. 集合を初期化する必要があること。(?)

9.

コード(BBEdit)

sample.py

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

# スペースが含まれる文字列の扱いについてが曖昧

def all_prefixes(s):
    res = set()
    for i in range(len(s)):
        res.add(s[:i + 1])
    return res

print(all_prefixes("lead"))

import nose

def test_0():
    assert all_prefixes("") == set()

def test_space():
    assert all_prefixes(" ") == {" "}

def test_1():
    assert all_prefixes("a") == {"a"}

def test_2():
    assert all_prefixes("ab") == {"a", "ab"}

def test_space_and_2():
    assert all_prefixes(" ab") == {" ", " a", " ab"}

def test_1_and_space_2():
    assert all_prefixes("a bc") == {"a", "a ", "a b", "a bc"}

if __name__ == '__main__':
    nose.runmodule()

入出力結果(Terminal)

$ ./sample.py
{'lea', 'l', 'le', 'lead'}
......
----------------------------------------------------------------------
Ran 6 tests in 0.005s

OK
$

10.

コード(BBEdit)

sample.py

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

def is_sorted(values):
    if values == sorted(values):
        return True
    return False

import nose

def test_empty():
    assert is_sorted([])

def test_one():
    assert is_sorted([10])

def test_two():
    assert is_sorted([10, 20])

def test_two_reverse():
    assert not is_sorted([20, 10])

def test_equal():
    assert is_sorted([10, 10, 10, 10, 10])

def test_first():
    assert not is_sorted([5, 1, 2, 3, 4])

def test_last():
    assert not is_sorted([1,2,3,4,0])

def test_middle():
    assert not is_sorted([1, 2, 0, 4, 5])

def test_normal():
    assert is_sorted([-100, -50, -5, 1, 10, 100, 1000, 5555])

def test_type():
    try:
        is_sorted("python")
        assert False
    except:
        assert True

def test_type_invidual():
    try:
        is_sorted([10, "python"])
        assert False
    except:
        assert True

if __name__ == '__main__':
    nose.runmodule()

入出力結果(Terminal)

$ ./sample.py
...........
----------------------------------------------------------------------
Ran 11 tests in 0.028s

OK
$

11.

リストは参照なので、各関数で変更されていくので、one_item_listを複数のテストケースで使っているのが誤り。関数内でスライスl = L[:]としてコピーしたリストlを使ってテストするように変更すればいい。

コード(BBEdit)

sample.py

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

def remove_all(values, value):
    while value in values:
        values.remove(value)

import nose

empty_list = []
one_item_list = ['He']
multi_item_list = ['Ne', 'Ar', 'He', 'He']

def test_remove_from_empty():
    l = empty_list[:]
    remove_all(l, 'He')
    assert len(l) == 0

def test_remove_from_one_item_list():
    l = one_item_list[:]
    remove_all(l, 'He')
    assert len(l) == 0

def test_remove_something_else():
    l = one_item_list[:]
    remove_all(l, 'Pb')
    assert len(l) == 1

def test_remove_multiple():
    l = multi_item_list[:]
    remove_all(l, 'He')
    assert len(l) == 2

if __name__ == '__main__':
    nose.runmodule()

入出力結果(Terminal)

$ ./sample.py
....
----------------------------------------------------------------------
Ran 4 tests in 0.030s

OK
$

0 コメント:

コメントを投稿