Research Ideas - Northwestern University



EECS110 Homework 3, Spring 2009

Due: 11:59pm on Sunday April 26, 2009

Submission: submit your solutions at the submissions server

If you are working on lab problems, please go to:



You should do the first problem for Lab1.

Problems:

Problem 1: Evolving Lists and Lights On! (hw3pr1.py) [35 points; individual or pair]

Week 3, Problem 1: Evolving Lists and Lights On!

[35 points; individual or pair]

Submission: This lab has four parts. Because each builds on the last, please create only one file, named hw3pr1.py and add to it throughout the lab. Please submit your hw3pr1.py file to the submission server.

The bird's-eye view

The end goal of this lab is to build a game called "Lights On" (alternatively, "Lights Out", but that seemed so gloomy to us). "Lights On" is played with a grid of lights which are either on or off.

The goal in Lights On is to turn all of the lights in the initial grid on. Each time the user selects a light, that light toggles from 0 to 1 or from 1 to 0. The challenge is that the neighboring light(s) ALSO toggle. That is, the one, two, three or four lights directly to the N, S, E and W of the selected light also change state (either on to off, or off to on). The lights do not "wrap-around": e.g., the leftmost light is not a neighbor to the rightmost light.

You can play a version of Lights Out here:

This lab will guide you in developing several Python functions that will allow you to implement this game. In doing so, we will introduce and reinforce the concepts of

• decomposing problems into small pieces, i.e., functions

• composing functions to create more powerful ones

• recursion: writing functions in terms of themselves

• representing data as list (both 1D and 2D)

• design/test/repeat: cs is fundamentally exploratory, and this lab offers several open-ended problems...

Lab 3, Part 0: Set up

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

# John Smith

# April 21, 2009

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:

• What data will your program need to keep track of?

• What will your program need to do with that data?

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, 4, 9]

[1, 16, 81]

[1, 256, 6561]

[1, 65536, 43046721]

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.

Lab 3, Part 1: Counting generations

Lab 3 Part 1: Counting generations

At the moment, the runGenerations function has evolved its input lists in a number of ways, but it so far has not evolved them for any purpose or to achieve any particular result.

In the game of Lights On, the goal is to evolve the list so that all of its values are "on". Throughout the rest of the lab, we will use 1 to indicate that a cell is "on" and 0 to indicate that it is "off". In this portion of the lab, we will experiment with several strategies for evolving a list into a same-length list of all 1s. From now on, our initial lists will consist only of 0s and 1s.

Detecting when we've reached our goal

In your hw3pr1.py file write a function named allOnes(L) that takes as input a list of numbers L and returns True if all of L's elements are 1 and returns False otherwise. Raw recursion is one good way to do this, though not the only one. Notice that the empty list vacuously satisfies the all-ones criterion, because it has no elements at all! Here are some examples to check:

>>> allOnes( [1,1,1] )

True

>>> allOnes( [] )

True

>>> allOnes( [ 0, 0, 2, 2 ] ) # this should be False!

False # but be careful... if you use sum(L) == len(L), this will be True

>>> allOnes( [ 1, 1, 0 ] )

False

Caution about True/False!

You will want to use the line

return True

somewhere in your code, as well as the line

return False

Be sure to return (and not print) these values! Also, watch out that you're returning the values True and False. You DON'T want to return the strings "True" and "False".

Improving the function runGenerations

Now that you have a function for testing if a list is all ones, improve your runGenerations function in two ways:

• First, add a base case to the recursion, so that runGenerations stops when the input list is all 1s.

• Second, change runGenerations so that it returns the number of generations needed to evolve the input into all 1s.

Suggestions

• Leave the print and pause lines before the check to see if the all-ones base case has been reached. That way they will run whether it's the base case or the recursive case that runs afterward.

• In order to return the number of generations required to evolve the list into all ones, consider the rwSteps problem from the last homework, or the mylen recursive example written in class. The idea is to add 1 for each evolve step. That 1 needs to be added to the number of steps needed to evolve the new list into all-ones.

Trying it out

First, you might want to reduce or remove the half-second pause produced by the line time.sleep(0.5). A value of a twentieth of a second (or zero) might be better for these trials.

