Homework 6

Sixth Homework due Friday 13 December (by 11:59pm)

Part 1

This homework uses the Echo Nest API. The main part of the homework is to write an interactive query that outputs (prints) the result of a number of queries to Echo Nest, using the Pyen module (please study the Echo Nest page for details). The goal is to write a script that asks the user for the name of a song, and then outputs up to 120 lines, each line listing the name of an artist and that artist's familiarity score. Here is an example of using such a script and its output:

Please enter a song name: Blue
0.12 Bodhi and the Kung Fu Buddhists
0.25 Nancy Apple
0.38 cholo
0.03 Reese Simmons

(Only a few lines are shown; there were 120 lines, each with a different artist).

Notes on Part 1

Part 2

Part 2 is the "extra credit" effort of the homework, giving students a chance to work with a graphical interface. Part 2 of the homework is to embed some of the Echo Nest work from Part 1 into a Tk GUI program. To do this, please first study the Tk GUI page, download examples and experiment with them first.

An example (but by no means the only one) is shown in this screenshot.

guidemo.png

This window has a place to enter a song, and then a Listbox (see listbox widget for explanation) showing familiarity and artists for the song. The window even has fancy features like the Quit and +/- buttons for scrolling.

Notes on Part 2

Notes on Submissions

After reviewing the Part 2 submissions, here are some general observations:

Though 100 points could have been theoretically awarded for part 2 of the homework, no student got to this level. Perhaps there was too little time to devote to the GUI, since it was the only homework that emphasized class/object design.

Homework 5

Fifth Homework due Tuesday 10 December (by 11:59pm)

Homework 5 asks you to write programs that make performance graphs. Each graph should be produced by matplotlib, using the line plot technique (the first one with an example in the Plots page). The performance graphs are all based on looking at different ways of computing the median of a list of numbers. Measuring performance consists of two parts.

Part 1
Show the comparison of computing time for two methods of getting the median. The first way is based on using Python's sort() method. The second way uses Python's heapq module. For each of these two ways, there should be many measurements of computing time.
  • The length of the list M for which median(M) is calculated, should be all the values in range(2**10,2**19,2**15) --- that means measuring median(M) where len(M) is 1024, 33792, ..., up to 492544.
  • For each length in range(2**10,2**19,2**15), the measurement should be the average of 5 experiments, using 5 different randomly chosen lists M. That means there will be 5 different calculations of median(M) for a list M, where each experiment randomly generates the list M. Each of the 5 experiments for a particular length might have a different computing time, but only the average computing time for the 5 is represented the plot. Of course, this happens for each length; overall there will be 5*len(range(2**10,2**19,2**15))=5*16=80 experiments for each way of calculating the median. Since there are two ways to calculate the median being compared, the total number of experiments to get all the data is 160 (80 experiments for each median type). On a typical computer, once you have a working program, it will take a few minutes for Python to run all the experiments.
  • The line plot will show how the computing time tends to grow, for either way to getting the median, as the length of M increases. So, the line plot will show two curves, one for each kind of median calculation, and both will start get larger on the y-axis (computing time) as x (length of M) gets larger. Here is a typical graph that might be produced for this part of the homework. part1.png

Part 2

Show the comparison of estimating the median for different kinds of lists. Below, there is a "quality score" to see how good an estimate is to the median --- it is this score which is y-axis for the plots. A perfect score is 0.0, and higher scores indicate lower quality estimates. There will be three lines all in the same plot, one for each way of generating a random list (they could be red, blue, and green curves). Instead of having different list lengths, all experiments have the same list length: 16384. However, different sets of experiments vary the way that the median is estimated. Each median estimate uses x randomly selected values from a list, where x is a number in range(4,128,4). Thus, the x-axis of the plot is the number of values used to estimate the median. The experimental plots should show that when more values are used to make an estimate (more to the right on the x-axis), then the score of the estimate gets better (lower on the y-axis). Each (x,y) point in the data for the curves represents 20 experiments, where each experiment uses a particular way of getting a random list of 16384 values and estimates the median using x randomly chosen values from the list. Here is a plot typical for this part of the homework. part2.png

Code Snippets

