Lab 3 Part 0: Planning and Set up
You may have noticed that this task (programming Lights
On) is bigger than what we've asked you to do so far. This program will require
more than one function, and some planning about how to organize the data the
game needs to keep track of and how the functions interact and modify this
data.
If you haven't already, create a new file called hw3pr1.py
and put the usual header at the top of that
file:
# Homework 3, Problem 1, done in lab
# James Bond
# April 23, 2017
Planning
your program
Although we will lead you through the decomposition of
this problem, we'd like you to do some brainstorming to help you practice
breaking a problem down into smaller pieces. Without looking ahead, in comments
at the top of that file, answer the following:
Try to be specific, describing what you could do with a
very short function (e.g., one of the things you program will need to do might
be "Take input from the user about which light they want to toggle")
Implementing the program, piece by
piece
A central piece of data to keep track of, which you
likely noted above, is the current state of the board. One of the central
pieces of functionality will be to modify this data after each turn, in
response to the user's input. This first section explores how we will represent
the board state, and has you write a number of functions that modify this data
in various ways.
To simplify things, we will work with a 1D version of
the game, where the lights exist in a row, rather than a grid. As you might
have already guessed, we will use a list to store the current state of the
board.
In this section, we will not yet implement the data
modifications for Lights On, nor will we (yet) respond to user input. That will
come later. The purpose of this section is simply for you to practice modifying
the values in a list.
Code
to start with
Copy these three functions (and import lines) into your hw3pr1.py file:
import time # provides
time.sleep(0.5)
from random import * # provides
choice( [0,1] ), etc.
import sys # larger recursive
stack
sys.setrecursionlimit(100000) #
100,000 deep
def runGenerations( L ):
""" runGenerations keeps
running evolve...
"""
print(L) #
display the list, L
time.sleep(0.5) # pause a bit
newL = evolve( L ) # evolve L into newL
runGenerations( newL ) # recurse
def evolve( L ):
""" evolve takes in a list of
integers, L,
and returns a new list of integers
considered to be the "next
generation"
"""
N = len(L)
# N now holds the size of the list L
return [ setNewElement( L, i ) for i in
range(N) ]
def setNewElement( L, i, x=0 ):
""" setNewElement returns the
NEW list's ith element
input L: any list of integers
input i: the index of the new element to
return
input x: an extra, optional input for future
use
"""
return L[i] + 1
One note on this code: the x=0 in the third input to setNewElement is an optional
input. That is, if you provide a third input to setNewElement,
the
value you provide becomes
x.
However, if you do not provide a third input, the value x = 0 is used instead. Here, x isn't
used, though it will be in the future.
Save and load your code with F5. Then, at the Python
shell prompt, run
>>> runGenerations( [1,2,3] )
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
You'll need to type control-c to stop the
function - otherwise it will run until its memory runs out.
Write a comment of 2-3 sentences describing what's
happening in the above example. Be sure to include a brief description of how
each of the three functions contributes to the behavior. Remember that you can
use Python's per-line comment character, #, or
you can simply place your comments in a triple-quoted string in your hw3pr1.py file.
"""
like this
"""
NOTE:
To succeed in this lab, it is extremely important that you understand exactly how
and why runGenerations
works. If you aren't 100%
certain you understand what's going on, ask for help. Later problems will
depend on your understanding of runGenerations, evolve, and setNewElement.
For each of the following questions, define a new
function named setNewElement that produces the desired
sequence of lists. There is a completed example in Question 0.
Python can have many functions of the same name
in a single file. This is sometimes helpful if you want to switch around as you
test things. It is the last one in the file that will be used when you
import that file. The last function "redefines" any others of the
same name that appear earlier in the file. For each of these questions, paste a
new setNewElement function at the bottom of
your file, and then change it to match the behavior you want. That way, all of
the intermediate versions will still be in your file (but only the last will be
used).
Question 0
Write
a setNewElement function that yields the
following behavior:
>>> runGenerations( [1,2,3] )
[1, 2, 3]
[2, 4, 6]
[4, 8, 12]
[8, 16, 24]
[16, 32, 48]
[32, 64, 96]
[64, 128, 192]
Answer to Question 0
The
idea here is that each output element is double the corresponding input
element. Thus, the code is the following, simply cut, pasted, and modified from
the old setNewElement:
def setNewElement( L, i, x=0 ):
""" setNewElement returns the
NEW list's ith element
input L: any list of integers
input i: the index of the new element to
return
input x: an extra, optional input for future
use
"""
return L[i]*2
Question 1
Write
a setNewElement function that yields the
following behavior:
>>> runGenerations( [1,2,3] )
[1, 2, 3]
[1, 8, 27]
[1, 512, 19683]
Question 2
This
example uses a slightly longer initial list. Write a setNewElement function that yields the following
behavior:
>>> runGenerations( [1,2,3,4,5,42] )
[1, 2, 3, 4, 5, 42]
[42, 1, 2, 3, 4, 5]
[5, 42, 1, 2, 3, 4]
[4, 5, 42, 1, 2, 3]
[3, 4, 5, 42, 1, 2]
[2, 3, 4, 5, 42, 1]
[1, 2, 3, 4, 5, 42]
[42, 1, 2, 3, 4, 5]
[5, 42, 1, 2, 3, 4]
Hint: each returned value is
the value from the old list, L, one index to the left (lower)
than the current index. Thus, the return line will be
return L[ SOMETHING ]
where SOMETHING is a very short expression involving i and 1.
Question 3
Write
a setNewElement function that yields the
following behavior:
>>> runGenerations( [1,2,3,4,5,42] )
[1, 2, 3, 4, 5, 42]
[2, 3, 4, 5, 42, 1]
[3, 4, 5, 42, 1, 2]
[4, 5, 42, 1, 2, 3]
[5, 42, 1, 2, 3, 4]
[42, 1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 42]
[2, 3, 4, 5, 42, 1]
Hint: this is the opposite of
the previous example. However, depending on how you implement it, you may need
an if and an else to
handle the very last column.
A random list generator...
Write
a setNewElement function that yields a
random list of 0s and 1s with each
genetation. It completely ignores the input list! For example (and lots of other
behaviors could occur, as well):
>>> runGenerations( [1,2,3,4,5,42] )
[1, 2, 3, 4, 5, 42]
[0, 0, 1, 1, 1, 0]
[0, 0, 1, 1, 0, 0]
[1, 0, 0, 1, 0, 0]
[0, 1, 0, 1, 1, 0]
[0, 0, 0, 1, 0, 0]
Reminder: the random-choice
function is choice(
[0,1] ) --
that's all you'll need!
The next part of the lab will build on this
randomly-evolving behavior.
This link
continues with the lab -- with the same hw3pr1.py file.