課題09-1 点と線分 #
難易度 ⭐⭐
点(Point
)と線分(Line
)を表す2つのクラスを作成してください.
Point
クラスは,2次元平面上の点を表すクラスです.x
座標とy
座標を持ち,コンストラクタで初期化します.- 他の
Point
オブジェクトからの距離を計算するメソッドdistance
を持ちます.- 他の
Point
オブジェクトが渡されなかった場合は,原点(0, 0)
からの距離を計算します.
- 他の
__str__
メソッドでは,f"({self._x}, {self._y})"
という文字列表現を返します.
Line
クラスは,2つのPoint
オブジェクトからなる線分を表すクラスです.- 2つの
Point
オブジェクトを持ち,コンストラクタで初期化します. - 線分の長さを計算するメソッド
distance
を持ちます. __str__
メソッドでは,f"({self._p1}, {self._p2})"
という文字列表現を返します.is_on
メソッドは,引数にPoint
オブジェクトを受け取り,その点が線分上にあればTrue
を返し,そうでなければFalse
を返します.- 直線の方程式を求めて,引数の
Point
オブジェクトの座標が方程式を満たすかどうかで判断すると良いでしょう. - ただし,浮動小数点変数(
float
)の場合,誤差により必ずしも一致するわけではないので,誤差を許容する必要があります.- 求めた値
got_x
と,一致してほしい値want_x
の差の絶対値が0.00001
より小さければ等しいとみなすと良いでしょう(abs(got_x - want_x) < 0.00001
).
- 求めた値
- 直線の方程式を求めて,引数の
- 2つの
以下のプログラム(assignment09-1.py
)を実行したときに,テストが全て通るように plane_figures.py
を作成してください.
import plane_figures as pf
p1 = pf.Point(3, 4)
assert p1.distance() == 5.0, "原点からの距離が正しくありません"
assert p1.distance(p1) == 0.0, "同じ点からの距離が正しくありません"
assert str(p1) == "(3, 4)", "文字列表現が正しくありません"
p2 = pf.Point(1, 1)
assert p2.distance() == 2 ** 0.5, "原点からの距離が正しくありません"
l1 = pf.Line(p2, pf.Point(5, 5))
assert l1.distance() == 32 ** 0.5, "線分の長さが正しくありません"
assert str(l1) == "((1, 1), (5, 5))", "文字列表現が正しくありません"
assert l1.is_on(pf.Point(3, 3)), "点 (3, 3) が線分上にないと判断されています"
assert not l1.is_on(pf.Point(0, 0)), "点 (0, 0) は線分上にありません"
課題09-2 乱数ジェネレータ #
難易度 ⭐⭐
以下の特徴を持つ乱数生成クラス MyRandom
(my_random.py
)を作成してください.
MyRandom
クラスは,線形合同法(Linear Congruential Generator; LCG)による乱数生成器です.- 線形合同法は \(X_{n+1} = (a * X_n + c) \mod m\) という漸化式で表されます.
- 上記の
a
は乗数(multiplier),c
は加数(increment),m
は剰余(modulus)と呼びます.
- 上記の
- 線形合同法は \(X_{n+1} = (a * X_n + c) \mod m\) という漸化式で表されます.
- コンストラクタは,
seed
とmodulus
とmultiplier
とincrement
を受け取り,初期化します.seed
は乱数の初期値です.デフォルト値は0
です.modulus
は剰余演算に使う値です.デフォルト値は2 ** 32
です.multiplier
は乗算に使う値です.デフォルト値は1664525
です.increment
は加算に使う値です.デフォルト値は1013904223
です.
next
メソッドは,次の0以上1未満の乱数を生成し,返します.- 得られた\(X_{n+1}\)は\(0\)以上\(m\)未満の整数となりますので,範囲を \(0\)以上\(1\)未満に変換するために,\(X_{n+1} / m\) を返します.
class MyRandom:
def __init__(self): # 引数(seed,modulus, multiplier, increment)を追加してください.
pass # seed, modulus, multiplier, increment はデフォルト引数を持つようにしてください.
def next(self, count = 0): # count が指定された場合,count 回乱数を生成します.
result = self._next_impl()
if count > 0:
return self.next(count - 1)
return result
def _next_impl(self):
pass # 線形合同法による乱数生成を実装してください.
以下のテストコード(assignment09-2.py
)を通るようにしてください.
import my_random as mr
rg = mr.MyRandom(0, 2 ** 32, 1664525, 1013904223)
assert rg.next() - 0.236067972844466 < 0.000001, "乱数が正しくありません"
assert rg.next() - 0.278566908556968 < 0.000001, "乱数が正しくありません"
assert rg.next(2) - 0.384077370865270 < 0.000001, "乱数が正しくありません"
# assert rg.next() - 0.819533759960904 < 0.000001, "乱数が正しくありません" # このコメントアウトした
# assert rg.next() - 0.667866897769272 < 0.000001, "乱数が正しくありません" # 2つの乱数が飛ばされる.
assert rg.next() - 0.621807487215846 < 0.000001, "乱数が正しくありません"
課題09-3 ベクトル #
難易度 ⭐⭐⭐
次のプログラム(assignment09-3.py
)を実行したときに,テストが全て通るように vector.py
を作成してください.
vector.py
中で Vector
クラスを定義し,以下のメソッドを用意してください.
__init__
コンストラクタ.n
個の引数(可変長)を受け取り,ベクトルを表す.__add__
ベクトル同士の足し算を計算し,新しいベクトルを返す.__mul__
ベクトル同士の内積を計算し,スカラー値を返す.__getitem__
ベクトルの要素を取得する.__len__
ベクトルの長さを返す.__str__
ベクトルの文字列表現を返す.norm
ベクトルのノルム(大きさ)を計算し,返す.
import vector as v
v1 = v.Vector(3, 4, 5)
v2 = v.Vector(1, 2, 3)
v3 = v1 + v2
assert v3[0] == 4 and v3[1] == 6 and v3[2] == 8, "ベクトルの足し算が正しくありません"
assert v1 * v2 == 26, "ベクトルの内積の計算が正しくありません"
assert str(v1) == "(3, 4, 5)", "ベクトルの文字列表現が正しくありません"
assert len(v1) == 3, "ベクトルの長さが正しくありません"
assert v1.norm() == 50 ** 0.5, "ベクトルのノルム(大きさ)の計算が正しくありません."
v4 = v.Vector(1, 1, 1, 1, 1)
assert len(v4) == 5, "ベクトルの長さが正しくありません"
assert v4.norm() == 5 ** 0.5, "ベクトルのノルム(大きさ)の計算が正しくありません."
assert v4 + v1 == None, "要素数の異なるベクトル同士の足し算は計算できないので,None が返るはずです."
assert v1 * v4 == None, "要素数の異なるベクトル同士の内積は計算できないので,None が返るはずです."
なお,リストを可変長引数として受け取る方法は以下の通りです.
>>> list = [1, 2, 3]
>>> v1 = Vector(list) # これは,[1, 2, 3] という1つの要素を持つベクトルになってしまう.
>>> v1.elements
([1, 2, 3],) # ベクトルの要素は [1, 2, 3] という値一つ.
>>> v2 = Vector(*list) # このようにリスト変数の前に * をつけると,リストの要素を展開して引数として渡すことができる.
>>> v2.elements
(1, 2, 3)