A number of questions arise from the description above. How is the median calculated? How is computing time measured? How are lists randomly generated? How is a median estimated? How is the quality of an estimate scored? To answer these questions, some fragments of Python are shown here. These fragments could be parts of functions, lines of a script, or even lines of a method within a class.

Median

Here are two ways to calculate the median of a randomly generated list M. The first is what's usually done.

   1 median = sorted(M)[ len(M)//2 ]

The idea is simple: for a sorted list, half of the elements are smaller than the middle and half are larger, roughly speaking. (Technically, for valid statistics, we might need to do bit more if the length of M is even, but that's not the issue in this homework.)

The second way is more cumbersome, but it is needed for the first part of the homework.

   1 import heapq 
   2 heapq.heapify(M)  # rearrange M into heap form
   3 for n in range(len(M)//2):
   4   heapq.heappop(M)
   5 median = heapq.heappop(M)

Again, for valid statistics a bit more work needs to done, but this code is good enough for experiments.

(By the way, both ways of getting median shown above will fail for a tiny list, say M with length 2 or less.)

Generating Random Lists

Three possible ways of generating a random list of length K are shown here, called uniform, normal, and exponential. Each of these uses built-in methods of Python's random module.

Uniform Random List Generation This code is quite simple:

   1 M = [ random.random() for i in range(K) ]  # list of K random numbers

For the first part of the homework, just use the uniform method of randomly making a list.

Normal Random List Generation This one uses the gauss() method in the random module, but we have an extra step to force all numbers to be just two significant digits, because this is like reality where the chance of having multiple random numbers being the same is higher. (Technically, this is called data binning.)

   1 M = [ random.gauss(mu=10.0,sigma=3.0) for i in range(K) ]
   2 M = [ round(val*10.0)/10.0 for val in M ]

Exponential Random List Generation This uses a method for exponentially distributed random numbers, derived for instance from how radioactive decay of elements works. Again, data binning is used.

   1 M = [ random.expovariate(1/10.0) for i in range(K) ]
   2 M = [ round(val*10.0)/10.0 for val in M ]

To see the code for normal and exponential in action, the attached program distributions.py plots these two ways of making a randomly generated list.

Computing Time Measurements

See the examples in the Timing page to learn how computing time is measured in Python. One thing to be careful about is to measure only the median calculation. Do not measure the random generation of a list or other things. Aim to have your measurements be purely the time taken to compute the median.

You should arrange measurements by iteration and accumulation: for 20 times, randomly generate a list and get the computing time for median on that list; sum all the times measured and divide by 20.0 to get the average time.

Estimating Median

Here's a snippet of code to estimate the median of list M using just k randomly chosen values from M:

   1 estimate = median( random.sample(M,k) )

It's just the regular median, but using a random sample of k items from M. (The median() here refers to the sort-and-take-middle idea shown earlier.)

Scoring an Estimate

Suppose M is the list and estimate is the value to be scored. Here's the calculation of the score:

   1 score = abs(estimate - median(M))/float(median(M))

Notice that if the estimate is equal to the actual median, the numerator will be zero, so the score will be zero. The float() function was used only to be sure (in case of Python2) that the score is a float as well. With Python3 the float() would not be needed, since division using the / operator gives us a float.

Note: it can be argued that this way of calculating a score isn't fair because not all the list generation methods shown above have the same range of values. That's OK, we hope still to see some interesting differences in the results.

Notes and Rubric

Homework 4

Fourth Homework Sample Solution

There could be many ways to answer this homework. Here is one, which shows comments and program structuring. The last two lines in the program use the style of Testor in previous homeworks, only running the script if it is directly run (but not running the script if it is imported). Students weren't expected to do this.

   1 '''
   2 This is an elementary program to produce a pie chart
   3 comparing the average salaries of Major League Baseball
   4 teams, restricted to a specified year and league within
   5 Lahman's 2012 CSV file of salaries.  
   6 
   7 ( See http://www.seanlahman.com/baseball-archive/statistics/ )
   8 
   9 The following modules are used:
  10   
  11   csv -- to parse the CSV file (currently hard-coded
  12          as Salaries.csv)
  13   matplotlib.pyplot -- to produce a pie chart
  14 
  15 Various functions deal with prompted user input, 
  16 extracting years from Salaries.csv, computing average
  17 salaries using the accumulation pattern, and invoking
  18 the plotting.
  19 
  20 Author:  Ted Herman
  21 Date:    November 2013
  22 '''
  23 import matplotlib.pyplot as plt
  24 import csv
  25 
  26 def solicit(prompt,checker):
  27   '''
  28   This is a general purpose function to ask the user for
  29   data, check what user entered, and repeat until the 
  30   user input looks good.
  31 
  32   parameters:
  33    
  34     prompt -- this is the string to ask the user for input
  35     checker -- a boolean function that tells whether the 
  36               user input was satisfactory.
  37 
  38   returns:
  39 
  40     string (for which checker(string) is True
  41   '''
  42   while True:  # repeat until input(prompt) is OK
  43     data = input(prompt)  # would be raw_input(prompt) in Py2
  44     if checker(data):
  45        return data
  46     print("Input was not an allowable string, please retry")
  47 
  48 def validyears(csvfilename):
  49   '''
  50   Read the CSV file, gathering all year fields as indicated
  51   in the 'yearID' column of the CSV file.  Then, make a 
  52   dictionary of all the years found, and return that.
  53 
  54   parameter:
  55 
  56     csvfilename -- the name of the CSV file to open, assumed 
  57                    to be in the current path
  58   '''
  59   F = open(csvfilename,'r')
  60   rowsupply = csv.DictReader(F)
  61   yeardict = { }
  62   for row in rowsupply:
  63     yeardict[ row['yearID'] ] = True
  64   F.close() # be nice to Python and system
  65   return yeardict
  66 
  67 def getleague():
  68   '''
  69   Ask the user for a league (AL or NL), returning
  70   either 'AL' or 'NL'
  71   '''
  72   def leaguechecker(value):
  73      return value in ('AL','NL')
  74   prompt = "Enter league (AL or NL): "
  75   return solicit(prompt,leaguechecker)
  76 
  77 def getyear(csvfilename):
  78   '''
  79   Ask the user for a year in the CSV file, returning
  80   a four-character year string.
  81 
  82   parameter:
  83 
  84     csvfilename -- the name of the CSV file to open, assumed 
  85                    to be in the current path. The file is needed
  86                    to extract what years are present.
  87   '''
  88   availables = validyears(csvfilename)
  89   yearlist = ', '.join(sorted(list(availables.keys())))
  90   def yearchecker(value):
  91      return value in availables
  92   print("Years found in database: {}".format(yearlist))
  93   prompt = "Choose a year in the database: "
  94   return solicit(prompt,yearchecker)
  95 
  96 def avesalaries(csvfilename,year,league):
  97   '''
  98   Compute the average salary for each team within
  99   the CSV file for a given league and year.
 100 
 101   parameters:
 102    
 103      csvfilename --- the name of the salaries CSV file
 104      year        --- the year to select
 105      league      --- which league to select
 106 
 107   returns:
 108 
 109      a dictionary with teams as keys and average
 110      salaries as values
 111   '''
 112   F = open(csvfilename,'r')
 113   rowsupply = csv.DictReader(F)
 114   sumdict = { }    # for sums of all salaries
 115   countdict = { }  # for counting rows per team 
 116   for row in rowsupply:
 117      if row['yearID'] != year or row['lgID'] != league: 
 118         continue  
 119      # this row has the right year and league
 120      team = row['teamID']
 121      if team not in sumdict: 
 122         sumdict[team] = countdict[team] = 0
 123      sumdict[team] += int(row['salary']) # I hope they are whole numbers!
 124      countdict[team] += 1
 125   F.close()
 126   # at end of loop we have sums and counts to make a new
 127   # dictionary with averages for each team
 128   avedict = { }
 129   for team in sumdict: # maybe a comprehension would be nicer?
 130     avedict[team] = sumdict[team] / float(countdict[team])
 131   return avedict
 132 
 133 def teamshare(averages):
 134   '''
 135   Calculate the share of each team with respect to 
 136   all the average salaries.
 137 
 138   parameter:
 139 
 140      averages -- dictionary of teams, with average salary
 141                  as the value
 142 
 143   returns:
 144 
 145      shares   -- dictionary of teams, with percent share
 146                  (with respect to all teams) as value.
 147 
 148                  Note: percent should be an integer X to
 149                  satisfy  0 <= X <= 100 (like a percent)
 150   ''' 
 151   shares = { }
 152   total = sum( x for x in averages.values() )
 153   for team in averages:
 154     shares[team] = round( 100 * averages[team] / float(total) )
 155     # note that int() instead of round() would be OK for this homework
 156   return shares
 157 
 158 def plot(teamshares,year,league):
 159   '''
 160   Make a pie chart of the team shares using 
 161   matplotlib, following the style in many matplotlib tutorials.
 162 
 163   parameter:
 164 
 165      teamshares --- a dictionary of teams (character string keys),
 166                     and the relative share (percent) as the value
 167                     for a team.
 168 
 169      league --- what league was used to calculate teamshares
 170      year   --- the year for teamshares
 171 
 172   returns:
 173 
 174      None.  It just plots, it doesn't calculate something to return.
 175   '''
 176   fig = plt.figure(figsize=(8,8))
 177   ax1 = fig.add_subplot(111)
 178   ax1.set_title("salary average pie chart for {} {}".format(league,year))
 179   labels = list(teamshares.keys()) 
 180   percents = list(teamshares.values()) 
 181   p = plt.pie(percents,labels=labels)
 182   plt.show()
 183 
 184 def main():
 185   '''
 186   The main logic for the program: 
 187 
 188   1. Call getleague() and getyear(), saving the values.
 189   2. Call avesalaries(), saving the dictionary it computes. 
 190   3. Call teamshare() to convert avesalaries() result into percentages.
 191   4. Call plot() to make a pie chart.
 192 
 193   Note:  the CSV file name is defined here, so change that as
 194   needed to get the program's input file.
 195   '''
 196   FileName = "Salaries.csv"  # CHANGE THIS AS NEEDED
 197   league = getleague()
 198   year = getyear(FileName)
 199   aves = avesalaries(FileName,year,league)
 200   shares = teamshare(aves)
 201   plot(shares,year,league)
 202 
 203 # main program actually starts here
 204 
 205 if __name__ == "__main__":  # allow program to be imported without running
 206   main()  # good luck! 


Fourth Homework due Tuesday 19 November (by 11:59pm)

This homework asks you to write a program that reads a CSV file (download Salaries.csv ) and uses matplotlib to produce a pie chart. There are two sources of input for your program, the keyboard and the Salaries.csv file. Here is how your program should work:

  1. When it starts, your program should ask the user for a league (which can either be AL or NL --- those are the only two options). If the user makes a mistake, the program should ask again.
  2. Then your program should ask the user for a year. If the year is not in Salaries.csv, the user should be told that is an error and asked to try again (without quitting the program).
  3. After this, the program should calculate the average salary for all teams in the chosen league (AL or NL) for the specified year only, ignoring the rows that have a different year.
  4. Once all the average salaries are calculated, the program should figure out the relative share of each team's average salary with respect to all others (this can be rounded to an integer percent, a value from 0 to 100).
  5. Finally, plot all the team average salary shares as a pie chart. An example for NL in 1985 is shown here:

salary.png

Notes:

Rubric


Homework 3

Third Homework Sample Solutions

These are some solutions to the problems.

   1 def Vecombine(A,B,C):
   2   '''
   3   Three lists, A, B, and C, each have the same number
   4   of items -- all items are numbers.  As a result of
   5   calling Vecombine, we want A[i] = A[i]*B[i] + C[i] 
   6   at each index i.
   7 
   8   Also, if the result has A[i]<0 at any index i, then
   9   Vecombine should return -1.0;  otherwise, Vecombine
  10   should return 1.0
  11   '''
  12   for i in range(len(A)):
  13     A[i] *= B[i]
  14     A[i] += C[i]
  15   for i in range(len(A)):
  16     if A[i]<0:
  17       return -1.0
  18   return 1.0
  19 
  20 def Smooth(ValueList,Threshold):
  21   '''
  22   ValueList is a list of float numbers, and Threshold
  23   is a number.  The function Smooth goes through 
  24   ValueList sequentially, and if it finds 
  25 
  26         abs(ValueList[i]-ValueList[i+1]) > Threshold
  27 
  28   then a new item is inserted between indexes i and i+1
  29   equal to the average of ValueList[i] and ValueList[i+1],
  30   and then exits.  It is important that Smooth inserts 
  31   at most one new item.  
  32 
  33   Example:  
  34 
  35       Z = [1.0, 1.5, 2.0, 4.0, 4.5]
  36       Smooth(Z,1.5)
  37 
  38       Now, Z is [1.0, 1.5, 2.0, 3.0, 4.0, 4.5]
  39   '''
  40   for i in range(len(ValueList)-1):
  41     if abs(ValueList[i]-ValueList[i+1]) > Threshold:
  42        ValueList[i+1:i+1] = [ (ValueList[i]+ValueList[i+1]) / 2.0 ]
  43        return
  44 
  45 def RemoveAll(D,limit):
  46   '''
  47   D is a dictionary and limit is some value (maybe number or string).
  48 
  49   RemoveAll(D,limit) removes from D any item with a value larger
  50   than limit.
  51   '''
  52   P = list(D.keys())
  53   for key in P:
  54     if D[key] > limit:
  55       del D[key]
  56 
  57 def Enclosure(Q):
  58   '''
  59   Q is a list of rectangles and the function
  60   Enclosure(Q) returns the smallest (in area) rectangle
  61   that contains all rectangles in Q.
  62 
  63   Each rectangle is a tuple (x,y,width,height) where
  64   x and y specify the lower left corner of the rectangle.
  65   '''
  66   if len(Q) < 1:
  67      return (0.0,0.0,0.0,0.0)
  68   Minx,Miny,width,height = Q[0]  # take 1st rectangle as guess
  69   Maxx, Maxy =  Minx + width, Miny + height
  70   for x,y,width,height in Q: 
  71      right, top = x + width, y + height
  72      Minx, Miny = min(Minx,x), min(Miny,y)
  73      Maxx, Maxy = max(Maxx,right), max(Maxy,top)
  74   # now convert Minx, Miny, Maxx, Maxy into rectangle
  75   x,y,width,height = Minx, Miny, Maxx-Minx, Maxy-Miny
  76   return (x,y,width,height)
  77 
  78 def Findex(G):
  79   '''
  80   G is an iterator returning pairs (v,text) where v is 
  81   a line number and text is a string (so, "for v,text in G: ..."
  82   can be used in a loop).  
  83 
  84   The goal is to return dictionary where the keys are words
  85   from text, and the values are lists of which which line contains
  86   a particular word.  For instance, maybe the word "fame" is 
  87   found in one or more lines provided via G.  Then, maybe the
  88   dictionary entry for "fame" could have [4,8,13,29], which says
  89   that "fame" is found on lines 4, 8, 13, and 29.  
  90   '''
  91   D = dict()
  92   for v,text in G:
  93     words = text.split()
  94     for item in words:
  95       if item not in D:
  96         D[item] = list() 
  97       if v not in D[item]:
  98         D[item].append(v)
  99   return D     
 100 
 101 def Allbinary(N):
 102    '''
 103    This is just enumeration of all the binary numbers
 104    with N digits.
 105 
 106    The result is a tuple containing a representation 
 107    of each binary number, where each binary number 
 108    itself is a tuple.  The order of the tuples in
 109    the result should be sorted from least to greatest.
 110    '''
 111    if N<2:
 112       return ((0,),(1,))
 113    M,New = Allbinary(N-1),list()
 114    for vertex in M:
 115       New.append(vertex+(0,))
 116       New.append(vertex+(1,))
 117    return tuple(New)
 118 
 119 def NextGray(T):
 120   '''
 121   After study of the pattern, we see
 122   that NextGray(T) with T having even 
 123   parity is just flipping the last bit;
 124   but for odd parity, flip the bit that
 125   comes before the rightmost 1 bit.
 126   '''
 127   if sum(T)%2 == 0:  # even parity?
 128      return T[:-1] + (1-T[-1],) # flip last bit
 129   else:
 130      for i in reversed(range(len(T))): 
 131        if T[i] == 1:  # finds rightmost 1 bit in T
 132           break
 133      if i == 0:  # special case is 1 followed by zeroes
 134         return len(T)*(0,)  # the "rollover" case
 135      j = i - 1   # index just before rightmost bit
 136      return T[:j] + (1-T[j],) + T[i:]

Third Homework due Friday 1 November (by 11:59 pm)

The document Homework3.pdf describes the seven programs for the second homework. This homework also serves as preparation for the second midterm exam. To do this homework, you need to download and run Testor.py as well as write functions in files. Each file is submitted separately to the dropbox.

Testing your solutions uses the same general idea as in the second homework, it uses Testor which has unit tests for each of the seven functions. As you did for the second homework, you might find it helpful to write some "helping" functions and put those definitions in your file, though Testor doesn't see the helping functions if there are extra blank lines (it's a bug in Testor).

The Findex function is tested by a large file, sherlock.txt, which you should download also when you are working on Findex. It might be useful to temporarily use a smaller file (named sherlock.txt) until you are confident that Findex is working. Make sure that sherlock.txt is in the same folder/directory as Testor.py.

IMPORTANT NOTES

  1. Some discussion, questions and answers on the homework is on the Piazza site.
  2. Only the techniques covered in class and in the readings up through November 1 are allowed in the solutions to the problems.
    • Rationale: especially for NextGray, there are solutions (even in Python!) found on the internet. Therefore, some bit operations are not allowed (they are not discussed in class or in the readings)

    • Import statements are not allowed, even though this topic has been presented in the course; the emphasis for this assignment is on loops and the assignment statement. A few other methods and functions which cause problems for Testor (like the input() and eval() functions) are also disallowed.
  3. Bug in Testor.py (for Findex, test needed to accommodate differing dictionary orderings; fixed 10/23/2013, h/t Julio). Please download new copy of Testor.py

  4. Python3 change to Testor.py fixed 10/25/2013. For RemoveAll, a change to Testor.py because in Python3, the dictionary methods keys(), values(), and items() no longer return lists, they return "objects" (the way that range() does). The fix is just to use list(D.values()) instead of D.values(), and the same idea is needed for keys() and items() if you use those methods in your code. Again, Please download new copy of Testor.py


Homework 2

Second Homework Sample Solutions

Many correct solutions are possible for these problems. Here are just a few examples:

   1 # common
   2 def common(A,B):
   3   intersect = [ t for t in A if t in B ]
   4   return intersect
   5 
   6 # convert
   7 def fc(x):
   8   if x[0] in "0123456789":
   9      return float(x)
  10   else:
  11      return x
  12 def convert(record):
  13   T = record.split(",")
  14   return tuple(map(fc,T))
  15 
  16 # determinant
  17 def determinant(A):
  18   return A[0][0]*A[1][1] - A[1][0]*A[0][1]
  19 
  20 # middle
  21 def midword(W):
  22   if len(W) < 3:
  23      return ''
  24   else:
  25      return W[1:-1]
  26 def middle(phrase):
  27   words = phrase.split()
  28   newwords = map(midword,words)
  29   safewords = [ term for term in newwords if term != '' ]
  30   return ' '.join(safewords)
  31 
  32 # overflow
  33 def overflow(L,threshold):
  34   def invert(x):
  35     return 1.0/x
  36   inverted = list(map(invert,L))
  37   places = [ k for k in range(len(L)) 
  38              if sum(inverted[:k]) > threshold ] 
  39   if len(places) < 1:
  40      return -1
  41   else:
  42      return places[0]
  43 
  44 # subzero
  45 def valorzero(x,minvalue):
  46   if x > minvalue:
  47      return x
  48   else:
  49      return 0
  50 def subzero(M):
  51   R = [ valorzero(e,min(M)) for e in M ]
  52   return R
  53 
  54 # sucontain
  55 def sucontain(phrase):
  56   words = phrase.split()
  57   contained = [ words[i] for i in range(len(words)-1) if words[i] in words[i+1] ]
  58   return contained
  59 
  60 # title
  61 def capword(S):
  62   return S[0].upper() + S[1:]
  63 def title(phrase):
  64   words = phrase.split()
  65   newphrase = map(capword,words)
  66   return ' '.join(newphrase)
  67 
  68 # vowelcount
  69 def vnum(word):
  70   return [ c in "aeiou" for c in word ].count(True) 
  71 def vowelcount(wordlist):
  72   return { w:vnum(w) for w in wordlist }


Second Homework due Friday 4 October (by 11:59 pm)

The document Homework2.pdf describes the nine programs for the second homework. This is meant to be a challenging homework that also serves as preparation for the first midterm exam. To do this homework, you need to download and run Testor.py as well as write functions in files. Each file is submitted separately to the dropbox.

Bug in Homework2.pdf description of the "common" problem -- fixed on 9/24 at 5:00pm (please reload Homework2.pdf to refresh your copy)

IMPORTANT NOTES

  1. The discussion, questions and answers on the homework is on the Piazza site.
  2. Only the techniques covered in class and in the readings up through Chapter 14 are allowed in the solutions to the problems.
    1. Rationale: we want everyone to be on the same level, with less advantage given to students who already know how to program (typically in Java, C#, Javascript, Visual Basic, etc). The techniques up through Chapter 14 are functional style programming, which every computer science student should see and try.

    2. The use for for-loops (statements that begin with the "for" keyword) and while-loops is not allowed in a solution, even if the solution works. However, the "for" keyword can be used inside of a comprehension expression, as covered in Chapter 13.

    3. The use of the assignment statement is not allowed. Yes, solutions can define names in the functions, but they cannot define the same name multiple times -- that would be an assignment statement. Compare these two:
      •    1      def foo(L):
           2        r = L[0]
           3        r = r + 1
           4        return r
        
        this uses an assignment to variable r. But this next one is allowable:
           1      def foo(L):
           2        r = L[0]
           3        s = r + 1
           4        return s
        

        The second version only defines names. It has no "variables", because no name varies when the function is evaluated: once a name is defined, it stays with that definition as long as the function is being evaluated.

    4. The use of such advanced techniques as using "with", "import", "from", and "try"-- these are also not allowed.
    5. All mutating methods (append(), push(), pop(), remove(), etc) -- count as assignments to variables. Therefore, they are disallowed on this assignment.
    6. "Python magic" assignments, such as locals()['x'] = True, are also disallowed: this is just another way to do an assignment, as is the dictionary update() method used on locals() or globals().


Homework 1

First Homework due Friday 6 September (by 11:59 pm)

The first homework is by electronic submission, using the ICON dropbox for this course. Please submit a file before Saturday 7 September. There are two purposes to this homework:

  1. Demonstrate that you can use the dropbox system and edit a text file.
  2. Help us comply with a US Government regulation:

    Because of changes in federal financial aid regulations, The University of Iowa requires that every instructor verifies the occurrence of students’ academic activity through the 10th day of the semester. The University of Iowa and students could lose federal Title IV financial aid if we fail to comply with these regulations. The University requires 100% completion of the tenth-day academic activity report by instructors for every student in each class.

What do I submit?

You should put a text file into the dropbox that has one line of text, consisting of your name (no student number, just your name).

Isn't this very easy?

Whether this is extremely easy depends on your experience. There are pitfalls (ways to do it incorrectly):

  1. The dropbox system has a poor interface. You can think that you have submitted the homework, but it was not actually submitted. You need to be somewhat careful about this.

  2. What is meant by a text file? Some students might think this can be a Word document, or an RTF document (often prepared by Apple apps). These are not text files. By text file, we mean a file that contains a string containing only alphabetic characters, spaces, punctuation, and newline or return characters (denoted '\n' and '\r' in Python). To be sure about this, prepare your homework using a simple text file editor, not a fancy word processing editor. For Windows, this might be notepad or similar. Ask your TA if you are uncertain.

Why can't I submit it now?

The dropbox for this homework has been set up to accept submissions between 7am on Tuesday 3 September and midnight Friday 6 September.

If I cannot understand what "dropbox" is, can I just email?

Emailing would miss one of the crucial points of the homework. It is important to use the dropbox. Why not learn how to do this? It is not so hard to do.

Tutorials

  1. Demo using Laptop Windows

  2. Demo using CSG Linux

Other possibilities, like CSG Windows machine, or a Mac, will be similar; on a Mac there is an accessory called Textedit (or something like that).

Homeworks (last edited 2014-05-25 17:58:24 by localhost)