How to Think Like a Computer Scientist: Learning with Python 2nd Edition/Solutions

      The following section contains answers to the exercises in the Book.

      Chapter 1

      Exercise 1:

      print("5 ** 5 is", 5**2)
      print("9 * 5 is", 9 * 5)
      print("15 / 12 is", 15 / 12)
      print("12 / 15 is", 12 / 15)
      print("15 // 12 is", 15 // 12)
      print("12 // 15 is", 12 // 15)
      print("5 % 2 is", 5 % 2)
      print("9 % 5 is", 9 % 5)
      print("15 % 12 is", 15 % 12)
      print("12 % 15 is", 12 % 15)
      print("6 % 6 is", 6 % 6)
      print("0 % 7 is", 0 % 7)
      

      Exercise 2:

      time_start=14  #  Use 24 hour clock.  Makes life a lot easier.
      wait=51
      time_hours= time_start + wait
      days=time_hours//24
      clock=time_hours-(days*24) 
      print("The alarm goes of at", str(clock)+":00")
      

      Exercise 3:

      #  24 hour clock
      t1=input("Enter the current time's hour using 24 hour clock: ")
      t1=int(t1)
      wait=input("Enter wait in hours for next alarm: ")
      wait=int(wait)
      t2_hrs=wait+t1
      days=t2_hrs//24
      t2_time=t2_hrs-(days*24) 
      print("The alarm goes of at", str(t2_time)+":00")
      
      ↑Jump back a section

      Chapter 3

      Solution 4


      def cat_n_times(s, n):

         string=s
         print string*n
      

      Chapter 4 Excercise 5

      def dispatch(choice):
              if choice == 'a':
                      function_a()
              elif choice == 'b':
                      function_b()
              elif choice == 'c':
                      function_c()
              else:
                      print "Invalid choice."
      def function_a():
              print "function_a was called ..."
      def function_b():
              print "function_b was called ..."
      def function_c():
              print "function_c was called ..."
       
      choice = raw_input ("Please Enter a Function.")  #had to ask about this,  choice is raw input.  
      print dispatch(choice)
      

      Chapter 4 Excercise 7

      def is_divisible_by_3(x):
              if x % 3 == 0:
                      print x, "This number is divisible by three."
              else:
                      print x, "This number is not divisible by three."
      x = input ("Enter a number")
      print is_divisible_by_3(x)
       
       
       
       
      def is_divisible_by_5(y):
              if y % 5 == 0:
                      print y, "This number is divisible by five."
              else:
                      print y, "This number is not divisible by five."
      y = input ("Enter a number")
      print is_divisible_by_5(y)
       
      def is_divisible_by_n(c,z):
              if c % z == 0:
                      print "Yes", c, "divisible by", z
              else:
                      print "No", c, "is not divisible by", z
      c = input ("Enter number")
      z = input ("Enter another number")
      print is_divisible_by_n(c,z)
      
      ↑Jump back a section

      Chapter 5

      CH 5 - Solution 1

      def compare(a, b):
          """
              >>> compare(5, 4)
              1
              >>> compare(7, 7)
              0
              >>> compare(2, 3)
              -1
              >>> compare(42, 1)
              1
          """
          if a > b:
              return 1
          elif a == b:
              return 0
          elif a < b:
              return -1
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 2

      def hypotenuse(a, b):
          """
              >>> hypotenuse(3, 4)
              5.0
              >>> hypotenuse(12, 5)
              13.0
              >>> hypotenuse(7, 24)
              25.0
              >>> hypotenuse(9, 12)
              15.0
          """
          import math
          return math.sqrt(a**2 + b**2)
          # You could also use    
          # return (a**2 + b**2)**0,5
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 3 Part 1

      def slope(x1, y1, x2, y2):
          """
              >>> slope(5, 3, 4, 2)
              1.0
              >>> slope(1, 2, 3, 2)
              0.0
              >>> slope(1, 2, 3, 3)
              0.5
              >>> slope(2, 4, 1, 2)
              2.0
          """
          return float(y2 - y1)/(x2 - x1)
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 3 Part 2

      def slope(x1, y1, x2, y2):
          return float(y2 - y1)/(x2 - x1)
       
      def intercept(x1, y1, x2, y2):
          """
              >>> intercept(1, 6, 3, 12)
              3.0
              >>> intercept(6, 1, 1, 6)
              7.0
              >>> intercept(4, 6, 12, 8)
              5.0
          """
          m = slope(x1, y1, x2, y2)
          return float(y1 - m*x1)
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 4

      def is_even(n):
          """
              >>> is_even(2)
              True
              >>> is_even(3)
              False
              >>> is_even(7)
              False
              >>> is_even(10)
              True
          """
          # You could also type just
          # return n % 2 == 0
          if n % 2 == 0:
              return True
          else:
              return False
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 5 Part 1

      def is_odd(n):
          """
              >>> is_odd(2)
              False
              >>> is_odd(3)
              True
              >>> is_odd(7)
              True
              >>> is_odd(10)
              False
          """
          if n % 2 != 0:
              return True
          else:
              return False
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 5 Part 2

      def is_even(n):
          if n % 2 == 0:
              return True
          else:
              return False
       
      def is_odd(n):
          """
              >>> is_odd(2)
              False
              >>> is_odd(3)
              True
              >>> is_odd(7)
              True
              >>> is_odd(10)
              False
          """
          if is_even(n) is True:
              return False
          else:
              return True
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 6

      def is_factor(f, n):
          """
              >>> is_factor(3, 12)
              True
              >>> is_factor(5, 12)
              False
              >>> is_factor(7, 14)
              True
              >>> is_factor(2, 14)
              True
              >>> is_factor(7, 15)
              False
          """
          if n % f == 0:
              return True
          else:
              return False
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 7

      def is_multiple(m, n):
          """
              >>> is_multiple(12, 3)
              True
              >>> is_multiple(12, 4)
              True
              >>> is_multiple(12, 5)
              False
              >>> is_multiple(12, 6)
              True
              >>> is_multiple(12, 7)
              False
          """
          if m % n == 0:
              return True
          else:
              return False
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 8

      def f2c(t):
          """
            >>> f2c(212)
            100
            >>> f2c(32)
            0
            >>> f2c(-40)
            -40
            >>> f2c(36)
            2
            >>> f2c(37)
            3
            >>> f2c(38)
            3
            >>> f2c(39)
            4
          """
          return int(round((t - 32.0) * 5.0/9))
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 5 - Solution 9

      def c2f(t):
          """
            >>> c2f(0)
            32
            >>> c2f(100)
            212
            >>> c2f(-40)
            -40
            >>> c2f(12)
            54
            >>> c2f(18)
            64
            >>> c2f(-48)
            -54
          """
          return int(round((t * 9.0/5) + 32.0))
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      
      ↑Jump back a section

      Chapter 6

      CH 6 - Solution 1

      $ cat ch0601.py

      print 'produces', '\n', 'this', '\n', 'output'


      $ python ch0601.py

      produces

      this

      output

      CH 6 - Solution 2

      $ cat ch0602.py

      def sqrt(n):

         approx = n/2.0
         better = (approx + n/approx)/2.0
         print better
         while better != approx:
             approx = better
             better = (approx + n/approx)/2.0
         return approx
      

      print sqrt(25)


      $ python ch0602.py

      7.25

      5.0

      CH 6 - Solution 3

      CH 6 - Solution 4

      def print_triangular_numbers(x):
         i = 1
         while i <= x:
             print i, '\t', i*(i+1)/2
             i += 1
      

      CH 6 - Solution 5 v1

      def is_prime(n):
          """
              >>> is_prime(2)
              True
              >>> is_prime(3)
              True
              >>> is_prime(4)
              False
              >>> is_prime(41)
              True
              >>> is_prime(42)
              False
          """
          count = 2
          #so counting starts at 2
          #as all numbers can be divided by 1 and remainder = 0; and because nothing can be divided by 0
          while count <= n:
              if n % count == 0 and count != n:
                  #if when n divided by count remainder is 0
                  #for example when 4 is divided by 2
                  #and to make sure count != n because any number divided by itself then remainder = 0;
                  #then return False
                  return False
              #if above is not applicable then return true for doctest to pass
              elif count == n:
                  return True
              #to make sure it doesnt exit after one try, and it counts
              elif n % count != 0:
                  count = count + 1
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 6 - Solution 5 v2

      def is_prime(n):
          """
              >>> is_prime(2)
              True
              >>> is_prime(3)
              True
              >>> is_prime(4)
              False
              >>> is_prime(41)
              True
              >>> is_prime(42)
              False
          """
          count = 2
          while count <= n:
              if n % count == 0 and count != n:
                  return False
              else:
                  count = count + 1
          return True
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 6 - Solution 6 Part 1

      What will num_digits(0) return?

      def num_digits(n):
          """
              >>> num_digits(12345)
              5
              >>> num_digits(0)
              1
              >>> num_digits(-12345)
              5
          """
          count = 0
          while n != 0:
              count = count + 1
              n = n / 10
          return count
       
      #num_digits(0) returns 0 because the while statement is not run,
      #and therefore it returns count.
      

      CH 6 - Solution 6 Part 2

      Modify it to return 1 for this case.

      def num_digits(n):
          """
              >>> num_digits(12345)
              5
              >>> num_digits(0)
              1
              >>> num_digits(-12345)
              5
          """
          if n == 0:
              return 1
       
      #the program checks if n == 0. if it's 0, it simply returns 1.
      #if not, count below is initialized, then, after the calculation, 
      #count is returned with the final result
       
          count = 0
          while n != 0:
              count = count + 1
              n = n / 10
          return count
      

      CH 6 - Solution 6 Part 3

      Why does a call to num_digits(-24) result in an infinite loop (hint: -1/10 evaluates to -1)?

      >>> -24/10
      -3
      >>> -3/10
      -1
      >>> -1/10
      -1
      >>>
      

      The loop will end when n = 0, and per above -1/10 == -1, causing an infinite loop.

      CH 6 - Solution 6 Part 4

      def num_digits(n):
          """
              >>> num_digits(12345)
              5
              >>> num_digits(0)
              1
              >>> num_digits(-12345)
              5
          """
      #        >>> num_digits(-100)    #The code must be checked with this value for assurance
      #        3
      #        >>> num_digits(-9999)    #The code must be checked with this value for assurance
      #        4
       
          count = 0
          if n == 0:
              return 1
       
          elif n < 0:
              n = -n
              while n:
                  count = count + 1
                  n = n/10
              return count
       
          else:
              while n:
                  count = count + 1
                  n = n/10
              return count
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 6 - Solution 7

      def num_even_digits(n):
          """
              >>> num_even_digits(123456)
              3
              >>> num_even_digits(2468)
              4
              >>> num_even_digits(1357)
              0
              >>> num_even_digits(2)
              1
              >>> num_even_digits(20)
              2
          """
          count = 0
          while n != 0:
              digit = n % 2
              if digit == 0:
                  count = count + 1
              n = n / 10
          return count
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 6 - Solution 8

      def print_digits(n):
          """
            >>> print_digits(13789)
            9 8 7 3 1
            >>> print_digits(39874613)
            3 1 6 4 7 8 9 3
            >>> print_digits(213141)
            1 4 1 3 1 2
          """
          while n != 0:
              print n % 10,
              n = n/10
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 6 - Solution 9

      def sum_of_squares_of_digits(n):
          """
            >>> sum_of_squares_of_digits(1)
            1
            >>> sum_of_squares_of_digits(9)
            81
            >>> sum_of_squares_of_digits(11)
            2
            >>> sum_of_squares_of_digits(121)
            6
            >>> sum_of_squares_of_digits(987)
            194
          """
          sumof = 0
          while n != 0:
              sumof += (n % 10)**2
              n = n/10
          return sumof
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      
      ↑Jump back a section

      Chapter 7

      CH 7 - Question 1

      Modify:

      prefixes = "JKLMNOPQ"
      suffix = "ack"
       
      for letter in prefixes:
          print letter + suffix
      

      so that Ouack and Quack are spelled correctly.

      CH 7 - Notes regarding Question 1

      Note that for letter in prefixes: is a substitution of traversal, for example:

      index = 0
      while index < len(fruit):
          letter = fruit[index]
          print letter
          index += 1
      #fruit = "banana"
      #while index is less than 6.
      #6 is the lenght of fruit
      #letter = fruit[index]
      #Since index = 0, "b" is equal to letter in loop 1
      #letter is printed
      #1 is added to whatever the value of index is
      #the loop continues until index < 6
      

      is substituted by:

      for char in fruit:
          print char
      

      CH 7 - Solution 1 v1

      prefixes = "JKLMNOPQ"
      suffix = "ack"
       
      for letter in prefixes:
          if letter == "O" or letter == "Q":
              print letter + "u" + suffix
          else:
              print letter + suffix
      

      CH 7 - Solution 1 v2

      prefixes = "JKLMNOPQ"
      suffix = "ack"
       
      for letter in prefixes:
          if letter in "OQ":
              print letter + "u" + suffix
          else:
              print letter + suffix
      


      CH 7 - Question 2

      Encapsulate:

      fruit = "banana"
      count = 0
      for char in fruit:
          if char == 'a':
              count += 1
      print count
      

      in a function named count_letters, and generalize it so that it accepts the string and the letter as arguments.

      CH 7 - Solution 2

      def count_letters(strng, letter):
          count = 0
          for char in strng:
              if char == letter:
                  count += 1
          return count
      

      CH 7 - Question 3

      Now rewrite the count_letters function so that instead of traversing the string, it repeatedly calls find (the version from Optional parameters), with the optional third parameter to locate new occurences of the letter being counted.

      CH 7 - Solution 3

      def find(strng, ch, start=0):
          index = start
          while index < len(strng):
              if strng[index] == ch:
                  return index
              index += 1
          return -1
       
      #for example strng = "banana"
      #letter = "a"
      #x = find(strng, letter, start) will return 1
      #we need to modify count_letters so it returns 3
      #the start variable can thus be used to our advantage
      #the loop will end at the last letter of the string by returning -1
       
      def count_letters(strng, letter, start=0):
          count = 0
          x = find(strng, letter, start)
          while x != -1:
              count += 1
              x = find(strng, letter, x + 1)
          return count
      

      Tracing the program:

      #in our traceback, x = 1
      #x = find(strng, letter, 2)
      #x above will be assigned new value find(strng, letter, 2) 
       
      >>> find("banana", "a", 1)
      1
      >>> find("banana", "a", 2)
      3
      >>> find("banana", "a", 4)
      5
      >>> find("banana", "a", 6)
      -1
      >>>
      

      CH 7 - Solution 4

      Re: the versions of is_lower:

      def is_lower(ch):
          return string.find(string.lowercase, ch) != -1
      


      def is_lower(ch):
          return ch in string.lowercase
      


      def is_lower(ch):
          return 'a' <= ch <= 'z'
      

      CH 7 - Question 5

      Create a file named stringtools.py and put the following in it:

      def reverse(s):
          """
            >>> reverse('happy')
            'yppah'
            >>> reverse('Python')
            'nohtyP'
            >>> reverse("")
            ''
            >>> reverse("P")
            'P'
          """
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      Add a function body to reverse to make the doctests pass.

      CH 7 - Solution 5

      def reverse(s):
          """
            >>> reverse('happy')
            'yppah'
            >>> reverse('Python')
            'nohtyP'
            >>> reverse("")
            ''
            >>> reverse("P")
            'P'
          """
       
      #we need to use len(s) to make it output letters
      #length = len(happy) = 6
      #print last = happy[length - 1] will return y
      #we need to make it such that [length - 2] and so on
      #we need the while loop to stop when length - x = 0
      #if len(s) is 6
       
          x = 1
          while x <= len(s):
              length = len(s)
              lastoutput = s[length - x]
              print lastoutput,
              x += 1
      


      #Why is x <= len(s)?
      #because if x < len(s):
      >>> reverse("happy")
      y p p a
      >>>
      #with x<= len(s)
      >>> reverse("happy")
      y p p a h
      >>>
      

      Now inorder to make the doctest pass we need to enclose our ouput in a string. Here we use a placeholder string: lastoutput = "".

      Second, we remove redundant code:

          x = 1
          while x <= len(s):
              length = len(s)
              lastoutput = s[length - x]
      

      per:

      length = len(fruit)
      last = fruit[length-1]
      

      by using negative indices, such as:

      fruit[-1]
       
      and
       
      fruit[-2]
      

      to:

          x = 1
          while x <= len(s):
              lastoutput = s[-x]
      


      def reverse(s):
          """
            >>> reverse('happy')
            'yppah'
            >>> reverse('Python')
            'nohtyP'
            >>> reverse("")
            ''
            >>> reverse("P")
            'P'
          """
          last = ""
          x = 1
          while x <= len(s):
              lastoutput = s[-x]
              last += lastoutput
              x += 1
          return last
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 7 - Solution 6

      def reverse(s):
          last = ""
          x = 1
          while x <= len(s):
              lastoutput = s[-x]
              last += lastoutput
              x += 1
          return last
       
      def mirror(s):
          """
            >>> mirror("good")
            'gooddoog'
            >>> mirror("yes")
            'yessey'
            >>> mirror('Python')
            'PythonnohtyP'
            >>> mirror("")
            ''
            >>> mirror("a")
            'aa'
          """
      #we will be calling function reverse
      #first we need it to ouput everything
          s_back = reverse(s)
          return s + s_back
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 7 - Solution 7

      def reverse(s):
          last = ""
          x = 1
          while x <= len(s):
              lastoutput = s[-x]
              last += lastoutput
              x += 1
          return last
       
      def mirror(s):
          out = reverse(s)
          out2 = reverse(out)
          return out2 + out
       
      def remove_letter(letter, strng):
          """
            >>> remove_letter('a', 'apple')
            'pple'
            >>> remove_letter('a', 'banana')
            'bnn'
            >>> remove_letter('z', 'banana')
            'banana'
            >>> remove_letter('i', 'Mississippi')
            'Msssspp'
          """
          without_letter = ""
          for c in strng:
              if c not in letter:
                  without_letter += c
          return without_letter
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 7 - Solution 8

      def reverse(s):
          """
            >>> reverse('happy')
            'yppah'
            >>> reverse('Python')
            'nohtyP'
            >>> reverse("")
            ''
            >>> reverse("P")
            'P'
          """
          last = ""
          x = 1
          while x <= len(s):
              lastoutput = s[-x]
              last += lastoutput
              x += 1
          return last
       
      def mirror(s):
          """
            >>> mirror("good")
            'gooddoog'
            >>> mirror("yes")
            'yessey'
            >>> mirror('Python')
            'PythonnohtyP'
            >>> mirror("")
            ''
            >>> mirror("a")
            'aa'
          """
          out = reverse(s)
          out2 = reverse(out)
          return out2 + out
       
      def remove_letter(letter, strng):
          """
            >>> remove_letter('a', 'apple')
            'pple'
            >>> remove_letter('a', 'banana')
            'bnn'
            >>> remove_letter('z', 'banana')
            'banana'
            >>> remove_letter('i', 'Mississippi')
            'Msssspp'
          """
          without_letter = ""
          for c in strng:
              if c not in letter:
                  without_letter += c
          return without_letter
       
       
      def is_palindrome(s):
          """
            >>> is_palindrome('abba')
            True
            >>> is_palindrome('abab')
            False
            >>> is_palindrome('tenet')
            True
            >>> is_palindrome('banana')
            False
            >>> is_palindrome('straw warts')
            True
          """
          half = len(s)/2
          fronthalf = s[:half]
          backhalf = s[-half:] #N.B no need to compare middle letter
          return fronthalf == reverse(backhalf)
       
          # We can make this even simpler by not bothering to split the word
          # into halves. Simplest solution is the single line:
          #     return s == reverse(s)
          # This will return True if word is the same forwards as backwards. 
          # Although might be slower for v. long words?
       
       
       
      def count(sub, s):
          """
            >>> count('is', 'Mississippi')
            2
            >>> count('an', 'banana')
            2
            >>> count('ana', 'banana')
            2
            >>> count('nana', 'banana')
            1
            >>> count('nanan', 'banana')
            0
          """
          count = 0
          x = s.find(sub)
          while x != -1:
              count += 1
              x = s.find(sub, x + 1)
          return count
       
      def remove(sub, s):
          """
            >>> remove('an', 'banana')
            'bana'
            >>> remove('cyc', 'bicycle')
            'bile'
            >>> remove('iss', 'Mississippi')
            'Missippi'
            >>> remove('egg', 'bicycle')
            'bicycle'
          """
          x = s.find(sub)
          if x != -1:
              out1 = s[:x]
              y = len(sub)
              out2 = s[x + y:]
              return out1 + out2
          else:
              return s
       
      def remove_all(sub, s):
          """
            >>> remove_all('an', 'banana')
            'ba'
            >>> remove_all('cyc', 'bicycle')
            'bile'
            >>> remove_all('iss', 'Mississippi')
            'Mippi'
            >>> remove_all('eggs', 'bicycle')
            'bicycle'
          """
          while s.find(sub) != -1:
              s = remove(sub, s)
          return s
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 7 - Solution 9

      >>> "%s %d %f" % (5, 5, 5)
      '5 5 5.000000'
      #note %f outputs 6 decimal places of 0s
      


      >>> "%-.2f" % 3
      '3.00'
      #note .2 before f causes decimal output at 2 places (.00)
      


      >>> "%-10.2f%-10.2f" % (7, 1.0/2)
      '7.00      0.50      '
      #note "The - after each % in the converstion specifications indicates left justification. 
      #The numerical values specify the minimum length, 
      #so %-13d is a left justified number at least 13 characters wide."
      #Here if we count from index 0 @ 7 we will reach to index 10, before 
      #the next string formatting operator
      


      >>> print " $%5.2fn $%5.2fn $%5.2f" % (3, 4.5, 11.2)
       $ 3.00n $ 4.50n $11.20
      

      CH 7 - Solution 10

      >>> "%s %s %s %s" % ('this', 'that', 'something')
      Traceback (most recent call last):
        File "<pyshell#24>", line 1, in <module>
          "%s %s %s %s" % ('this', 'that', 'something')
      TypeError: not enough arguments for format string
      


      >>> "%s %s %s" % ('this', 'that', 'something')
      'this that something'
      


      >>> "%s %s %s" % ('yes', 'no', 'up', 'down')
      Traceback (most recent call last):
        File "<pyshell#27>", line 1, in <module>
          "%s %s %s" % ('yes', 'no', 'up', 'down')
      TypeError: not all arguments converted during string formatting
      


      >>> "%s %s %s %s" % ('yes', 'no', 'up', 'down')
      'yes no up down'
      


      >>> "%d %f %f" % (3, 3, "three")
      Traceback (most recent call last):
        File "<pyshell#29>", line 1, in <module>
          "%d %f %f" % (3, 3, "three")
      TypeError: float argument required, not str
      


      >>> "%d %f %f" % (3, 3, 3)
      '3 3.000000 3.000000'
      
      ↑Jump back a section

      Chapter 8

      CH 8 - Solution 4

      Not fully complete but...

      <syntaxhighlight lang="python">
      fruit = "banana"
       
      def count_letters(array, n):
          count = 0
          for i in range(len(array)):
              m = array.find(n,i)
              if( i == m ):
                  count += 1
          print(count)
       
      count_letters(fruit,"a")
      
      ↑Jump back a section

      Chapter 9

      CH 9 - Solution 1

      x = ['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]
       
      for i in x:
          print len(i)
      


      >>> 
      5
      Traceback (most recent call last):
        File "C:\Python26\ch9.py", line 5, in <module>
          print len(i)
      TypeError: object of type 'int' has no len()
      >>>
      


      x = ['spam!', 'one', ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]
       
      for i in x:
          print len(i)
      


      >>> 
      5
      3
      3
      3
      >>>
      

      CH 9 - Solution 2

      CH 9 - Solution 2.1

      """
        >>> a_list[3]
        42
        >>> a_list[6]
        'Ni!'
        >>> len(a_list)
        8
      """
       
       
      a_list = [1, 2, 3, 42, 5, 6, 'Ni!', 8]
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 2.2

      """
        >>> b_list[1:]
        ['Stills', 'Nash']
        >>> group = b_list + c_list
        >>> group[-1]
        'Young'
      """
       
      b_list = ['Crosby', 'Stills', 'Nash'] 
      c_list = ['Young']
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 2.3

      """
        >>> 'war' in mystery_list
        False
        >>> 'peace' in mystery_list
        True
        >>> 'justice' in mystery_list
        True
        >>> 'oppression' in mystery_list
        False
        >>> 'equality' in mystery_list
        True
      """
       
      mystery_list = ['peace', 'justice', 'equality']
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 2.4

      """
        >>> range(a, b, c)
        [5, 9, 13, 17]
      """
       
      a = 5
      b = 18
      c = 4
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 3

      >>> range(10, 0, -2)
      [10, 8, 6, 4, 2]
      

      What happens if start is less than stop and step is less than 0?

      The result will be an empty list.

      Write a rule for the relationships among start, stop, and step.

      CH 9 - Solution 4

      >>> a = [1, 2, 3]
      >>> b = a[:]
      >>> id(a)
      18484400
      >>> id(b)
      18594872
      >>> b[0]
      1
      >>> b[0] = 5
      >>> id(a)
      18484400
      >>> id(b)
      18594872
      >>> b
      [5, 2, 3]
      >>> a
      [1, 2, 3]
      

      CH 9 - Solution 5

      >>> this = ['I', 'am', 'not', 'a', 'crook']
      >>> that = ['I', 'am', 'not', 'a', 'crook']
      >>> print "Test 1: %s" % (id(this) == id(that))
      Test 1: False
      >>> that = this
      >>> print "Test 2: %s" % (id(this) == id(that))
      Test 2: True
      >>>
      

      CH 9 - Solution 6

      CH 9 - Solution 6.1

      """
        >>> 13 in junk
        True
        >>> del junk[4]
        >>> junk
        [3, 7, 9, 10, 17, 21, 24, 27]
        >>> del junk[a:b]
        >>> junk
        [3, 7, 27]
      """
       
      junk = [3, 7, 9, 10, 13, 17, 21, 24, 27]
      a = 2
      b = (len(junk) - 2)
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 6.2

      """
        >>> nlist[2][1]
        0
        >>> nlist[0][2]
        17
        >>> nlist[1][1]
        5
      """
       
      nlist = [[1, 2, 17], [4, 5, 6], [7, 0, 9]]
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 6.3

      """
        >>> import string
        >>> string.split(message, '??')
        ['this', 'and', 'that']
      """
       
      message = "this??and??that"
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 7

      def add_lists(a, b):
          """
            >>> add_lists([1, 1], [1, 1])
            [2, 2]
            >>> add_lists([1, 2], [1, 4])
            [2, 6]
            >>> add_lists([1, 2, 1], [1, 4, 3])
            [2, 6, 4]
          """
       
          new_list = []
          for x, elmt1 in enumerate(a):
              for y, elmt2 in enumerate(b):
                  if x == y:
                      new_list += [elmt1 + elmt2]
          return new_list
          #there is a simpler solution:
          #new_list = []
          #for index, value in enumerate(a):
          #   new_list += [a[index], b[index]]
          #return new_list
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 8

      def mult_lists(a, b):
          """
            >>> mult_lists([1, 1], [1, 1])
            2
            >>> mult_lists([1, 2], [1, 4])
            9
            >>> mult_lists([1, 2, 1], [1, 4, 3])
            12
          """
          sm = 0
          new_list = []
          for x, elmt1 in enumerate(a):
              for y, elmt2 in enumerate(b):
                  if x == y:
                      new_list += [elmt1 * elmt2]
          q = len(new_list) - 1
          while q != -1:
              sm += new_list[q]
              q += -1
          return sm
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      #Simpler Code
      #new_list = []
      #for index, value in enumerate(b):
      #new_list += [a*value]
      #return new_list
      

      CH 9 - Solution 9

      CH 9 - Solution 9.1

      def add_row(matrix):
          """
            >>> m = [[0, 0], [0, 0]]
            >>> add_row(m)
            [[0, 0], [0, 0], [0, 0]]
            >>> n = [[3, 2, 5], [1, 4, 7]]
            >>> add_row(n)
            [[3, 2, 5], [1, 4, 7], [0, 0, 0]]
            >>> n
            [[3, 2, 5], [1, 4, 7]]
          """
          y = len(matrix[0])
       
          matrix2 = matrix[:]
          for z in range(1):
              matrix2 += [[0] * y]
          return matrix2
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 9.2

      def add_column(matrix):
          """
            >>> m = [[0, 0], [0, 0]]
            >>> add_column(m)
            [[0, 0, 0], [0, 0, 0]]
            >>> n = [[3, 2], [5, 1], [4, 7]]
            >>> add_column(n)
            [[3, 2, 0], [5, 1, 0], [4, 7, 0]]
            >>> n
            [[3, 2], [5, 1], [4, 7]]
          """
          x = len(matrix)
       
          matrix2 = [d[:] for d in matrix]
          for z in range(x):
              matrix2[z] += [0]
          return matrix2
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 10

      def add_matrices(m1, m2):
          """
            >>> a = [[1, 2], [3, 4]]
            >>> b = [[2, 2], [2, 2]]
            >>> add_matrices(a, b)
            [[3, 4], [5, 6]]
            >>> c = [[8, 2], [3, 4], [5, 7]]
            >>> d = [[3, 2], [9, 2], [10, 12]]
            >>> add_matrices(c, d)
            [[11, 4], [12, 6], [15, 19]]
            >>> c
            [[8, 2], [3, 4], [5, 7]]
            >>> d
            [[3, 2], [9, 2], [10, 12]]
         """
       
          new_matrix = []
          for i, row in enumerate(m1):
              new_row = []        
              for j, m1_value in enumerate(row):
                  m2_value = m2[i][j]
                  new_row += [m1_value + m2[i][j]]
              new_matrix += [new_row]
          return new_matrix
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 11

      def scalar_mult(n, m):
          """
            >>> a = [[1, 2], [3, 4]]
            >>> scalar_mult(3, a)
            [[3, 6], [9, 12]]
            >>> b = [[3, 5, 7], [1, 1, 1], [0, 2, 0], [2, 2, 3]]
            >>> scalar_mult(10, b)
            [[30, 50, 70], [10, 10, 10], [0, 20, 0], [20, 20, 30]]
            >>> b
            [[3, 5, 7], [1, 1, 1], [0, 2, 0], [2, 2, 3]]
          """
       
          new_matrix = []
          for row in m:
              new_row = []        
              for value in row:
                  new_row += [value*n]
              new_matrix += [new_row]
          return new_matrix    
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 12

      # Once we have obtained lists for the relevant rows and columns
      # in row_times_column function, we will re-use the mult_lists
      # function from question 8:
       
      def mult_lists(a, b):
          sum = 0
          for i, a_value in enumerate(a):
              sum += a_value * b[i]
          return sum
       
       
      def row_times_column(m1, row, m2, column):
          """
            >>> row_times_column([[1, 2], [3, 4]], 0, [[5, 6], [7, 8]], 0)
            19
            >>> row_times_column([[1, 2], [3, 4]], 0, [[5, 6], [7, 8]], 1)
            22
            >>> row_times_column([[1, 2], [3, 4]], 1, [[5, 6], [7, 8]], 0)
            43
            >>> row_times_column([[1, 2], [3, 4]], 1, [[5, 6], [7, 8]], 1)
            50
          """
          m1_row = m1[row]
          m2_col = []
          for m2_row in m2:
              m2_col += [m2_row[column]]
          return mult_lists(m1_row, m2_col)
       
      #This code may also be used to bypass the mult_lists code
       
      def row_times_column(m1, row, m2, column):
              x = 0
              y = 0
              for a in m1[row]:
                      t = a * m2[x][column]
                      y += t
                      x += 1
              return y
       
      def matrix_mult(m1, m2):
         """
            >>> matrix_mult([[1, 2], [3,  4]], [[5, 6], [7, 8]])
            [[19, 22], [43, 50]]
            >>> matrix_mult([[1, 2, 3], [4,  5, 6]], [[7, 8], [9, 1], [2, 3]])
            [[31, 19], [85, 55]]
            >>> matrix_mult([[7, 8], [9, 1], [2, 3]], [[1, 2, 3], [4, 5, 6]])
            [[39, 54, 69], [13, 23, 33], [14, 19, 24]]
          """
       
      #To pass these tests, the function needs to multiply each each m1 row
      #by each m2 column, to produce a new matrix with with the same number
      #of rows as m1, and the same number of columns as m2. (This is the way
      #matrices are commonly multiplied in mathematics). We can use
      #row_times_column for each row/column combination
       
         m1_num_rows = len(m1)
         m2_num_cols = len(m2[0])
         product_matrix = []
         for row in range(m1_num_rows): 
             new_row = []
             for column in range(m2_num_cols):
                 new_row += [row_times_column(m1, row, m2, column)]
             product_matrix += [new_row]
         return product_matrix
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 9 - Solution 13

      CH 9 - Solution 14

      import string
       
      def replace(s, old, new):
          """
            >>> replace('Mississippi', 'i', 'I')
            'MIssIssIppI'
            >>> s = 'I love spom!  Spom is my favorite food.  Spom, spom, spom, yum!'
            >>> replace(s, 'om', 'am')
            'I love spam!  Spam is my favorite food.  Spam, spam, spam, yum!'
            >>> replace(s, 'o', 'a')
            'I lave spam!  Spam is my favarite faad.  Spam, spam, spam, yum!'
          """
          s_without_old = string.split(s, old)
          s_with_new = string.join(s_without_old, new)
          return s_with_new
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      You can also do:

      def myreplace(s, old, new):
          """
            >>> myreplace('Mississippi', 'i', 'I')
            'MIssIssIppI'
            >>> s = 'I love spom!  Spom is my favorite food.  Spom, spom, spom, yum!'
            >>> myreplace(s, 'om', 'am')
            'I love spam!  Spam is my favorite food.  Spam, spam, spam, yum!'
            >>> myreplace(s, 'o', 'a')
            'I lave spam!  Spam is my favarite faad.  Spam, spam, spam, yum!'
          """
          new_string = ""
          counter = 0
          while counter<len(s): 
       
              # check if old equals a slice of len(old)
       
              if old == s[counter:counter+len(old)]:
                  new_string += new #s[counter+len(old):]
                  counter+=len(old)
              else:
                  new_string += s[counter]
                  counter += 1
          return new_string
       
       if __name__ == '__main__':
          import doctest
          doctest.testmod(verbose=True)
      
      ↑Jump back a section

      Chapter 10

      CH 10 - Solution 1

      CH 10 - Solution 1.1

      >>> import calendar
      >>> year = calendar.calendar(2008)
      >>> print year
                                        2008
       
            January                   February                   March
      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4  5  6                   1  2  3                      1  2
       7  8  9 10 11 12 13       4  5  6  7  8  9 10       3  4  5  6  7  8  9
      14 15 16 17 18 19 20      11 12 13 14 15 16 17      10 11 12 13 14 15 16
      21 22 23 24 25 26 27      18 19 20 21 22 23 24      17 18 19 20 21 22 23
      28 29 30 31               25 26 27 28 29            24 25 26 27 28 29 30
                                                          31
       
             April                      May                       June
      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4  5  6                1  2  3  4                         1
       7  8  9 10 11 12 13       5  6  7  8  9 10 11       2  3  4  5  6  7  8
      14 15 16 17 18 19 20      12 13 14 15 16 17 18       9 10 11 12 13 14 15
      21 22 23 24 25 26 27      19 20 21 22 23 24 25      16 17 18 19 20 21 22
      28 29 30                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                          30
       
              July                     August                  September
      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4  5  6                   1  2  3       1  2  3  4  5  6  7
       7  8  9 10 11 12 13       4  5  6  7  8  9 10       8  9 10 11 12 13 14
      14 15 16 17 18 19 20      11 12 13 14 15 16 17      15 16 17 18 19 20 21
      21 22 23 24 25 26 27      18 19 20 21 22 23 24      22 23 24 25 26 27 28
      28 29 30 31               25 26 27 28 29 30 31      29 30
       
            October                   November                  December
      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
             1  2  3  4  5                      1  2       1  2  3  4  5  6  7
       6  7  8  9 10 11 12       3  4  5  6  7  8  9       8  9 10 11 12 13 14
      13 14 15 16 17 18 19      10 11 12 13 14 15 16      15 16 17 18 19 20 21
      20 21 22 23 24 25 26      17 18 19 20 21 22 23      22 23 24 25 26 27 28
      27 28 29 30 31            24 25 26 27 28 29 30      29 30 31
       
      >>>
      


      CH 10 - Solution 1.2

      isleap(year) - Return 1 for leap years, 0 for non-leap years.


      >>> from calendar import *
      >>> isleap(2008)
      True
      >>> isleap(2009)
      False
      >>>
      

      CH 10 - Solution 2

      CH 10 - Solution 2.1

       python C:\Python26\Lib\pydoc.py -p 7464 
      

      CH 10 - Solution 2.2

      There are 35 functions in the math module.

      CH 10 - Solution 2.3

      The floor function finds the greatest integral value less than or equal to x. The ceil function finds the lowest integeral value greater than or equal to x.

      CH 10 - Solution 2.4

      CH 10 - Solution 2.5

      The two data constants in the math module are: 'e' and 'pi'.

      CH 10 - Solution 3

      """
      Interface summary:
       
              import copy
       
              x = copy.copy(y)        # make a shallow copy of y
              x = copy.deepcopy(y)    # make a deep copy of y
       
      For module specific errors, copy.Error is raised.
       
      The difference between shallow and deep copying is only relevant for
      compound objects (objects that contain other objects, like lists or
      class instances).
       
      - A shallow copy constructs a new compound object and then (to the
        extent possible) inserts *the same objects* into it that the
        original contains.
       
      - A deep copy constructs a new compound object and then, recursively,
        inserts *copies* into it of the objects found in the original."""
      

      deepcopy would have come handy in exercises you didn't have to solve regarding object reference, thus no answer is excpected here.

      CH 10 - Solution 4

      CH 10 - Solution 5

      CH 10 - Solution 6

      Namespaces are one honking great idea -- let's do more of those!

      CH 10 - Solution 7

      CH 10 - Solution 8

      def matrix_mult(m1, m2):

        """
           >>> matrix_mult([[1, 2], [3,  4]], [[5, 6], [7, 8]])
           [[19, 22], [43, 50]]
           >>> matrix_mult([[1, 2, 3], [4,  5, 6]], [[7, 8], [9, 1], [2, 3]])
           [[31, 19], [85, 55]]
           >>> matrix_mult([[7, 8], [9, 1], [2, 3]], [[1, 2, 3], [4, 5, 6]])
           [[39, 54, 69], [13, 23, 33], [14, 19, 24]]
         """
        
        qr = len(m1)
        qc = len(m2[0])
        NewMtx = []
        for row in range(qr):
            newRow = []
            for column in range(qc):
                newRow.append(row_times_column(m1, row, m2, column))
            NewMtx.append(newRow)
        return NewMtx
      

      return NewMtx

           qr = len(m1)
        qc = len(m2[0])
        NewMtx = []
        for row in range(qr):
            newRow = []
            for column in range(qc):
                newRow.append(row_times_column(m1, row, m2, column))
            NewMtx.append(newRow)
      

      CH 10 - Solution 9

      CH 10 - Solution 10

      def myreplace(old, new, s):
          """
          Replace all occurences of old with new in the string s.
       
            >>> myreplace(',', ';', 'this, that, and, some, other, thing')
            'this; that; and; some; other; thing'
            >>> myreplace(' ', '**', 'Words will now be separated by stars.')
            'Words**will**now**be**separated**by**stars.'
       
          """
          old_removed = s.split(old)
          new_added = new.join(old_removed)
          return new_added
      # Shorter version
      #    new_added = new.join(s.split(old))
      

      CH 10 - Solution 11

      def cleanword(word):
          """
            >>> cleanword('what?')
            'what'
            >>> cleanword('"now!"')
            'now'
            >>> cleanword('?+="word!,@$()"')
            'word'
          """
          cleaned_word = ''
          for i in range(len(word)):
              char = word[i]
              if char.isalpha():
                  cleaned_word += char
          return cleaned_word
       
       
      def has_dashdash(s):
          """
            >>> has_dashdash('distance--but')
            True
            >>> has_dashdash('several')
            False
            >>> has_dashdash('critters')
            False
            >>> has_dashdash('spoke--fancy')
            True
            >>> has_dashdash('yo-yo')
            False
          """
          return s.find('--') != -1
       
       
      def extract_words(s):
          """
            >>> extract_words('Now is the time!  "Now", is the time? Yes, now.')
            ['now', 'is', 'the', 'time', 'now', 'is', 'the', 'time', 'yes', 'now']
            >>> extract_words('she tried to curtsey as she spoke--fancy')
            ['she', 'tried', 'to', 'curtsey', 'as', 'she', 'spoke', 'fancy']
          """
          if has_dashdash(s):
              s = myreplace('--', ' ', s) #using myreplace function from Q. 10
          words_punc = s.split()
          cleanlist = []
          for word in words_punc:
              cleanedword = cleanword(word).lower()
              cleanlist.append(cleanedword)
          return cleanlist
       
       
      def wordcount(word, wordlist):
          """
            >>> wordcount('now', ['now', 'is', 'time', 'is', 'now', 'is', 'is'])
            ['now', 2]
            >>> wordcount('is', ['now', 'is', 'time', 'is', 'now', 'is', 'the', 'is'])
            ['is', 4]
            >>> wordcount('time', ['now', 'is', 'time', 'is', 'now', 'is', 'is'])
            ['time', 1]
            >>> wordcount('frog', ['now', 'is', 'time', 'is', 'now', 'is', 'is'])
            ['frog', 0]
          """
       
          return [word, wordlist.count(word)]
       
       
      def wordset(wordlist):
          """
            >>> wordset(['now', 'is', 'time', 'is', 'now', 'is', 'is'])
            ['is', 'now', 'time']
            >>> wordset(['I', 'a', 'a', 'is', 'a', 'is', 'I', 'am'])
            ['I', 'a', 'am', 'is']
            >>> wordset(['or', 'a', 'am', 'is', 'are', 'be', 'but', 'am'])
            ['a', 'am', 'are', 'be', 'but', 'is', 'or']
          """
       
          for word in wordlist:
              count = wordcount(word, wordlist)[1]
              if count > 1:
                  for a in range(count - 1):
                      wordlist.remove(word)
          wordlist.sort()
          return wordlist
       
       
      def longestword(wordset):
          """
            >>> longestword(['a', 'apple', 'pear', 'grape'])
            5
            >>> longestword(['a', 'am', 'I', 'be'])
            2
            >>> longestword(['this', 'that', 'supercalifragilisticexpialidocious'])
            34
          """
          longest = 0
          for word in wordset:
              length = len(word)
              if length > longest:
                  longest = length
          return longest
       
       
      if __name__ == '__main__':
          import doctest
          doctest.testmod()
      

      CH 10 - Solution 12

      #sort_fruits.py
       
      source = open('unsorted_fruits.txt', 'r')
      fruits = source.readlines()
      source.close()
      fruits.sort()
      newfile = open('sorted_fruits.txt', 'w')
      newfile.writelines(fruits)
      newfile.close()
      

      CH 10 - Solution 13

      CH 10 - Solution 14

      #mean.py
       
      from sys import argv
       
      nums = argv[1:]
       
      for i, value in enumerate(nums):
          nums[i] = float(value)
       
      mean = sum(nums) / len(nums)
       
      print mean
      

      CH 10 - Solution 15

      #median.py
       
      from sys import argv
      nums = argv[1:]
       
      for i, value in enumerate(nums):
          nums[i] = float(value)
       
      nums.sort()
      size = len(nums)
      middle = size / 2
       
      if size % 2 == 0:
          median = (nums[middle - 1] + nums[middle]) / 2
      else:
          median = nums[middle]
       
      if median == float(int(median)):
          median = int(median)
       
      print median
      

      CH 10 - Solution 16

      #
      # countletters.py
      #
       
      def display(i):
          if i == 10: return 'LF'
          if i == 13: return 'CR'
          if i == 32: return 'SPACE'
          return chr(i)
       
      from sys import argv
       
      filename = argv[1]
       
      infile = open(filename, 'r')
      text = infile.read()
      infile.close()
       
      counts = 128 * [0]
       
      for letter in text:
          counts[ord(letter)] += 1
       
      filenamesplit = filename.split('.') # splits 'name.txt' -> ['name', 'txt']
      count_file = filenamesplit[0] + '_counts.dat' # 'name' -> 'name_counts.dat'
       
      outfile = open(count_file, 'w')
      outfile.write("%-12s%s\n" % ("Character", "Count"))
      outfile.write("=================\n")
       
      for i in range(len(counts)):
          if counts[i]:
              outfile.write("%-12s%d\n" % (display(i), counts[i]))
       
      outfile.close()
      
      ↑Jump back a section

      Chapter 11

      CH 11 - Solution 1

      CH 11 - Solution 2

      CH 11 - Solution 3

      #
      #seqtools.py
      #
       
      def remove_at(pos, seq):
          return seq[:pos] + seq[pos+1:]
       
       
      def encapsulate(val, seq):
          """
            >>> encapsulate((1, 'a'), [0 , 'b'])
            [(1, 'a')]
            >>> encapsulate(42, 'string')
            '42'
            >>> tup = 1, 2, 3                   # NB. Testmod seems to report this
            >>> encapsulate(5, tup)             # as a fail, despite returning the
            (5,)                                # correct result?
          """
       
          if type(seq) == type(""):
              return str(val)
          if type(seq) == type([]):
              return [val]
          return (val,)
       
       
      def insert_in_middle(val, seq):
          """
            >>> insert_in_middle('two', (1,3))
            (1, 'two', 3)
            >>> insert_in_middle(4, 'two  six')
            'two 4 six'
            >>> insert_in_middle((2, 4), [(1, 2), (3, 6)])
            [(1, 2), (2, 4), (3, 6)]
          """
          middle = len(seq)/2
          return seq[:middle] + encapsulate(val, seq) + seq[middle:]
       
       
      def make_empty(seq):
          """
            >>> make_empty([1, 2, 3, 4])
            []
            >>> make_empty(('a', 'b', 'c'))
            ()
            >>> make_empty("No, not me!")
            ''
          """
          if type(seq) == type(""):
              return ''
          if type(seq) == type([]):
              return []
          return ()
       
       
      def insert_at_end(val, seq):
          """
            >>> insert_at_end(5, [1, 3, 4, 6])
            [1, 3, 4, 6, 5]
            >>> insert_at_end('x', 'abc')
            'abcx'
            >>> insert_at_end(5, (1, 3, 4, 6)) # NB. Testmod seems to report this as a fail
            (1, 3, 4, 6, 5)                    # despite returning the correct result
          """
          return seq + encapsulate(val, seq)
       
       
      def insert_in_front(val, seq):
          """
            >>> insert_in_front(5, [1, 3, 4, 6])
            [5, 1, 3, 4, 6]
            >>> insert_in_front(5, (1, 3, 4, 6))
            (5, 1, 3, 4, 6)
            >>> insert_in_front('x', 'abc')
            'xabc'
          """
          return encapsulate(val, seq) + seq
       
       
      def index_of(val, seq, start=0):
          """
            >>> index_of(9, [1, 7, 11, 9, 10])
            3
            >>> index_of(5, (1, 2, 4, 5, 6, 10, 5, 5))
            3
            >>> index_of(5, (1, 2, 4, 5, 6, 10, 5, 5), 4)
            6
            >>> index_of('y', 'happy birthday')
            4
            >>> index_of('banana', ['apple', 'banana', 'cherry', 'date'])
            1
            >>> index_of(5, [2, 3, 4])
            -1
            >>> index_of('b', ['apple', 'banana', 'cherry', 'date'])
            -1
          """
          for i in range(start, len(seq)):
              if seq[i] == val:
                  return i
          return -1
       
       
      def remove_at(index, seq):
          """
            >>> remove_at(3, [1, 7, 11, 9, 10])
            [1, 7, 11, 10]
            >>> remove_at(5, (1, 4, 6, 7, 0, 9, 3, 5))
            (1, 4, 6, 7, 0, 3, 5)
            >>> remove_at(2, "Yomrktown")
            'Yorktown'
          """
          return seq[:index] + seq[index + 1:]
       
       
      def remove_val(val, seq):
          """
            >>> remove_val(11, [1, 7, 11, 9, 10])
            [1, 7, 9, 10]
            >>> remove_val(15, (1, 15, 11, 4, 9))
            (1, 11, 4, 9)
            >>> remove_val('what', ('who', 'what', 'when', 'where', 'why', 'how'))
            ('who', 'when', 'where', 'why', 'how')
          """
          return remove_at(index_of(val, seq), seq)
       
       
      def remove_all(val, seq):
          """
            >>> remove_all(11, [1, 7, 11, 9, 11, 10, 2, 11])
            [1, 7, 9, 10, 2]
            >>> remove_all('i', 'Mississippi')
            'Msssspp'
          """
          while index_of(val, seq) != -1:
              seq = remove_val(val, seq)
          return seq
       
       
      def count(val, seq):
          """
            >>> count(5, (1, 5, 3, 7, 5, 8, 5))
            3
            >>> count('s', 'Mississippi')
            4
            >>> count((1, 2), [1, 5, (1, 2), 7, (1, 2), 8, 5])
            2
          """
          count = 0
          for item in seq:
              if item == val:
                  count += 1
          return count
       
       
      def reverse(seq):
          """
            >>> reverse([1, 2, 3, 4, 5])
            [5, 4, 3, 2, 1]
            >>> reverse(('shoe', 'my', 'buckle', 2, 1))
            (1, 2, 'buckle', 'my', 'shoe')
            >>> reverse('Python')
            'nohtyP'
          """
          output = make_empty(seq)
          for item in seq:
              output = insert_in_front(item, output)
          return output
       
       
       
      def sort_sequence(seq):
          """
            >>> sort_sequence([3, 4, 6, 7, 8, 2])
            [2, 3, 4, 6, 7, 8]
            >>> sort_sequence((3, 4, 6, 7, 8, 2))
            (2, 3, 4, 6, 7, 8)
            >>> sort_sequence("nothappy")
            'ahnoppty'
          """
          listseq = list(seq)
          listseq.sort()
          output = make_empty(seq)
          for item in listseq:
              output = insert_at_end(item, output)
          return output
      


      CH 11 - Solution 4

      def recursive_min(nested_num_list):
          """
            >>> recursive_min([2, 9, [1, 13], 8, 6])
            1
            >>> recursive_min([2, [[100, 1], 90], [10, 13], 8, 6])
            1
            >>> recursive_min([2, [[13, -7], 90], [1, 100], 8, 6])
            -7
            >>> recursive_min([[[-13, 7], 90], 2, [1, 100], 8, 6])
            -13
          """
          smallest = nested_num_list[0]
          while type(smallest) == type([]):
              smallest = smallest[0]
       
          for element in nested_num_list:
              if type(element) == type([]):
                  min_of_elem = recursive_min(element)
                  if smallest > min_of_elem:
                      smallest = min_of_elem
              else:
                  if smallest > element:
                      smallest = element
       
          return smallest
      

      CH 11 - Solution 5

      def recursive_count(target, nested_num_list):
          """
            >>> recursive_count(2, [2, 9, [2, 1, 13, 2], 8, [2, 6]])
            4
            >>> recursive_count(7, [[9, [7, 1, 13, 2], 8], [7, 6]])
            2
            >>> recursive_count(15, [[9, [7, 1, 13, 2], 8], [2, 6]])
            0
            >>> recursive_count(5, [[5, [5, [1, 5], 5], 5], [5, 6]])
            6
          """
          count = 0
       
          for element in nested_num_list:
              if type(element) == type([]):
                  count += recursive_count(target, element)
              else:
                  if element == target:
                      count += 1
       
          return count
      

      CH 11 - Solution 6

      def flatten(nested_num_list):
          """
            >>> flatten([2, 9, [2, 1, 13, 2], 8, [2, 6]])
            [2, 9, 2, 1, 13, 2, 8, 2, 6]
            >>> flatten([[9, [7, 1, 13, 2], 8], [7, 6]])
            [9, 7, 1, 13, 2, 8, 7, 6]
            >>> flatten([[9, [7, 1, 13, 2], 8], [2, 6]])
            [9, 7, 1, 13, 2, 8, 2, 6]
            >>> flatten([[5, [5, [1, 5], 5], 5], [5, 6]])
            [5, 5, 1, 5, 5, 5, 5, 6]
          """
          flat_num_list = []
       
          for element in nested_num_list:
              if type(element) == type([]):
                  flat_num_list += flatten(element)
              else:
                  flat_num_list += [element]
       
          return flat_num_list
      

      CH 11 - Solution 7

      def readposint(prompt = 'Please enter a positive integer: '):
          while True:
              posint = raw_input(prompt)
              try:
                  posint = float(posint)
                  if posint != int(posint):
                      raise ValueError, '%s is not an integer' % posint
                  elif posint < 1:
                      raise ValueError, '%s is not positive' % posint
                  break
              except:
                  print '%s is not a positive integer. Try again.' % posint
       
          return int(posint)
      

      CH 11 - Solution 8

      CH 11 - Solution 9

      CH 11 - Solution 10

      def factorial(n):
          nshriek = 1       # n factorial is sometimes called 
          while n > 1:      # 'n shriek' because of the 'n!' notation
              nshriek *= n
              n -= 1
          return nshriek
      

      CH 11 - Solution 11

      #
      # litter.py
      #
       
      import os
      import sys
       
       
      def getroot():
          if len(sys.argv) == 1:
              path = ''
          else:
              path = sys.argv[1]
       
          if os.path.isabs(path):
              tree_root = path
          else:
              tree_root = os.path.join(os.getcwd(), path)
       
          return tree_root
       
       
      def getdirlist(path):
          dirlist = os.listdir(path)
          dirlist = [name for name in dirlist if name[0] != '.']
          dirlist.sort()
          return dirlist
       
       
      def traverse(path, t=0):
          dirlist = getdirlist(path)
       
          for num, file in enumerate(dirlist):
              dirsize = len(dirlist)
       
              path2file = os.path.join(path, file)
       
              if os.path.isdir(path2file):
                  t += 1
                  newtrash = open(path2file + '\\trash.txt', 'w')
                  newtrash.close()
       
                  if getdirlist(path2file):
                      t = traverse(path2file, t)
       
          return t
       
       
      if __name__ == '__main__':
          root =  getroot()
          trashes = traverse(root)
       
          if trashes == 1:
              filestring = 'file'
          else:
              filestring = 'files'
       
          print '%d trash.txt %s created' % (trashes, filestring)
      
      #
      # cleanup.py
      #
       
      import os
      import sys
       
       
      def getroot():
          if len(sys.argv) == 1:
              path = ''
          else:
              path = sys.argv[1]
       
          if os.path.isabs(path):
              tree_root = path
          else:
              tree_root = os.path.join(os.getcwd(), path)
       
          return tree_root
       
       
      def getdirlist(path):
          dirlist = os.listdir(path)
          dirlist = [name for name in dirlist if name[0] != '.']
          dirlist.sort()
          return dirlist
       
       
      def traverse(path, t = 0):
          dirlist = getdirlist(path)
       
          for num, file in enumerate(dirlist):
              dirsize = len(dirlist)
              path2file = os.path.join(path, file)
       
              if file == 'trash.txt':
                  t += 1
                  os.remove(path2file)
       
              elif os.path.isdir(path2file):
                  t += traverse(path2file)
       
          return t
       
       
      if __name__ == '__main__':
          root =  getroot()
          trashed = traverse(root)
       
          if trashed == 1:
              filestring = 'file'
          else:
              filestring = 'files'
       
          print '%d trash.txt %s deleted' % (trashed, filestring)
      
      ↑Jump back a section

      Chapter 12

      CH 12 Solution 1

      #
      # letter_counts.py
      #
       
      import sys
       
      def count_letters(s):
          letter_counts = {}
          for letter in s:
              if letter.isalpha():
                  letter_counts[letter.lower()] = letter_counts.get(letter.lower(), 0) + 1
          return letter_counts
       
      def print_counts(letter_counts):
          letter_items = letter_counts.items()
          letter_items.sort()
          for item in letter_items:
              print item[0], item[1]
       
      if len(sys.argv) > 1:
          letter_counts = count_letters(sys.argv[1])
          print_counts(letter_counts)
      else: 
          print 'No argument supplied'
      

      CH 12 Solution 2

      def add_fruit(inventory, fruit, quantity=0):
           """
           Adds quantity of fruit to inventory.
       
             >>> new_inventory = {}
             >>> add_fruit(new_inventory, 'strawberries', 10)
             >>> new_inventory.has_key('strawberries')
             True
             >>> new_inventory['strawberries']
             10
             >>> add_fruit(new_inventory, 'strawberries', 25)
             >>> new_inventory['strawberries']
             35
           """
           if inventory.has_key(fruit):
               inventory[fruit] += quantity
           else:
               inventory[fruit] = quantity
      

      CH 12 Solution 3

      #
      # alice_words.py
      #
       
      import string
       
      filename = 'alice_in_wonderland.txt'
      countfile = 'alice_counts.txt'
       
      def add_word(counts, word):
          if counts.has_key(word):
              counts[word] += 1
          else:
              counts[word] = 1
       
      def get_word(item):  
          word = ''
          item = item.strip(string.digits)
          item = item.lstrip(string.punctuation)
          item = item.rstrip(string.punctuation)
          word = item.lower()
          return word
       
       
      def count_words(text):
          text = ' '.join(text.split('--')) #replace '--' with a space
          items = text.split() #leaves in leading and trailing punctuation,
                               #'--' not recognised by split() as a word separator
          counts = {}
          for item in items:
              word = get_word(item)
              if not word == '':
                  add_word(counts, word)
          return counts
       
      infile = open(filename, 'r')
      text = infile.read()
      infile.close()
       
      counts = count_words(text)
       
      outfile = open(countfile, 'w')
      outfile.write("%-18s%s\n" %("Word", "Count"))
      outfile.write("=======================\n")
       
      counts_list = counts.items()
      counts_list.sort()
      for word in counts_list:
          outfile.write("%-18s%d\n" %(word[0], word[1]))
       
      outfile.close
      

      The word "alice" occurs 386 times (not including 12 occurences of "alice's")

      CH 12 Solution 4

      The longest 'word' in the list is "bread-and-butter" with 16 characters. This can be found by adding the following code to the alice_words.py program:

      longest = ('', 0)
      for word in counts:
          if len(word) > longest[1]:
              longest = (word, len(word))
      print longest
      

      Slightly altering this we can find the longest unhyphenated word, "disappointment", which has 14 characters.

      longest = ('', 0)
      for word in counts:
          if len(word) > longest[1] and word.find('-') == -1
              longest = (word, len(word))
      print longest
      

      CH 12 Solution 5

      CH 12 Solution 6

      CH 12 Solution 7

      CH 12 Solution 8

      CH 12 Solution 9

      CH 12 Solution 10

      CH 12 Solution 11

      CH 12 Solution 12

      ↑Jump back a section

      Chapter 13

      CH 13 Solution 1

      CH 13 Solution 2

      def distance(p1, p2):
          dx = p2.x - p1.x
          dy = p2.y - p1.y
          dsquared = dx**2 + dy**2
          result = dsquared**0.5
          return result
      

      CH 13 Solution 3

      def move_rect(rect, dx, dy):
          rect.corner.x += dx
          rect.corner.y += dy
      

      CH 13 Solution 4

      def move_rect(rect, dx, dy):
          import copy
          new_rect = copy.deepcopy(rect)
          new_rect.corner.x += dx
          new_rect.corner.y += dy
          return new_rect
      
      ↑Jump back a section

      Chapter 14

      CH 14 Solution 1

      def print_time(t):
          print "%i:%i:%i" % (t.hours, t.minutes, t.seconds)
      

      CH 14 Solution 2

      def after(t1, t2):
          return convert_to_seconds(t1) > convert_to_seconds(t2)
      

      CH 14 Solution 3

      def increment(time, seconds):
          sum = convert_to_seconds(time) + seconds
          newtime = make_time(sum)
          time.hours = newtime.hours
          time.minutes = newtime.minutes
          time.seconds = newtime.seconds
       
      >>> increment(t1, 180)
      

      CH 14 Solution 4

      def increment(time, seconds):
          sum = convert_to_seconds(time) + seconds
          newtime = make_time(sum)
          return newtime
       
      >>> increment(t1, 180)
      <__main__.Time instance at 0x91ceeac>
       
      >>> t1 = increment(t1, 180)
      
      ↑Jump back a section

      Chapter 15

      CH 15 Solution 1

      class Time():
       
      # other method definitions here
       
          def convertToSeconds(self):
              minutes = self.hours * 60 + self.minutes
              seconds = minutes * 60 + self.seconds
              return seconds
      

      CH 15 Solution 2

      def find(str, ch, start=0, end = "None"):
          index = start
          if end == "None":
              end = len(str)
          while index < end:
              if str[index] == ch:
                  return index
              index = index + 1
          return -1
      
      ↑Jump back a section

      Chapter 16

      CH 16 Solution 1

      class Card:
      ...
          def __cmp__(self, other):
              # check the suits
              if self.suit > other.suit: return 1
              if self.suit < other.suit: return -1
              # suits are the same... check ranks
              if self.rank > other.rank:
                  if other.rank == 1: return -1 #other is Ace (and self is not)
                  return 1
              if self.rank < other.rank:
                  if self.rank == 1: return 1 #self is Ace (and other is not)
                  return -1
              # ranks are the same... it's a tie
              return 0
      
      ↑Jump back a section

      Chapter 17

      CH 17 Solution 1

      class OldMaidGame(CardGame):
      ...
          def printHands(self):
              for hand in self.hands:
                  print hand
      
      ↑Jump back a section

      Chapter 18

      CH 18 Solution 1

      def print_list(node):
          s = '['
          while node:
              s += str(node.cargo)
              node = node.next
              if node:
                  s += ', '
          s += ']'
          print s
      
      ↑Jump back a section

      Chapter 19

      CH 19 Solution 1

      >>> print eval_postfix("1 2 + 3 *")
      9
      

      CH 19 Solution 2

      >>> print eval_postfix("1 2 3 * +")
      7
      
      ↑Jump back a section

      Chapter 20

      Solution 1

      class listQueue:
          def __init__(self):
              self.items = []
       
          def is_empty(self):
              return self.items == []
       
          def insert(self, item):
              self.items.append(item)
       
          def remove(self):
              if self.is_empty():
                  return None
              return self.items.pop()
      
      class llPriorityQueue:
          def __init__(self):  # NB, self.last is no longer needed because
              self.length = 0  # the linked list will be ordered with
              self.head = None # the next item to be removed at the head
       
          def is_empty(self):
              return (self.length == 0)
       
          def insert(self, cargo):   # insert() needs to keep the list ordered to
              node = Node(cargo)     # make remove() constant time. So insert()
              if self.head == None:  # must traverse the list. Now insert() is
                  self.head = node   # linear time instead of remove()!
              else:
                  if cargo > self.head.cargo:
                      node.next = self.head
                      self.head = node
                  else:
                      smaller = self.head          
                      while smaller.cargo >= cargo:# traverse queue until we 
                          previous = smaller       # find first node with cargo
                          smaller = smaller.next   # smaller than the new node
                          if smaller == None:      #<--(or we get to the end
                              break                #    of the list)
                      previous.next = node         # insert node ahead of first
                      node.next = smaller          # smaller item
              self.length += 1
       
          def remove(self):
              if self.is_empty():
                  return None
              cargo = self.head.cargo
              self.head = self.head.next
              self.length = self.length - 1
              return cargo
      
      ↑Jump back a section

      Chapter 21

      CH 21 Solution 1

      def print_tree_inorder(tree):
          if tree == None: return
          if tree.left:
              print '(',
          print_tree_inorder(tree.left),
          print tree.cargo,
          print_tree_inorder(tree.right),
          if tree.right:
              print ')',
       
      # The output from this function is correct and unambiguous, but many 
      # brackets are not really necessary and look messy. For example:
      >>> token_list =['(',3, '+', 7, ')', '*', '(', 5, '+', 3, ')', '+', 4, '*', 5, 'end']
      >>> tree = get_sum(token_list)
      >>> print_tree_inorder(tree)
      ( ( ( 3 + 7 ) * ( 5 + 3 ) ) + ( 4 * 5 ) )
      # The ideal output would be something like: (3 + 7) * (5 + 3) + 4 * 5
      

      CH 21 Solution 2

      def make_token_list(s):
          token_list = []
          for char in s:
              if char == ' ':
                  continue
              elif char.isdigit():
                  token_list.append(int(char))
              else:
                  token_list.append(char)
          token_list.append('end')
          return token_list
      

      CH 21 Solution 3

      CH 21 Solution 4

      # ... (only modified functions shown)
       
      def dump(tree):                  
          # returns string representation of tree in postfix-style
          # order with commas separating nodes. Leaves are
          # represented with two preceding commas, corresponding to
          # the empty tree.left & tree.right attributes.
          if tree == None: return ','  
          s = ''                       
          s += dump(tree.left)        
          s += dump(tree.right)
          s += str(tree) + ','   
          return s
       
      def restore_tree(token_list):
          # Recreate tree from token list generated from save file
          cargo = token_list.pop()
          if cargo == '': return
          right = restore_tree(token_list)
          left = restore_tree(token_list)
          tree = Tree(cargo, left, right)
          return tree
       
      def animal():
          #start with a singleton
          root = Tree("bird")
       
          # or use save file if it exists
          try:
              infile = open(savefile, 'r')
              s = infile.read()
              infile.close()
              token_list = s.split(',')
              token_list.pop() #remove empty item at end
              root = restore_tree(token_list)
          except IOError: 
              pass
       
          # loop until the user quits
          while True:
              print
              if not yes("Are you thinking of an animal? "): break
       
              # walk the tree
              tree = root
              while tree.left != None:
                  prompt = tree.cargo + "? "
                  if yes(prompt):
                      tree = tree.right
                  else:
                      tree = tree.left
       
              # make a guess
              guess = tree.cargo
              prompt = "Is it a " + guess + "? "
              if yes(prompt):
                  print "Yatta!"
                  continue
       
              # get new information
              prompt  = "What is the animal's name? "
              animal  = raw_input(prompt)
              prompt  = "What question would distinguish a %s from a %s? "
              question = raw_input(prompt % (animal, guess)).strip('?').capitalize()
       
              # add new information to the tree
              tree.cargo = question
              prompt = "If the animal were %s the answer would be? "
              if yes(prompt % animal):
                  tree.left = Tree(guess)
                  tree.right = Tree(animal)
              else:
                  tree.left = Tree(animal)
                  tree.right = Tree(guess)
       
          # save the tree
          s = dump(root)
          outfile = open(savefile, 'w')
          outfile.write(s)
          outfile.close()
      
      ↑Jump back a section
      Last modified on 23 April 2013, at 02:30