ひるあんどんブログ

色々なことに手を出してみるブログ

Building Base

奇妙なことが起こって、私たちは権力者のために理想的なロボットの街を作っています。 この輝かしいロボットの街では、すべての建物は四角ですべての通りは東西南北の美しい格子状に走っています。 私達が初める前にまず完璧な建物を表現するクラスを作ります。

その街のすべての建物は四角でそれらの壁は通りと平行なので、私たちはあらゆる建物を2つの引数(東西の壁の長さ、南北の壁の長さ)と南西の角の座標と建物の高さとして定義することが出来ます。 これらの値は慣習的に正の数字として表すことにします。 座標の原点は南西にあります 、そのため北の座標は南の座標より大きい値を持って終わります。 このミッションを終わらせるため、いくつかの演算が必要になります。 クラスの詳細を見てください。

class Building(south, west, width_WE, width_NS, height=10)

[south, west] に南西の角がある新しい建物のインスタンスを返します、width_WE と width_NS は大きさで、建物の高さは heightです。 "height" は正の数でデフォルト値は10です。

>>> Building(10, 10, 1, 2, 2)
Building(10, 10, 1, 2, 2)
>>> Building(0, 0, 10.5, 2.546)
Building(0, 0, 10.5, 2.546, 10)


corners()

建物の角の座標の辞書を返します。 辞書は以下のキーがあります、 "north-west"、 "north-east"、 "south-west"、 "south-east"。 それらの値は2つの値からなるリストかタプルです。

>>> Building(1, 2, 2, 2).corners()
{"north-west": [3, 2], "north-east": [3, 4], "south-west": [1, 2], "south-east": [1, 4]}


area()

建物の面積を返します。

>>> Building(1, 2.5, 4.2, 1.25).area()
5.25


volume()

建物の容積を返します。

>>> Building(1, 2.5, 4.2, 1.25, 101).volume()
530.25


__repr__()

これは建物の文字列表現です。このメソッドは"print"と"str"に使われます。 以下のような形式で文字列を返します。
"Building({south}, {west}, {width_we}, {width_ns}, {height})"

>>> str(Building(0, 0, 10.5, 2.546))
"Building(0, 0, 10.5, 2.546, 10)"


このミッションではすべてのデータは正しく、値のチェックを実装する必要はありません。

入力 Buildingクラスのステートメントと式

出力 前述のふるまい

どうやって使われるか ここではロボニアの繁栄を達成する最小の機能を持つ単純なクラスを書く方法を学びます。

事前条件 すべてのデータは正しい

class Building:
    """ Defines a building
    """

    def __init__(self, south, west, width_WE, width_NS, height=10):
        self.south = south
        self.west = west
        self.width_WE = width_WE
        self.width_NS = width_NS
        self.height = height

    def corners(self):

        return dict([("north-west",[self.width_NS + self.south,self.west]),
        ("north-east",[self.south + self.width_NS,self.west + self.width_WE]),
        ("south-west",[self.south,self.west]),
        ("south-east",[self.south,self.west+self.width_WE])])

        

    def area(self):
        """ Returns the area of the building
        """
        return self.width_NS * self.width_WE

    def volume(self):
        """ Return the volume of the building
        """
        return self.area() * self.height

    def __repr__(self):
        return ("Building(" + str(self.south) + ", " + str(self.west) + ", "
                + str(self.width_WE) + ", " + str(self.width_NS) + ", "
                + str(self.height) + ")")

if __name__ == '__main__':
    #These "asserts" using only for self-checking and not necessary for auto-testing
    def json_dict(d):
        return dict((k, list(v)) for k, v in d.items())

    b = Building(1, 2, 2, 3)
    b2 = Building(1, 2, 2, 3, 5)
    assert json_dict(b.corners()) == {'north-east': [4, 4], 'south-east': [1, 4],
                                      'south-west': [1, 2], 'north-west': [4, 2]}, "Corners"
    assert b.area() == 6, "Area"
    assert b.volume() == 60, "Volume"
    assert b2.volume() == 30, "Volume2"
    assert str(b) == "Building(1, 2, 2, 3, 10)", "String"

素直に解いた。しかし、selfの使い方が冗長だなぁ。

Clear 1位


from itertools import product

<200b>

class Building(object): # W to E: width, N to S: depth

    def __init__(self, south, west, width, depth, height=10):

        self.south, self.west = south, west

        self.width, self.depth, self.height = width, depth, height

        self.north, self.east = south + depth, west + width

<200b>

    def corners(self):

        pairs = product(('south', 'north'), ('west', 'east'))

        return {'-'.join(p): [getattr(self, d) for d in p] for p in pairs}

<200b>

    def area(self):

        return self.width * self.depth

<200b>

    def volume(self):

        return self.width * self.depth * self.height

<200b>

    def __repr__(self):

        txt = 'Building({0.south}, {0.west}, {0.width}, {0.depth}, {0.height})'

        return txt.format(self)


self.__init__ で多重代入を行っている。

また、北と東の座標はなんども使うので前もって計算している。これだと確かに無駄がない。

productという関数は、itertoolsの関数みたいで色々便利なものがあるようだ。
qiita.com