Then, try your new runGenerations function on input lists with varying numbers of 0s. You should use the random element chooser that you wrote at the end of the previous part of the lab as your setNewElement function. Here are two examples:

>>> runGenerations([0,0,0,0,1])

[0, 0, 0, 0, 1]

[1, 0, 1, 1, 1]

[1, 1, 0, 0, 0]

[1, 0, 1, 0, 1]

[1, 0, 0, 0, 1]

[1, 1, 1, 1, 0]

[0, 1, 1, 0, 0]

[1, 1, 0, 1, 0]

[0, 0, 1, 1, 0]

[0, 1, 1, 1, 1]

[1, 1, 1, 0, 0]

[1, 1, 0, 1, 0]

[1, 1, 1, 1, 1]

12

>>> runGenerations([0,1,0,1,1])

[0, 1, 0, 1, 1]

[0, 0, 0, 1, 0]

[0, 1, 0, 1, 1]

[1, 1, 0, 1, 1]

[1, 1, 1, 1, 1]

4

This link continues the lab with the same hw3pr1.py file.

Lab 3, Part 2: Graphics and user input

Lab 3 Part 2: Graphics and user input

At the moment, your random-evolver for lists displays its interim generations using text only. This part will uses Python's graphics to display those lists. In addition, we will use graphics-based input in order to interact with the functions.

Displaying the lists graphically

The csplot.py module contains a function named show that will display lists as patches of color in a window. To use csplot, follow these steps:

1. Be sure that you download csplot.py to the same directory that your hw3pr1.py file is located.

This is the link to csplot.py. Use right-click on a PC or control-click on a Mac

You should re-download the file from the link above - it has changed since the last HW.

2. Include the line from csplot import * at the top of your hw3pr1.py file near the other import lines - this will provide access to the graphics functions in csplot.

3. Include the line show(L) right above the print L line that is already in your runGenerations function. This is the command to display your list graphically.

How does it display lists?

Try the function call

show( [1,0,1,1,0] )

and you should see a window that looks like the following:

[pic]

NOTE: csplot has the same "frozen window" problem as turtle graphics had. After csplot finishes each command its window will become unresponsive. This is OK; as soon as you give it another command it will update to show this command. However, if you want to see the result of your previous command (and end your interaction with the csplot window) you can type done() at the python prompt and the csplot window will respond again. However, after typing done(), you will have to close the csplot window before you can interact with the python shell again. For most of the assignment, you will not need to use the done() command. When we add mouse input, the window will respond just fine.

Try it out

Alter your runGenerations code by adding the line show(L) above the line print L that is already there. Try it out with runGenerations( [0,0,0,0,0] ) or variants... .

Want different colors?

You can set each value's color at the Python prompt, as follows:

>>> setColor( 0, "purple" )

>>> setColor( 1, "blue" )

>>> setColor( 2, "green" )

>>> show( [0,1,2,0,1] )

resulting in the image

[pic]

We will be using only 0s and 1s, but this example shows that other values are also possible.

Accepting user input

The approach to evolving lists thus far is, well, a bit too random. This section will enable the user to guide the process by clicking on the graphical representation of the list.

Getting mouse input

Replace your evolve and setNewElement functions by copying these at the bottom of your file:

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

x = sqinput() # Get mouse input from the user

