For the below given exercise:
Exercise 7: Abstracting Rectangles
Implement a representation for rectangles in a plane. (Hint: You may want to make use of your procedures from exercise 5). Then, in terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle.
where exercise 5 is:
Consider the problem of representing line segments in a plane. Each segment is represented as a pair of points: a starting point and an ending point. Define a constructor make-segment and selectors start-segment and end-segment that define the representation of segments in terms of points. Furthermore, a point can be represented as a pair of numbers: the x coordinate and the y coordinate. Accordingly, specify a constructor make-point and selectors x-point and y-point that define this representation. Finally, using your selectors and constructors, define a procedure midpoint-segment that takes a line segment as argument and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints)
Below is the solution:
# point.py
# Representation - start
from operator import sub, mul
from math import sqrt
#Constructor
def make_point(x, y):
return (x, y)
#Selector
def x_coordinate(point):
return point[0]
#Selector
def y_coordinate(point):
return point[1]
#Selector
def distance_between_points(p1, p2):
return sqrt(square(sub(p1[0],p2[0])) + square(sub(p1[1],p2[1])))
#helper for selector
def square(a):
return mul(a, a)
#Representation - end
#Use - start
def get_x_coordinate(point):
return x_coordinate(point)
def get_y_coordinate(point):
return y_coordinate(point)
#Use - end
# segment.py
# Representation - start
from point import distance_between_points, make_point, get_x_coordinate, get_y_coordinate
#Constructor
def make_segment(point1, point2):
return (point1, point2)
#Selector
def start_segment(lineSegment):
return lineSegment[0]
#Selector
def end_segment(lineSegment):
return lineSegment[1]
#Representation - end
#Use -start
def midpoint_segment(lineSegment):
return make_point((get_x_coordinate(start_segment(lineSegment)) + get_x_coordinate(end_segment(lineSegment)))/2, (get_y_coordinate(start_segment(lineSegment)) + get_y_coordinate(end_segment(lineSegment)))/2)
def get_size(lineSegment):
return distance_between_points(start_segment(lineSegment), end_segment(lineSegment))
#Use - end
#Driver code from user
if __name__ == "main":
p1 = make_point(1,2)
p2 = make_point(3, 4)
line = make_segment(p1, p2)
midpoint = midpoint_segment(line)
print(midpoint)
# rectangle.py
# Representation - start
from point import make_point, get_x_coordinate, get_y_coordinate
from segment import get_size
from operator import sub, abs
#Constructor
def make_rectangle(p1, p2, p3, p4):
if are_opposite_sides_equal(p1, p2, p3, p4):
return (p1, p2, p3, p4)
#Helper for constructor
def are_opposite_sides_equal(p1, p2, p3, p4):
if (abs(sub(get_x_coordinate(p1), get_x_coordinate(p2))) == abs(sub(get_x_coordinate(p3), get_x_coordinate(p4)))) and (abs(sub(get_y_coordinate(p2), get_y_coordinate(p3))) == abs(sub(get_y_coordinate(p1), get_y_coordinate(p4)))):
return True
else:
return False
#Selector
def get_length_side_segment(quadruple):
return (quadruple[0], quadruple[1])
#Selector
def get_breadth_side_segment(quadruple):
return (quadruple[1], quadruple[2])
#Representation - end
#Use -start
def perimeter(rectangle):
segment1 = get_length_side_segment(rectangle)
segment2 = get_breadth_side_segment(rectangle)
length = get_size(segment1)
breadth = get_size(segment2)
return 2 * (length + breadth)
def area(rectangle):
segment1 = get_length_side_segment(rectangle)
segment2 = get_breadth_side_segment(rectangle)
length = get_size(segment1)
breadth = get_size(segment2)
return (length * breadth)
#Use - end
#Driver code from user
if __name__ == "main":
p1 = make_point(1, 1)
p2 = make_point(3, 1)
p3 = make_point(3, 3)
p4 = make_point(1, 3)
rectangle = make_rectangle(p1, p2, p3, p4)
peri = perimeter(rectangle)
area_value = area(rectangle)
print(peri)
print(area_value)
Here the "constructor" and "selectors" constitute the "Abstract data type" in each module holding some invariants:
Invariant1:
If we construct point p
from x-coordinate a
and y-coordinate b
, then x_coordinate(p), y_coordinate(p)
must equal a, b
Invariant2:
If we construct a line segment l
from point p1
and point p2
, then start_segment(l)______end_segment(l)
must equal p1______p2
constructor and selectors are part of representation in each module.
Data abstraction is to enforce barrier between "representation" and "Use".
My questions:
Based on the above points, Is the Data abstraction between 3 modules and within each module looks correct?
What is the behaviour condition (invariant) that constructor and selectors of rectangle supports?