Python Class Recap -2 tricky problems

发布时间 2023-09-18 00:56:56作者: 鱼市口
Test cases as below:

$ python3 >>> from quiz_8 import * >>> Point() ... quiz_8.PointError: Need two coordinates, point not created. >>> Point(0) ... quiz_8.PointError: Need two coordinates, point not created. >>> Point(0, 0, 0) ... quiz_8.PointError: Need two coordinates, point not created. >>> Point(0, 0) Point(0, 0) >>> print(Point(1, 2)) Point of x-coordinate 1 and y-coordinate 2 >>> p1 = Point(1, 2) >>> p2 = Point(4, 8) >>> p3 = Point(2, 4) >>> Triangle(point_1=p1, point_2=p2, point_3=p3) ... quiz_8.TriangleError: Incorrect input, triangle not created. >>> p3 = Point(3, 5) >>> Triangle(p1, p2, p3) ... TypeError: __init__() takes 1 positional argument but 4 were given >>> triangle = Triangle(point_1=p1, point_2=p2, point_3=p3) >>> triangle.perimeter 13.476032868131739 >>> triangle.area 1.5000000000000078 >>> p3 = Point(2, 4) >>> triangle.change_point_or_points(p3) ... TypeError: change_point_or_points() takes 1 positional argument but 2 were given >>> triangle.change_point_or_points(point_3=p3) Incorrect input, triangle not modified. >>> triangle.perimeter 13.476032868131739 >>> triangle.area 1.5000000000000078
page1image1017303744
>>> p0 = Point(0, 0)
>>> p3 = Point(0, 4)
>>> triangle.change_point_or_points(point_3=p3, point_1=p0)
>>> triangle.perimeter
18.60112615949154
>>> triangle.area
7.999999999999994
>>> triangle.change_point_or_points(point_2=Point(4, 0))
>>> triangle.area
7.999999999999997
>>> triangle.change_point_or_points(point_3=Point(4, 0))
Incorrect input, triangle not modified.
>>> triangle.change_point_or_points(point_3=Point(4, 8))
>>> triangle.area
16.0
>>> triangle.perimeter
20.94427190999916

Descriptions:
Defines two classes, Point and Triangle.

An object of class Point is created by passing exactly 2 integers as arguments to __init__().
You can assume that nothing but integers will indeed be passed as arguments to __init__(),
but not that exactly 2 arguments will be provided; when that is not the case, a PointError error is raised.
The point class implements the __str__() and __repr__() special methods.

An object of class Triangle is created by passing exactly 3 points as keyword only arguments to __init__().
You can assume that exactly three points will indeed be passed as arguments to __init__().
The three points should not be collinear for the triangle to be created; otherwise a TriangleError error is raised.
A triangle object can be modified by changing one two or three points thanks to the method change_point_or_points(),
all of whose arguments are keyword only. At any stage, the object maintains correct values for perimeter and area.

#Not that exactly
# 2 arguments will be provided; when that is not the case,
# a PointError error is raised.
# The point class implements the __str__() and __repr__()
# special methods.

from math import sqrt
from math import pow

# INSERT YOUR CODE HERE
class Point():
    # try:
    #
    # except TypeError as e:
    #     print('quiz_8.PointError: Need two coordinates, point not created.')

    def __init__(self,p1, p2):
        self.p1 = p1
        self.p2 = p2
        print('quiz_8.PointError: Need two coordinates, point not created.')

    def __str__(self):
        if p1:
            print('Point of x-coordinate',self.p1.x ,'and y-coordinate', self.p1.y)
    def __repr__(self):
        return

# class quiz_8.PointError():
#     pass

class Triangle(Point):
    def __init__(self, point_1, point_2, point_3):
        self.point_1 = point_1
        self.point_2 = point_2
        self.point_3 = point_3
        
        self.aa = point_distance(point_1, point_2)
        self.bb = point_distance(point_2, point_3)
        self.cc = point_distance(point_1, point_3)

        if point_2 == None:
            print('quiz_8.PointError: Need two coordinates, point not created.')
        if aa * bb * cc == 0 or max(aa, bb, cc) == aa + bb + cc - max(aa, bb, cc):
            print('quiz_8.TriangleError: Incorrect input, triangle not created.')

    def point_distance(self, p, pp):
        return math.sqrt(math.pow(p[0] - pp[0], 2) + math.pow(p[1] - pp[1], 2))

    def area(self):
        aa = point_distance(point_1, point_2)
        bb = point_distance(point_2, point_3)
        cc = point_distance(point_1, point_3)
        s = (aa + bb + cc) / 2
        if aa * bb * cc != 0 and max(aa, bb, cc) != aa + bb + cc - max(aa, bb, cc):
            return math.sqrt(s * (s - aa) * (s - bb) * (s - cc))

    def perimeter(self):
        return aa+bb+cc

    def change_point_or_points(self, *p):
        if p :
            p1 = p.index(0)
            self.a = p.index(0)
            self.b = p.index(1)
        else: pass