return [ setNewElement( L, i, x ) 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

"""

if i == x: # if it's the user's chosen column,

return choice( [0,1] ) # return a random 0 or 1

else: # otherwise

return L[i] # return the original

Note that sqinput() is a function from the csplot module which takes mouse input from the user. It returns the index of the square closest to the mouse click.

Try running runGenerations( [0,0,0,0,0,0] ). Now, the execution should pause and wait for you to click on one of the squares in the window. Note that the square does not simply change from 0 to 1 and 1 to 0 - the call to choice randomizes the result.

Toggling the lights

Change the setNewElement function so that the light the user clicks on toggles from 0 to 1 or from 1 to 0, as appropriate. Hint: if the old value of the light is L[i], what will you get if you subtract that value from 1?

Be sure to test your code by running

runGenerations( [0,0,0,0,0,0] )

Admittedly, the "game" is not difficult to win in this case, but the next part of the lab adds the wrinkle that makes it much more challenging.

This link continues the lab with the same hw3pr1.py file.

Lab 3, Part 3: The game of "Lights On"

Lab 3 Part 3: Putting it all together

Question 1

Now, you are finally ready to implement the full 1D version of "Lights On". Modify your code so that the game play is as it should be (i.e., when you toggle one light, the lights next to it also toggle). Remember, lights do not "wrap around". That is, the lights at the edge of the board have only one neighbor. The function runGenerations( L ) should then play the game from the initial starting list L.

Suggestions: Only setNewElement needs to change in order to implement this game. You will need to compare the value of i, which is checked for each light in the row, and x, which is the user's choice.

Starting from a random binary list

Question 2

Create a function named

randBL( N )

that takes in a nonnegative integer, N, and returns a list of length N in which each element is equally likely to be a 0 or a 1. Raw recursion is one way to handle this; list comprehensions are another.

This randBL function makes it easy to start a new, random game. Try running

runGenerations( randBL(9) )

to be sure it works.

Question 3: The final 2D version

The show command will display 2d grids of lights as well as the 1d rows that this lab has used thus far. For example, in your Python shell try

>>> show( [ [0,1,0], [1,1,0], [0,0,1] ] )

You will see a three-by-three grid of lights appear. Each element of the input list to show is, itself, a row of the resulting grid of squares. The rows are plotted from-low-to-high in the window.

For this question, implement the 2d game of lights out by writing a new function named runGenerations2d( L ). Clicking on a square should change its neighbors (if any) to the north, east, west, and south. You will need to rework some of the helper functions in order to implement run2dGenerations -- rather than write over or redefine your existing functions, create new names for them, For example, you may need

1. evolve2d

2. setNewElement2d

3. allOnes2d

4. randBL2d

You will also need the function sqinput2() which returns 2d data, as follows:

x, y = sqinput2()

Warnings:

Make sure you understand exactly how the displayed squares and their coordinates correspond to the positions in the list

If you copy and paste your code (recommended) be sure to change all the function calls within each function to their 2d counterpart.

Letting the computer play...

Question 4 (Optional for up to 5 extra credit)

Don't be selfish -- Write new versions of evolve and evolve2d so that the computer gets to play! That is, have computer choose (randomly) one of the possible indices and the game continues until it's solved. Warning: one-sixth of all binary lists are dead ends! That is, there is no combination of toggled lights that will end up at the all-ones list. So, letting the computer play for a long time on one of those dead-ends will result in Python running out of memory.

Submission of hw3pr1.py

That's it!

Before you do leave, be sure to submit your hw3pr1.py file under homework 3, problem #1 at the Submission Site.

Good luck with the other problems on this week's HW!

This is the end of Lab3.

Below is the rest of Homework 3, also available at



Problem 2: Caesar Cipher (hw3pr2.py) [35 points; individual or pair]

Week 3, Problem 2: Caesar (De)Cipher

[35 points; individual or pair]: hw3pr2.py

This problem asks you to write and test two functions (perhaps with helper functions, as well):

encipher( S, n )

and

decipher( S )

[pic]

encipher

encipher( S , n ) takes as input a string S and a non-negative integer n between 0 and 25. This function returns a new string in which the letters in S have been rotated by n characters. For this problem, you should assume that upper-case letters are "rotated" to upper-case letters, lower-case letters are "rotated" to lower-case letters, and all non-alphabetic characters are left unchanged. For example, if we were to shift the letter 'y' by 3, we would get 'b' and if we were to shift the letter 'Y' by 3 we would get 'B'. (In python, you can use the test if 'a' > encipher('xyza', 1)

'yzab'

>>> encipher('Z A', 1)

'A B'

>>> encipher('*ab?', 1)

'*bc?'

>>> encipher('This is a string!', 1)

'Uijt jt b tusjoh!'

>>> encipher('Caesar cipher? I prefer Caesar salad.', 25)

'Bzdrzq bhogdq? H oqdedq Bzdrzq rzkzc.'

>>> decipher('Bzdrzq bhogdq? H oqdedq Bzdrzq rzkzc.')

'Caesar cipher? I prefer Caesar salad.'

>>> decipher('Hu lkbjhapvu pz doha ylthpuz hmaly dl mvynla lclyfaopun dl ohcl slhyulk.')

'An education is what remains after we forget everything we have learned.'

>>> decipher('Onyx balks')

'Edon rqbai' # wrong! it was 'Onyx balks' but there might be another rule I could add...

Here is the letter-probability function and its source:

# table of probabilities for each letter...

def letProb( c ):

""" if c is the space character or an alphabetic character,

we return its monogram probability (for english),

otherwise we return 1.0 We ignore capitalization.

Adapted from



"""

if c == ' ': return 0.1904

if c == 'e' or c == 'E': return 0.1017

if c == 't' or c == 'T': return 0.0737

if c == 'a' or c == 'A': return 0.0661

if c == 'o' or c == 'O': return 0.0610

if c == 'i' or c == 'I': return 0.0562

if c == 'n' or c == 'N': return 0.0557

if c == 'h' or c == 'H': return 0.0542

if c == 's' or c == 'S': return 0.0508

if c == 'r' or c == 'R': return 0.0458

if c == 'd' or c == 'D': return 0.0369

if c == 'l' or c == 'L': return 0.0325

if c == 'u' or c == 'U': return 0.0228

if c == 'm' or c == 'M': return 0.0205

if c == 'c' or c == 'C': return 0.0192

if c == 'w' or c == 'W': return 0.0190

if c == 'f' or c == 'F': return 0.0175

if c == 'y' or c == 'Y': return 0.0165

if c == 'g' or c == 'G': return 0.0161

if c == 'p' or c == 'P': return 0.0131

if c == 'b' or c == 'B': return 0.0115

if c == 'v' or c == 'V': return 0.0088

if c == 'k' or c == 'K': return 0.0066

if c == 'x' or c == 'X': return 0.0014

if c == 'j' or c == 'J': return 0.0008

if c == 'q' or c == 'Q': return 0.0008

if c == 'z' or c == 'Z': return 0.0005

return 1.

Hint: For decipher you might have your program "look at" all 26 possible rotations of the input string and then decide on which is "best"... .

Submission

You should submit your hw3pr2.py file at the Submission Site.

Problem 3: Looks Good! (hw3pr3.py) [30 points; individual or pair]

Week 3, Problem 3: Looks Good!

[30 points; individual or pair]: hw3pr3.py

See special submission instructions at the bottom of this page

In this problem you will get more practice working with 2D lists, this time to manipulate images.

Set up

Download the file mimp.pyw from this link and save it wherever is convenient for you. This file is based on the file linked from and provides basic image manipulation capabilities (plus the ability to add much more).

Next create a new folder on your desktop called "modifiers" (without the quotes). Into that directory, download the file modifyBase.py from this link.

NOTE FOR MAC/LINUX USERS: The program previously was not finding the modifiers directory on the desktop on Macs of Linux machines. This should be fixed now for Macs (but you have to re-download the mimp.py file). In Linux it will look in your home directory. However you can always set the location of the modifiers directory manually in the application by going to the Modifiers menu and choosing "Location...".

For the rest of this problem, you will run your code only by running the mimp.py file. You can run this file in two ways. First, you should be able to double-click on it and it should open a window that allows you to open up images. Alternatively, you can open the file in IDLE and then press F5. Try this now.

You'll also need some image files to work with. There are several that you can grab here: , but feel free to use whatever images you like (but you'll want to keep them small, and as they get bigger you'll need to increase your recursion depth as you've done in previous homeworks).

Run the mimp.py file and try opening some image files now.

Modifying the image

Once you have things set up, you're ready to start writing code that modifies images. We'll step through an example together so you get the hang of the general process and then you'll write several more image manipulation functions of your own.

1. Create a new python file called brighten.py and save it in the modifiers directory you created above

2. Copy and paste the following code into brighten.py

from modifyBase import *

label = "Brighten"

ordinal = 1

def modify(pic):

""" modify modifies an image to make it brighter """

pixels = getPixels(pic)

if len(pixels) == 0:

return

newPixels = [ [setNewPixel( pixels, row, col ) for col in range(len(pixels[0]))] for row in range(len(pixels))]

setPixels(pic, newPixels)

def setNewPixel( pixels, row, col ):

""" setNewPixel returns the NEW imanges (row, col) (r,g,b) value

input pixels: a 2D list containing RGB information in the pixels in a picture

input row: the row of the pixel in question

input col: the column of the pixel in question

"""

rval= min(pixels[row][col][0]+30, 255)

gval = min(pixels[row][col][1]+30, 255)

bval = min(pixels[row][col][2]+30, 255)

return (rval, gval, bval)

3. Now run the mimp.py file again. You should see a button at the bottom of the window named "brighten". Load an image and click on this button. You should see the image brighten each time you click on the button.

Looking at the above code, we see that it functions in a similar way to the Lights On code from lab. modify gets the pixels out of an image, creates a new 2D list containing the new color values for the pixels, and then sets the image to have these new color values. setNewPixel does the work of determining a new color for each pixel.

Representing Color

As we mentioned in class, images on the computer are represented as a grid of pixels, where each pixel has a red value, a green value and a blue value, which together determine the color of that pixel (i.e., its RGB value). Each pixel gets one byte for each color channel, so each color value can range from 0 to 255 (2^8-1).

The function getPixels above returns a 2D list of tuples containing RGB values. E.g., after the following code is executed

pixles = getPixels(pic)

(r,g,b) = pixels[row][col]

(r,g,b) will hold the red, green and blue values for the pixel at row row, column col in the image.

Remember that tuples are essentially the same as lists, with some subtle differences that we'll address later in the semester. You can still index into them and slice them, and append them, just like you did with lists. E.g.,

>>> t = (1, 2, 3)

>>> t[0:1]

(1,)

>>> t[1]

2

>>> t[0:2]

(1, 2)

>>>

For now the only difference is that tuples are created (and displayed) with parentheses. Notice that a tuple with only one element is displayed with a comma after that element.

Functions for you to write

Your task is to implement (at least) 3 of the following functions, one from each group. For up to +15 points of extra credit (depending on the scope of your additions) you can implement more of them or make up your own creative image manipulation function.

For each function you write, create a new .py file in your modifiers directory. You'll paste them all together when you submit. I recommend always starting with the brighten.py code by choosing the "Save As..." option in the File menu and then modifying the brighten code to suit your needs. The function modify should remain unchanged. You will change the setNewPixel function.

Group 1:

• negative.py: Modifies an image to create its negative. That is, all color values should be 255 minus their original value

• grayscale.py: Modifies an image to make it grayscale (i.e. black and white).

Group 2:

• flipVert.py: Flip the image on its horizontal axis

• flipHoriz.py: Flip the image on its vertical axis

• mirrorVert.py: Mirror the photo across its horizontal axis (i.e., so that the top part is mirrored upside down on the bottom of the image

• mirrorHoriz.py: Same as above, but across the vertical axis

Group3:

• scale.py: Scale the image to half its original size (either horizontally, vertically, or both)

• blur.py: Blur the image by combining neighboring pixels in some way (up to you)

• randomGrid.py: Divide the image into an NxN grid (where the N is up to you) and randomly sort the pieces of the grid across the image.

Feel free to add any more functions you can think of. Be creative! I'll show off the more interesting images in class.

Submitting your files

You have created several files for this problem, but you'll need to combine them into one file for submission. Create a new file named hw3pr3.py. Into this file copy and paste all of your image manipulation files. Be sure to include a comment between each, like this:

######## Code for grayscale.py starts here ##########

And at the top of your file you should include a comment listing the functions you implemented.

Submission

You should submit your hw3pr3.py file at the Submission Site.

Overall Instructions

Each of these questions asks you to write several short Python functions and/or an English response. Please place all of your answers for problems 1, 2 and 3 into a Python plain-text file named hw3pr1.py, hw3pr2.py, or hw3pr3.py (changing the problem number as appropriate). Please use the function names suggested by the problems - this will help us grade things!

Docstrings and Comments

Every function that you write must have a docstring. The docstring should explain how many inputs the function takes, what these inputs are supposed to be, and what the function returns. The doctring is intended for the user of your function. In contrast, comments in your code are used to explain details that are important to a programmer who might be reading your code (that "programmer" could be you - it's easy to forget what you had in mind when you wrote your code!). Any function that is doing anything even modestly complex or non-obvious deserves some explanatory comments. We'll look for your docstrings and comments, so be sure to include them.

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download