Introduction to Computer Science II
Homework 2
Due by 11:50am on Tuesday, January 18
Reading
Read chapter 8 and the week 2 lecture notes.
Problems
Solve the following by implementing the corresponding functions in homework2.py. When done, submit that file
through D2L.
1. Implement a class Polygon that
abstracts regular polygons and supports class methods:
- __init__(): A constructor that takes as input the
number of sides and the side length of a regular n-gon (n-sided
polygon) object. Your constructor should use default values 3
and 1 for the number of sides and side length,
respectively, when no arguments are passed
- perimeter(): Returns the perimeter of the n-gon
object.
- area(): returns the area of the n-gon object.
Note: The area of a regular polygon with n sides of length s
is
s**2 * n / (4 * tan(pi/n))
where pi is the mathematical constant Pi and tan is the trig
function tan().
Usage:
>>> p = Polygon(4,1)
>>> p.perimeter()
4
>>> p.area()
1.0000000000000002
>>> p = Polygon(6,1)
>>> p.area()
2.5980762113533165
>>> p.perimeter()
6
>>> p = Polygon()
>>> p.perimeter()
3
>>> p.area()
0.43301270189221946
>>> p = Polygon(n=4)
>>> p.area()
1.0000000000000002
>>> p.perimeter()
4
2. Overload appropriate operators for class
Card so that you can compare cards based on rank. Use the
following ranking: 2 < 3 < 4 < 5< 6 < 7 < 8 < 9
< 10 < J < Q < K < A.
Usage:
>>> d = Deck()
>>> d.shuffle()
>>> a = d.dealCard()
>>> b = d.dealCard()
>>> c = d.dealCard()
>>> a
Card('8', '♣')
>>> b
Card('2', '♡')
>>> c
Card('7', '♣')
>>> a < b
False
>>> c > b
True
>>> a <= a
True
>>> a >= c
True
3. Develop a class BankAccount that
supports these methods:
- __init__(): Initializes the bank account balance to
the value of the input argument, or to 0 if no input
argument is given
- withdraw(): Takes an amount as input and withdraws it
from the balance
- deposit(): Takes an amount as input and adds it to
the balance
- balance(): Returns the balance on the account
Usage:
>>> x = BankAccount(700)
>>> x.balance()
700
>>> x.withdraw(70)
>>> x.balance()
630
>>> x.deposit(7)
>>> x.balance()
637
4. Develop a class Craps that allows
you to play craps on your computer. (The craps rules are described
in homework assignment 1.) Your class will support methods:
- __init__(): Starts by rolling a pair of dice. If the
value of the roll (i.e., the sum of the two dice) is 7
or 11, then a winning message is printed. If the value
of the roll is 2, 3, or 12, then a
losing message is printed. For all other roll values, a message
telling the user to throw for point is printed.
- forPoint(): Generates a roll of a pair of dice and,
depending on the value of the roll, prints one of three messages
as appropriate (and as shown):
Usage:
>>> c = Craps()
Throw total: 11. You won!
>>> c = Craps()
Throw total: 2. You lost!
>>> c = Craps()
Throw total: 5. Throw for Point.
>>> c.forPoint()
Throw total: 6. Throw for Point.
>>> c.forPoint()
Throw total: 5. You won!
>>> c = Craps()
Throw total: 4. Throw for Point.
>>> c.forPoint()
Throw total: 7. You lost!
5. Implement class Random that
implements a linear congruential pseudorandom number generator. In
other words, it is used to generate a sequence of pseudorandom
integers using a linear congruential generator approach.
The linear congruential method generates a sequence of numbers (or
seeds) starting from a given seed number x. Each number
(seed) in the sequence will be obtained by applying a (math)
function f (x) on the previous number (seed) x in
the sequence. The precise function f (x) is defined by three
numbers: a (the multiplier), c (the increment), and
m (the modulus):
f(x) = (ax + c) mod m
For example, if m = 31, a = 17, and c = 7,
the linear congruential method would generate the next sequence of
numbers (seeds) starting from seed x = 12:
12,25,29,4,13,11,8,19,20, . . .
because f (12) = 25, f (25) = 29, f (29) = 4,
and so on.
The class Random should support methods:
- __init__(): Constructor that takes as input the
values a, x, c, and m
and initializes the Pseudorandom object.
- rand(): Generates and returns the next number (seed)
in the pseudorandom sequence
Usage:
>>> r = Random(12, 17, 7, 31)
>>> r.rand()
25
>>> r.rand()
29
>>> r.rand()
4
>>> r.rand()
13
>>> r.rand()
11
6. The numbers 17, 7, and 31
used for a (the multiplier), c (the increment), and
m (the modulus) in the above example do not result in a good
pseudorandom number generator. Much better values, used by the gcc C
compiler library, are a=1103515245, c=12345, and m=231
(2 to the power 31). These number will generate pseudorandom numbers
in the range from 0 to 231-1
with very good "random properties". Also, while good for debugging
your implementation, it is inconvenient to have to provide a seed to
the pseudorandom number generator. Much better would be to use an
integer related to the current time, in nanoseconds. The time()
function in the Python standard library module time gives
the number of seconds since January 1, 1970:
>>> import time
>>> time.time()
1579100035.550304
>>> time.time()
1579100036.813396
To get the number of nanoseconds since January 1, 1970 as an integer
we need to multiply time.time() by a billion and convert
to int:
>>> int(time.time()*10**9)
1579099881394504960
>>> int(time.time()*10**9)
1579099882719621888
Modify your class Random so that default values, as
specified above, for the seed, the multiplier, the increment, and
the modulus are used when no values are passed when constructing the
Random object.
Usage:
>>> r = Random()
>>> r.rand()
1435472185
>>> r.rand()
2004247422
>>> r.rand()
1630335199
>>> r.rand()
592381941
(NOTE: because the seed will be a function of the current
time when executing the constructor, your output will necessarily
be different)
7. Augment your Random class with
two additional methods:
- randint(a, b) that returns a random integer in the
range from a to b (included), uniformly
distributed at random. Your implementation must use the existing
Random method rand() to generate a number
between 0 and 231-1 and
then perform some arithmetic operations on it to obtain a number
in the range from a to b. (Hint: use %
modulus operator)
- random() that returns a random float in the range
from 0 to 1 (not included), uniformly
distributed at random. Your implementation must use the existing
Random method rand() to generate a number
between 0 and 231-1 and
then perform some arithmetic operations on it to obtain a float
in the range from 0 to 1. (Hint: use / division operator)
Usage:
>>> r.randint(1, 6)
4
>>> r.randint(1, 6)
3
>>> r.randint(1, 6)
6
>>> r.randint(1, 6)
5
>>> r.randint(1, 6)
4
>>> r.random()
0.2017026348039508
>>> r.random()
0.4628330278210342
>>> r.random()
0.09002611227333546
>>> r.random()
0.34171303221955895
>>> r.random()
0.2796304449439049
>>> r.random()
0.9617379498668015
>>> r.random()
0.37306692358106375
>>> r.random()
0.5769595871679485
>>> r.random()
0.18874327652156353