Another Class to implement

# Defines a class Building that defines a few special methods,
# as well as the two methods:
# - go_to_floor_from_entry()
# - leave_floor_from_entry()
# and an atribute, number_created, to keep track of
# the number of Building objects that have been created.
#
# Also defines a function compare_occupancies() meant to take
# as arguments two Building objects.
# Building objects are created with statements of the form
# Building(height, entries) where height is a positive integer
# (possibly equal to 0) and entries is a nonempty string that
# denotes all access doors to the building, with at least
# one space within the string to separate entries.
# You can assume that height and entries are as expected.
#
# If building denotes a Building object, then
# building.go_to_floor_from_entry(floor, entry, nb_of_people)
# takes as argument an integer, a string, and an integer.
# An error of type BuildingError is raised,
# all with the same message, if:
# - floor is not between 0 and the building's height, or
# - entry is not one of the building's entries, or
# - nb_of_people is not strictly positive.
# If the lift at that entry has to go down,
# then by how many floors it has to go down is printed out.
#
# If building denotes a Building object, then
# building.leave_floor_from_entry(floor, entry, nb_of_people)
# takes as argument an integer, a string, and an integer.
# An error of type BuildingError is raised if:
# - floor is not between 0 and the building's height, or
# - entry is not one of the building's entries, or
# - nb_of_people is not strictly positive, or
# - there are not at least nb_of_people on that floor.
# The same error message is used for the first 3 issues,
# and another error message is used for the last issue.
# If the lift at that entry has to go up or down, then
# by how many floors it has to go up or down is printed out.
#
# For the number of floors to go up or down, use
# "1 floor..." or "n floors..." for n > 1.

class BuildingError(Exception):
    pass


class Building:
    number_created = 0
    def __init__(self, height, entries):
        Building.number_created += 1
        self.height = height
        self.entries = entries
        self.the_entries = entries.split()
        self.lifts = {entry: 0 for entry in self.the_entries}
        self.occupancies = {(entry, floor): 0
                                for entry in self.the_entries
                                    for floor in range(0, self.height)
                           }
        
    def __repr__(self):
        return f"Building({self.height}, '{self.entries}')"
    
    def __str__(self):
        return 'Building with ' +\
               (self.height == 0 and '1 floor ' or\
                f'{self.height + 1} floors '\
               ) + 'accessible from entries: ' + ', '.join(self.the_entries)
    
    def go_to_floor_from_entry(self, floor, entry, nb_of_people):
        if not 0 <= floor <= self.height\
           or entry not in self.the_entries\
           or nb_of_people <= 0:
            raise BuildingError("That makes no sense!")
        self.occupancies[entry, floor] += nb_of_people
        if floor:
            if self.lifts[entry]:
                print('Wait, lift has to go down', self.lifts[entry],
                      self.lifts[entry] > 1 and 'floors...'\
                      or 'floor...'
                     )
            self.lifts[entry] = floor

    def leave_floor_from_entry(self, floor, entry, nb_of_people):
        if not 0 <= floor <= self.height\
           or entry not in self.the_entries\
           or nb_of_people <= 0:
            raise BuildingError("That makes no sense!")
        if self.occupancies[entry, floor] < nb_of_people:
            raise BuildingError("There aren't that many people on that floor!")
        self.occupancies[entry, floor] -= nb_of_people
        if floor:
            if self.lifts[entry] > floor:
                difference = self.lifts[entry] - floor
                print('Wait, lift has to go down', difference,
                      difference != 1 and 'floors...' or 'floor...'
                     )
            if self.lifts[entry] < floor:
                difference = floor - self.lifts[entry]
                print('Wait, lift has to go up', difference,
                      difference != 1 and 'floors...' or 'floor...'
                     )
            self.lifts[entry] = 0

    
