CS 313 - Homework 5 - Smalltalk (+ Python)

Part 1 due: Wednesday 10/20 at 10am

Part 2 due: Wednesday 10/27 at 10am

This homework consists of two programming problems in Smalltalk and an optional programming problem in Python. The first problem is due Wednesday after break, and must be done individually. It is fairly short, and it will give you valuable experience in Smalltalk before the midterm exam on Thursday 10/21. You cannot take one of your 24h extensions on part 1.

The other problems are due in two weeks, on Wednesday 10/27. You may work on problems 2 and 3 only in groups of two, or by yourself.

Submit your code via the links below by the respective deadline. To submit Smalltalk code, copy and paste your method and class definitions into a text file, and format it nicely, as in my examples. Instead of copying and pasting, you can also right-click on your classes category, select "file out", and use the resulting .st file (which should end up in the same folder as the Squeak executable) as a starting point. For problems 2 and 3, only one person per group should submit. Be sure your names appear in a comment at the top of your program.

Running Squeak

If you haven't already, install Squeak by following the instructions. You should do all your work using the same session, which Squeak stores in "image" and "changes" files. When you quit Squeak, be sure to always save the current image.

If you need to interrupt an infinite loop, hit Alt-period (PC) or Command-period (Mac). See FAQ.

Part 1 (due Wednesday 10/20 at 10am, no extensions)

  1. Implement a new method primesUpTo for the class SmallInteger that returns an OrderedCollection of all prime numbers less or equal to the receiver.

    Sample output (the arrow indicates "PrintIt"):

        29 primesUpTo  ->  an OrderedCollection(2 3 5 7 11 13 17 19 23 29)
    Specific instructions:
    • Create a new category for your methods in the SmallInteger class right-clicking in the third pane of the System Browser as demonstrated in class.
    • Implement the Sieve of Eratosthenes as discussed in class.
    • Use an object of class OrderedCollection to return the list of primes. Use "OrderedCollection new" to create an empty collection, and use the message "add: anObject" to add a new element to the end of the collection.
    • Use an object of class Array to hold an array of Booleans that represent whether the number at the current index is prime or not. Supposing that N is an integer, use "Array new: N" to create an array with N elements (indexed from 1 to N). Use the messages "at: i" to get the element at index i, "at: i put: x" to set the element at index i to x, and "atAllPut: x" to set all elements to x.

    To submit your code, copy and paste your method definition into a text file "primes.txt". Don't forget to document your method, and to include sample output (which you can copy and paste from a workspace window). Also, don't forget to include your name, and report any sources you consulted and/or students you collaborated with. Upload your file primes.txt via the HW 5.1 submission page by 10am on Wednesday 10/20.

Part 2 (due Wednesday 10/27 by 10am)

  1. Implement a binary search tree in an object-oriented fashion in Smalltalk. This is similar to Sethi, p. 296, problem 7.6, where you can find some code to get started (be sure to read also problem 7.3). Note that unlike in the linked list example, where there is only one IntList object and multiple IntListElt objects, here each subtree is a "Tree" object! In addition to the requirements of problem 7.6, your "Node" class should also have an instance variable "data" (which will hold an integer), and members of the "Tree" class should understand the messages "insert:" and "member:" (just like in homework 2 and 3). "Tree" objects should also understand the message "values", which should return an OrderedCollection of all the values in the tree, collected using an in-order traversal. Here is some sample output:
          t:= Tree new. t insert: 3. t insert: 1. t insert: 2.
          t member: 1.      -> true
          t member: 4.      -> false
          t values.         -> an OrderedCollection(1 2 3)
    Tips: In my sample solution, I use the following instance methods:
    • for class Tree: "member: anInt", "insert: anInt", "values", as well as "isEmpty" and "do: aBlock".
    • for class Node: accessor methods for all 3 instance variables, as well as "do: aBlock".
    The "do:" methods are used to perform a block on each data element in the tree using an in-order traversal. Once you have those, writing "values" is easy. I also define my own class method "new" for one of the two classes (I won't tell you which), to make sure everything is properly initialized.

  2. (Optional - mostly for fun, and a few points of extra credit)
    Implement a Fraction class in Python to represent numbers such as 2/3 and -4/5. Your class should support creating new fractions with given integer numerators and denominators, the operators +, -, *, /, and conversion to float and to string. Fractions should always be stored in reduced form, i.e. 1/4 instead of 2/8.

    Store your code in a file "fraction.py". I suggest you proceed in three stages:

    1. Implement a first version with methods add, mul, toFloat, and toString, and without reducing. Given the sample testing code
      a = Fraction(6,8)
      b = Fraction(5,4)
      c = a.add(b)
      print(a.toString(), "+", b.toString(), "=", c.toString(), "=", c.toFloat())
      d = c.mul(a)
      print(c.toString(), "*", a.toString(), "=", d.toString(), "=", d.toFloat())
      your program should produce the following output:
      6/8 + 5/4 = 64/32 = 2.0
      64/32 * 6/8 = 384/256 = 1.5
    2. Add code to ensure that fractions are always reduced. Hint: a GCD function might come in handy here. Also omit denominators of 1 when converting to strings. The code above should now produce the following output:
      3/4 + 5/4 = 2 = 2.0
      2 * 3/4 = 3/2 = 1.5
    3. Add "sub" and "div" methods that implement the operations - and /, and make sure everything works for negative fractions. Also allow omitting the denominator of 1 when constructing integer fractions, e.g., a = Fraction(3). Finally, define the operators +, -, *, / to work directly with Fraction objects. This is easily accomplished in Python by renaming your "add" method into "__add__" (i.e., add two leading and two trailing underscores). Do the same for "mul" and "sub". For "div" you'll need to use "__truediv__". Also rename "toFloat" into "__float__" and "toString" into "__str__". (See the Python documentation on special method names for more information on why this works.) Now you should be able to run code like this:
      a = Fraction(2)
      b = Fraction(13, 4)
      c = a - b
      print(a, "-", b, "=", c, "=", float(c))
      a = Fraction(2, -3)
      b = Fraction(-5, 6)
      c = a / b
      print(a, "/", b, "=", c, "=", float(c))
      which should produce the following output:
      2 - 13/4 = -5/4 = -1.25
      -2/3 / -5/6 = 4/5 = 0.8

You are allowed to work in groups of two on problems 2 and 3. I only need one submission per group. Submit your smalltalk code in a text file "bst.txt" containing your code. The file should contain your class and method definitions. You can start by selecting "FileOut" from the System Browser's class categories menu. But don't just hand in the resulting file, but clean it up and organize it nicely! (See my IntList file for an example.)

Don't forget to document your methods and to include your name(s) at the top. Please include testing code and sample output! The IntList file is also an example for good sample output. In any case, give me more than just the testing code included above.

Online submission

Upload your files bst.txt and (optionally) fraction.py via the HW 5.2 submission page by 10am on Wednesday 10/27.