Skip to content
Snippets Groups Projects
Commit 4949ffa6 authored by W. Spencer Smith's avatar W. Spencer Smith
Browse files

Addition of A1 Solution.

parent ab90b459
No related branches found
No related tags found
No related merge requests found
PY = python
PYFLAGS =
DOC = doxygen
DOCFLAGS =
DOCCONFIG = circdoc
SRC = src/testCircles.py
.PHONY: all test doc clean
test:
$(PY) $(PYFLAGS) $(SRC)
doc:
$(DOC) $(DOCFLAGS) $(DOCCONFIG)
cd latex && $(MAKE)
all: test doc
clean:
rm -rf html
rm -rf latex
This diff is collapsed.
## @file CircleADT.py
# @author Steven Palmer
# @brief Provides the CircleT ADT class for representing circles
# @date 1/12/2017
from math import pi, sqrt
## @brief An ADT that represents a circle
class CircleT:
## @brief CircleT constructor
# @details Initializes a CircleT object with a cartesian coordinate center
# and a radius
# @param x The x coordinate of the circle center
# @param y The y coordinate of the circle center
# @param r The radius of the circle
# @exception ValueError Throws if supplied radius is negative
def __init__(self, x, y, r):
if(r < 0):
raise ValueError("Radius cannot be negative")
self.__x = x
self.__y = y
self.__r = r
## @brief Gets the x coordinate of the circle center
# @return The x coordinate of the circle center
def xcoord(self):
return self.__x
## @brief Gets the y coordinate of the circle center
# @return The y coordinate of the circle center
def ycoord(self):
return self.__y
## @brief Gets the radius of the circle
# @return The radius of the circle
def radius(self):
return self.__r
## @brief Calculates the area of the circle
# @return The area of the circle
def area(self):
return pi * self.__r ** 2
## @brief Calculates the circumference of the circle
# @return The circumference of the circle
def circumference(self):
return 2 * pi * self.__r
## @brief Determines if circle is contained within a box
# @details The circles edges may overlap with
# the bounds of the box and still be considered contained.
# @param x x coordinate of top left corner of box
# @param y y coordinate of top left corner of box
# @param w Width of box
# @param h Height of box
# @return Returns true if the circle is contained within the box; false if not
def insideBox(self, x, y, w, h):
left = x <= (self.__x - self.__r)
right = (x + w) >= (self.__x + self.__r)
top = y >= (self.__y + self.__r)
bot = (y - h) <= (self.__y - self.__r)
return left and right and top and bot
## @brief Determines whether the circle intersects another circle
# @details This function treats circles as filled objects: circles completely
# inside other circles are considered as intersecting, even though
# their edges do not cross. The set of points in each circle
# includes the boundary (closed sets).
# @param c Circle to test intersection with
# @return Returns true if the circles intersect; false if not
def intersect(self, c):
xDist = self.__x - c.xcoord()
yDist = self.__y - c.ycoord()
centerDist = sqrt(xDist ** 2 + yDist ** 2)
rSum = self.__r + c.radius()
return rSum >= centerDist
## @brief Scales the radius of the circle
# @param k Scaling factor
def scale(self, k):
self.__r *= k
## @brief Translates the center of the circle
# @param dx Distance to translate the center x coordinate
# @param dy Distance to translate the center y coordinate
def translate(self, dx, dy):
self.__x += dx
self.__y += dy
## @file Statistics.py
# @author Steven Palmer
# @brief Provides statistics functions for the CircleT class
# @date 1/12/2017
import numpy
from CircleADT import *
## @brief Calculates the average radius of a list of circles
# @param circles List of CircleT
# @return Average radius of the list of CircleT
def average(circles):
radii = [c.radius() for c in circles]
return numpy.average(radii)
## @brief Calculates the standard deviation of the radii of a list of circles
# @param circles List of CircleT
# @return Standard deviation of the radii of the list of CircleT
def stdDev(circles):
radii = [c.radius() for c in circles]
return numpy.std(radii)
## @brief Ranks a list of circles by radius
# @details Given a list of n circles, this function provides a list of integer
# rankings 1 through n that rank the circles by radius (descending).
# The positions of the ranks in the returned list correspond to the
# positions of the circles in the list of circles. In the case of ties,
# the dense ranking scheme (as defined at https://en.wikipedia.org/wiki/Ranking)
# is used.
# @param circles List of CircleT
# @return List of rankings
def rank(circles):
radii = [c.radius() for c in circles]
vsmall = float("-inf")
ranking = [0 for x in radii]
rank_curr = 0
for i in range(len(radii)):
m_curr = max(radii)
j = radii.index(m_curr)
if rank_curr == 0 or m_curr != m_prev:
rank_curr += 1
ranking[j] = rank_curr
radii[j] = vsmall
m_prev = m_curr
return ranking
from CircleADT import *
from Statistics import *
from math import sqrt
# for testing floating point equality after arithmetic
# from Python development documentation:
# https://www.python.org/dev/peps/pep-0485/#proposed-implementation
def isClose(a, b, rel_tol = 1e-09, abs_tol = 0.0):
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
# @brief Tests the xcoord method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT xcoord method
def test_xcoord():
global testTot, passed
testTot += 1
try:
assert c1.xcoord() == 1
assert c2.xcoord() == -3
assert c3.xcoord() == -2
assert c4.xcoord() == 1e-10
assert c5.xcoord() == 1e10
passed += 1
print("xcoord test PASSED.")
except AssertionError:
print("xcoord test FAILED.")
# @brief Tests the ycoord method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT ycoord method
def test_ycoord():
global testTot, passed
testTot += 1
try:
assert c1.ycoord() == 0
assert c2.ycoord() == -5
assert c3.ycoord() == 5
assert c4.ycoord() == 1e-10
assert c5.ycoord() == 1e10
passed += 1
print("ycoord test PASSED.")
except AssertionError:
print("ycoord test FAILED.")
# @brief Tests the radius method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT radius method
def test_radius():
global testTot, passed
testTot += 1
try:
assert c1.radius() == 2
assert c2.radius() == 5.25
assert c3.radius() == 10
assert c4.radius() == 1e-10
assert c5.radius() == 1e10
passed += 1
print("radius test PASSED.")
except AssertionError:
print("radius test FAILED.")
# @brief Tests the area method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT area method
def test_area():
global testTot, passed
testTot += 1
try:
assert isClose(c1.area(), 12.566370614359172953850573533118)
assert isClose(c2.area(), 86.590147514568676135126608251641)
assert isClose(c3.area(), 314.15926535897932384626433832795)
assert isClose(c4.area(), 3.1415926535897932384626433832795e-20)
assert isClose(c5.area(), 3.1415926535897932384626433832795e20)
passed += 1
print("area test PASSED.")
except AssertionError:
print("area test FAILED.")
# @brief Tests the circumference method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT circumference method
def test_circumference():
global testTot, passed
testTot += 1
try:
assert isClose(c1.circumference(), 12.566370614359172953850573533118)
assert isClose(c2.circumference(), 32.986722862692829003857755524435)
assert isClose(c3.circumference(), 62.83185307179586476925286766559)
assert isClose(c4.circumference(), 6.283185307179586476925286766559e-10)
assert isClose(c5.circumference(), 6.283185307179586476925286766559e10)
passed += 1
print("circumference test PASSED.")
except AssertionError:
print("circumference test FAILED.")
# @brief Tests the insideBox method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT insideBox method. One of the tests covers the edge
# case in which the edge of the circle and the edge of the box
# are touching.
def test_insideBox():
global testTot, passed
testTot += 1
x = -12
y = 100
w = 20
h = 110
try:
assert c1.insideBox(x, y, w, h)
assert not c2.insideBox(x, y, w, h)
assert c3.insideBox(x, y, w, h)
assert c4.insideBox(x, y, w, h)
assert not c5.insideBox(x, y, w, h)
passed += 1
print("insideBox test PASSED.")
except AssertionError:
print("insideBox test FAILED.")
# @brief Tests the intersect method of the CircleT class
# @details Checks for equality between actual and expected values for
# the CircleT intersect method. One of the tests covers the edge
# case in which the edges of the circles are touching.
def test_intersect():
global testTot, passed
testTot += 1
ct = CircleT(1,1,sqrt(2))
try:
assert c1.intersect(ct)
assert not c2.intersect(ct)
assert c3.intersect(ct)
assert c4.intersect(ct)
assert not c5.intersect(ct)
passed += 1
print("intersect test PASSED.")
except AssertionError:
print("intersect test FAILED.")
# @brief Tests the scale method of the CircleT class
# @details Checks for equality between actual and expected values for
# the radius of CircleT objects after scale has been called.
def test_scale():
global testTot, passed
testTot += 1
# use new local circles since they will be mutated
c1 = CircleT(1,0,2)
c2 = CircleT(-3,-5,5.25)
c3 = CircleT(-2,5,10)
c4 = CircleT(1e-10,1e-10,1e-10)
c5 = CircleT(1e10,1e10,1e10)
c1.scale(1)
c2.scale(2)
c3.scale(10)
c4.scale(1e-10)
c5.scale(1e10)
try:
assert isClose(c1.radius(), 2)
assert isClose(c2.radius(), 10.5)
assert isClose(c3.radius(), 100)
assert isClose(c4.radius(), 1e-20)
assert isClose(c5.radius(), 1e20)
passed += 1
print("scale test PASSED.")
except AssertionError:
print("scale test FAILED.")
# @brief Tests the translate method of the CircleT class
# @details Checks for equality between actual and expected values for
# the x and y coordinates of CircleT objects after translate
# has been called.
def test_translate():
global testTot, passed
testTot += 1
# use new local circles since they will be mutated
c1 = CircleT(1,0,2)
c2 = CircleT(-3,-5,5.25)
c3 = CircleT(-2,5,10)
c4 = CircleT(1e-10,1e-10,1e-10)
c5 = CircleT(1e10,1e10,1e10)
c1.translate(0,0)
c2.translate(1,1)
c3.translate(-5,10)
c4.translate(1e-10, -1e-10)
c5.translate(-1e10, -1e10)
try:
assert c1.xcoord() == 1 and c1.ycoord() == 0
assert c2.xcoord() == -2 and c2.ycoord() == -4
assert c3.xcoord() == -7 and c3.ycoord() == 15
assert c4.xcoord() == 2e-10 and c4.ycoord() == 0
assert c5.xcoord() == 0 and c5.ycoord() == 0
passed += 1
print("translate test PASSED.")
except AssertionError:
print("translate test FAILED.")
# @brief Tests the average function of the Statistics module
# @details Checks for equality between actual and expected values for
# the output of the Statistics average function on a list of CircleT.
def test_average():
global testTot, passed
testTot += 1
try:
assert isClose(average(circles), 2000000003.45)
passed += 1
print("average test PASSED.")
except AssertionError:
print("average test FAILED.")
# @brief Tests the stdDev function of the Statistics module
# @details Checks for equality between actual and expected values for
# the output of the Statistics stdDev function on a list of CircleT.
def test_stdDev():
global testTot, passed
testTot += 1
try:
assert isClose(stdDev(circles), 3999999998.275)
passed += 1
print("stdDev test PASSED.")
except AssertionError:
print("stdDev test FAILED.")
# @brief Tests the rank function of the Statistics module
# @details Checks for equality between actual and expected values for
# the output of the Statistics rank function on a list of CircleT.
# Two circles with the same radius are included in the list to
# cover the edge case in which the ranked list has ties.
def test_rank():
global testTot, passed
testTot += 1
rankCircles = circles
rankCircles.append(c1) # for testing ties
try:
assert rank(circles) == [4,3,2,5,1,4]
passed += 1
print("rank test PASSED.")
except AssertionError:
print("rank test FAILED.")
c1 = CircleT(1,0,2)
c2 = CircleT(-3,-5,5.25)
c3 = CircleT(-2,5,10)
c4 = CircleT(1e-10,1e-10,1e-10)
c5 = CircleT(1e10,1e10,1e10)
circles = [c1,c2,c3,c4,c5]
testTot = 0
passed = 0
test_xcoord()
test_ycoord()
test_radius()
test_area()
test_circumference()
test_insideBox()
test_intersect()
test_scale()
test_translate()
test_average()
test_stdDev()
test_rank()
print ('\n%d of %d tests passed.') % (passed, testTot)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment