 %\documentclass{article}
\documentclass[twocolumn]{article}

\setlength{\oddsidemargin}{-0.5in}
\setlength{\evensidemargin}{-0.5in}
\setlength{\topmargin}{0.0in}
\setlength{\headheight}{0in}
\setlength{\headsep}{0in}
\setlength{\textwidth}{7.0in}
\setlength{\textheight}{9.5in}
\setlength{\parindent}{0in}
\setlength{\parskip}{0.05in}
\setlength{\columnseprule}{0.3pt}
\usepackage{fancyvrb}
\usepackage{relsize}
\usepackage{hyperref}
\usepackage{amsmath}

\begin{document}

Name: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_

Directions: {\bf Work only on this sheet} (on both sides, if needed).  DO NOT
turn in any supplementary sheets of paper. There is actually plenty of room
for your answers, as long as you organize yourself BEFORE starting writing.
When appropriate, SHOW YOUR WORK. 

{\bf 1.} (15) Fill in the blanks in the following version of our prime number
finding program:

\begin{Verbatim}[fontsize=\relsize{-2}]
import sys,math,threading,Queue

class primefind(threading.Thread):
   n = int(sys.argv[1])
   prime = (n+1) * [1]
   lim = int(math.sqrt(n)) + 1
   _______________________________________
   for i in range(2,lim+1):
      _________________________________________
   def __init__(self):
      _________________________________________
   def run(self):
      nk = 0
      while True:
         try:
            k = primefind.nexti.get(block=False)
         except:
            break
         nk += 1
         if primefind.prime[k]:
            r = primefind.n / k
            for i in range(2,r+1): primefind.prime[i*k] = 0
      print 'this thread handled',nk,'values of k'

def main():
   mythreads = []
   for i in range(int(sys.argv[2])):
      pf = primefind()
      mythreads.append(pf)
      pf.start()
   for pf in mythreads: pf.join()
   print reduce(lambda x,y: x+y, primefind.prime)-2,'primes'

if __name__ == '__main__': main()
\end{Verbatim}

{\bf 2.} (10) Sec. 2.4 of our PLN on iterators and generators is titled,
``Multiple Iterators from the Same Generator.''  Give an example in
which we actually had such a situation, i.e. we had code in which
several iterators from the same generator function would be in existence
at the same time.

{\bf 3.} This question involves our {\bf thrd} class for nonpreemptive
threads.

\begin{itemize}

\item  [(a)] (15) We could add an analog of the Queue class but there would
not be much point to it.  Why not?

\item [(b)] (15) Give the line number in pp.17-19 that will be executed
immediately after line 33 on p.14.

\item [(c)] (15) Suppose we are debugging the code on pp.14-15 of our
iterators/generators PLN (the one that illustrates the capabilities of
{\bf thrd}).  Give the PDB command to set a conditional breakpoint at
line 70, p.17 (beginning of {\bf thrd.do\_pause()}), breaking only if
the function is triggered by {\bf a()} in pp.14-15.  (The command set
listed in our intro PLN if you need it.)  

\end{itemize}

{\bf 4.} (15) In this problem, you will write a \underline{generator}
function {\bf il()} that interleaves two iterators of the same length.
For example:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> a = range(3)
>>> b = [-2,6,8]
>>> d = il(a,b)
>>> d.next()
0
>>> d.next()
-2
>>> d.next()
1
>>> d.next()
6
\end{Verbatim}

We'll use the function {\bf itertools.izip()}, which works like {\bf
zip()}, but inputs two iterators and outputs a third one.  Fill in the
blanks:

\begin{Verbatim}[fontsize=\relsize{-2}]
from itertools import *

def il(i,j):
   k = izip(i,j)  
   for __________________________________________:
      _______________________________________________
      _______________________________________________
\end{Verbatim}

{\bf 5.} (15) Solve the mystery!  We ran the Fibonacci number iterator from
our PLN on iterators and generators, and though it ran correctly for a
while, it got stuck on the number 8!

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> from fib import *
>>> f = fibnum()
>>> f.next()
1
>>> f.next()
1
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
>>> f.next()
8
>>> # here we executed a one-line Python statement (not shown)
>>> f.next()
8
>>> f.next()
8
\end{Verbatim}

What was that one-line Python mystery statement?

{\bf Solutions:}

{\bf 1.}

\begin{Verbatim}[fontsize=\relsize{-2}]
nexti = Queue.Queue()
nexti.put(i)
threading.Thread.__init__(self)
\end{Verbatim}

{\bf 2.}  Two examples were from discussions section, concerning tree
traversal and partitions of n.

{\bf 3.a}  The main utility of Queue is that it automatically handles
locks for us.  But we don't need locks in the case of {\bf thrd}.

{\bf 3.b}  157

{\bf 3.c}

\begin{Verbatim}[fontsize=\relsize{-2}]
b 70, yv[0] == '1'
\end{Verbatim}

{\bf 4.}

\begin{Verbatim}[fontsize=\relsize{-2}]
(u,v) in k
yield u
yield v
\end{Verbatim}


{\bf 5.}

\begin{Verbatim}[fontsize=\relsize{-2}]
f.next = lambda : 8
\end{Verbatim}
\end{document}

