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.

 

What to try

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.

 

What to do

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.

 

Changing 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.