.py
files containing your code.This homework assignment must be submitted in Gradescope by Noon central time on Tuesday January 30, 2024.
Collaboration is prohibited, and you may only access resources (books, online, etc.) listed below.
This assignment corresponds to Worksheet 3, which involves operator overloading and inheritance.
The materials you may refer to for this homework are:
This homework assignment has 3 problems, numbered 2 and 3. The grading breakdown is:
Points | Item |
---|---|
4 | Autograder |
5 | Problem 2 |
5 | Problem 3 |
14 | Total |
The part marked "autograder" reflects points assigned to your submission based on some simple automated checks for Python syntax, etc. The result of these checks is shown immediately after you submit.
Ask your instructor or TA a question by email, in office hours, or on discord.
Put the code you write for this problem in hwk3prob2.py
.
In the next cell, you'll see code for a class that represents a traffic signal controlling a single direction of traffic. The signal is a panel of three lights (one red, one yellow, one green), and exactly one of them is illuminated at any given time. The state of the light can be referred to by the illumated color, by a state number, or by the intent of the signal, which relate as shown below:
state | color | intent |
---|---|---|
0 | red | stop |
1 | yellow | slow |
2 | green | go |
The class given below is functional, in that it supports setting, querying, and changing the state of the light. It can also display itself in various forms.
However, a couple of features are missing. After copying the template code below into hwk2prob2.py
, modify it to add the following features:
True
if it allows any flow of traffic (i.e. is green or yellow), and False
otherwise. Thus the boolean value answers the question "is any movement allowed?"A
and B
are traffic signal objects, then the equality test A==B
should evaluate to True
if the two signals are in the same state (i.e. color/intent) and False
otherwise.This means you should add some special methods to TrafficSignal
. Do not modify or remove any existing methods or attributes of the template.
# MCS 275 Spring 2024 Homework 3
# Template for problem 2 --- save this in a file called hwk3prob2.py
# and add the features requested in the problem
class TrafficSignal:
"""
Class representing the state of a 3-color traffic signal (AKA traffic light)
controlling one direction of traffic. It can be in three states:
state 0 = red light = STOP = no traffic is allowed to pass the signal
state 1 = yellow light = SLOW = traffic at or near signal can proceed, others stop
state 2 = green light = GO = traffic can proceed normally
"""
color_map = ("red","yellow","green")
intent_map = ("stop","slow","go")
def __init__(self,state=None,color=None,intent=None):
"""
Initialize new traffic light according to a state number (0,1,2),
color name (red,yellow,green), or intent (stop,slow,go). Only one
of the arguments can be given. Initially red if no arguments given.
"""
self.state = 0 # default red
args_possible = [state,color,intent]
args_given = [ a for a in args_possible if a is not None ]
if not args_given:
# No arguments, so keep default red. We're done.
return
if len(args_given) > 1:
raise ValueError("Can only specify one of `state`, `color`, `intent`.")
# Now we know exactly one argument given. Which one?
if state is not None:
self.state = state
elif color is not None:
try:
self.state = self.color_map.index(color.lower())
except ValueError:
raise ValueError("Unrecognized color: "+str(color))
elif intent is not None:
try:
self.state = self.intent_map.index(intent.lower())
except ValueError:
raise ValueError("Unrecognized intent: "+str(intent))
def get_state(self):
"get the current state number"
return self.state
def get_color(self):
"get the current color"
return self.color_map[self.state]
def get_intent(self):
"get the current intent"
return self.intent_map[self.state]
def set_state(self,i):
"set the current state number"
if not isinstance(i,int):
raise TypeError("State must be an integer")
if s not in (0,1,2):
raise ValueError("Invalid state {}".format(repr(i)))
self.state = i
def set_color(self,c):
"set the light color"
if not isinstance(c,str):
raise TypeError("Color must be a string")
if c.lower() not in self.color_map:
raise ValueError("Invalid color {}".format(repr(c)))
self.state = self.color_map.index(c.lower())
def set_intent(self,t):
"set the signal intent"
if not isinstance(t,str):
raise TypeError("Intent must be a string")
if t.lower() not in self.intent_map:
raise ValueError("Invalid intent {}".format(repr(t)))
self.state = self.intent_map.index(t.lower())
def advance(self):
"advance to the next state in the usual green-yellow-red-green-... cycle"
self.state = (self.state-1)%3
def show(self):
"display with unicode characters"
for i in range(3):
print("\U0001F534\U0001F7E1\U0001F7E2\u26AB"[i if i==self.state else -1])
def __str__(self):
"Human-readable string"
return "{}[{}={}={}]".format(self.__class__.__name__,self.state,self.get_color(),self.get_intent())
def __repr__(self):
"String for use in the REPL (evaluates to a copy of this object)"
return "{}(state={})".format(self.__class__.__name__,self.state)
TrafficSignal
class works¶Feel free to skip this section. It's here in case you've been reading the code for the template TrafficSignal
class and find it confusing or difficult, and want to see an example of how it would be used.
# Three ways to create a yellow light
T = TrafficSignal(state=1) # by state number
T = TrafficSignal(intent="slow") # by intent (meaning)
T = TrafficSignal(color="yellow") # by color
# Display the traffic signal as a descriptive string
print(T)
# Display the traffic signal as an expression that would generate a copy of it
T
# When made with no arguments, the traffic signal will start red
T = TrafficSignal()
print(T) # descriptive
T.show() # text graphics
# The `.advance()` method will move to the "next" color
print("Initial:")
T.show()
for k in range(3):
T.advance()
print("Advanced {} times:".format(k))
T.show()
print()
# We can change the state of the signal arbitrarily.
# Here we do it by specifying intent but set_color
# and set_state work analogously.
T = TrafficSignal(intent="go") # initially green
print(T)
T.set_intent("stop") # now make it red
print(T)
# You can ask the signal for its current color
# E.g. here are the colors in a full cycle
for _ in range(3):
T.advance()
print(T.get_color())
# You can ask the signal for its current intent (meaning)
# E.g. here are the intents in a full cycle
for _ in range(3):
T.advance()
print(T.get_intent())
TrafficSignal
should behave when you're done¶The cells below were tested against a solution to the exercise. They check the boolean coercion and equality testing behavior. You can run the same code to check your work.
signalsA = [ TrafficSignal(state=i) for i in range(3) ]
boolsA = [ False, True, True ]
looks_good = True
for i in range(3):
actual = bool(signalsA[i])
expected = boolsA[i]
agree = actual==expected
looks_good = looks_good and agree
print("{}: bool({} signal) is {}".format(
"OK" if agree else "ERROR",
signalsA[i].get_color(),
actual,
))
print("\nBoolean coercion","is working \U0001F60A" if looks_good else "IS NOT WORKING CORRECTLY \U0001F6A9")
signalsA = [ TrafficSignal(state=i) for i in range(3) ]
signalsB = [ TrafficSignal(state=i) for i in range(3) ]
looks_good = True
for i in range(3):
for j in range(3):
actual = signalsA[i]==signalsB[j]
expected = i==j
agree = actual==expected
looks_good = looks_good and agree
print("{}: {}=={} evaluates to {}".format(
"OK" if agree else "ERROR",
signalsA[i].get_color(),
signalsB[j].get_color(),
actual,
))
print("\nEquality testing","is working \U0001F60A" if looks_good else "IS NOT WORKING CORRECTLY \U0001F6A9")
Put the code you write for this problem in hwk3prob3.py
.
This problem continues the work on Bot
subclasses that we began in lecture by creating bots.py, and which you also worked on in Worksheet 3.
Create another subclass of Bot
called SlowStartBot
with the following behavior:
position
, a Point2
specifying the starting positiondirection
, a Vector2
specifying the movement directioninitial_delay
, an integer indicating how "gradual" the acceleration will be.update()
is called repeatedly, the robot should behave as follows:initial_delay
time stepsdirection
initial_delay-1
time steps (assuming that is positive)direction
initial_delay-2
time steps (assuming that is position)direction
on each time step thereafterThus, the class is used for a robot that initially spends a lot of time waiting around instead of moving, but gradually the pauses get shorter until it eventually moves on each time step.
The cell below shows an example of how the class might be instantiated.
from hwk3prob3 import SlowStartBot
from plane import Point2, Vector2
S = SlowStartBot(position=Point2(6,4), direction=Vector2(-1,1), initial_delay=4)