def compare_occupancies(building_1, building_2):
    occupancy_1 = sum(building_1.occupancies.values())
    occupancy_2 = sum(building_2.occupancies.values())
    if occupancy_1 == occupancy_2:
        print('There is the same number of occupants in both buildings.')
    elif occupancy_1 > occupancy_2:
        print('There are more occupants in the first building.')
    else:
        print('There are more occupants in the second building.')

! test cases following!#
>>> the_horizons = Building(10, 'A B C D')
>>> the_horizons
Building(10, 'A B C D')
>>> print(the_horizons)
Building with 11 floors accessible from entries: A, B, C, D
>>>  Building.number_created
1
>>> the_spike = Building(37, '1')
>>> the_spike
Building(37, '1')
>>> print(the_spike)
Building with 38 floors accessible from entries: 1
>>> Building.number_created
2
>>> the_seaside = Building(6, 'A B Z')
>>> the_seaside
Building(6, 'A B Z')
>>> print(the_seaside)
Building with 7 floors accessible from entries: A, B, Z
>>> Building.number_created
3
>>> the_horizons.go_to_floor_from_entry(-1, 'A', 4)
...
quiz_8.BuildingError: That makes no sense!
>>> the_horizons.go_to_floor_from_entry(11, 'A', 4)
...
quiz_8.BuildingError: That makes no sense!
>>> the_horizons.go_to_floor_from_entry(0, 'Z', 4)
...
quiz_8.BuildingError: That makes no sense!
>>> the_horizons.go_to_floor_from_entry(0, 'B', 0)
...
quiz_8.BuildingError: That makes no sense!
>>> the_horizons.go_to_floor_from_entry(0, 'B', 4)
>>> compare_occupancies(the_horizons, the_spike)
There are more occupants in the first building.
>>> the_spike.go_to_floor_from_entry(17, '1', 4)
>>> compare_occupancies(the_horizons, the_spike)
There is the same number of occupants in both buildings.
>>> the_spike.leave_floor_from_entry(17, '1', 0)
...
quiz_8.BuildingError: That makes no sense!
>>> the_spike.leave_floor_from_entry(17, '1', 5)
...
quiz_8.BuildingError: There aren't that many people on that floor!
>>> the_spike.leave_floor_from_entry(17, '1', 3)
>>> the_horizons.leave_floor_from_entry(0, 'A', 1)
...
quiz_8.BuildingError: There aren't that many people on that floor!
>>> the_horizons.leave_floor_from_entry(0, 'B', 1)
>>> the_horizons.leave_floor_from_entry(0, 'B', 1)
>>> the_horizons.leave_floor_from_entry(0, 'B', 1)
>>> compare_occupancies(the_horizons, the_spike)
There is the same number of occupants in both buildings.
>>> the_horizons.leave_floor_from_entry(0, 'B', 1)
>>> compare_occupancies(the_horizons, the_spike)
There are more occupants in the second building.
>>> the_seaside.go_to_floor_from_entry(3, 'B', 1)
>>> the_seaside.go_to_floor_from_entry(3, 'B', 1)
Wait, lift has to go down 3 floors...
>>> the_seaside.go_to_floor_from_entry(3, 'B', 1)
Wait, lift has to go down 3 floors...
>>> the_seaside.go_to_floor_from_entry(3, 'B', 1)
Wait, lift has to go down 3 floors...
>>> the_seaside.leave_floor_from_entry(3, 'B', 2)
>>> the_seaside.leave_floor_from_entry(3, 'B', 2)
Wait, lift has to go up 3 floors...
>>> the_seaside.go_to_floor_from_entry(4, 'A', 10)
>>> the_seaside.go_to_floor_from_entry(5, 'A', 10)
Wait, lift has to go down 4 floors...
>>> the_seaside.go_to_floor_from_entry(2, 'A', 10)
Wait, lift has to go down 5 floors...
>>> the_seaside.leave_floor_from_entry(4, 'A', 2)
Wait, lift has to go up 2 floors...
>>> the_seaside.go_to_floor_from_entry(1, 'A', 10)
>>> the_seaside.leave_floor_from_entry(5, 'A', 2)
Wait, lift has to go up 4 floors...
>>> the_seaside.go_to_floor_from_entry(5, 'A', 10)
>>> the_seaside.leave_floor_from_entry(3, 'B', 2)
...
quiz_8.BuildingError: There aren't that many people on that floor!
>>> the_seaside.leave_floor_from_entry(2, 'A', 2)
Wait, lift has to go down 3 floors...