CMPSCI 291b: Reasoning About Uncertainty

David Mix Barrington

Spring, 2008

Programming Project 1: Listing Solutions to the Counting Problems

In this project our goal is to create methods that will list all solutions to our four counting problems, given parameters n (the number of items to be chosen from, which will be the set {1,...,n}) and k (the number of items to be chosen). Remember the types of sequences we are counting in each case:

  1. First Problem: Count all sequences of length k where the items are in the set {1,...,n}. We will call these sequences Sequence objects.
  2. Second Problem: Count only the sequences that have no element occurring more than once. We will call these sequences Perm objects.
  3. Third Problem: Count sequences with no repeated elements that are also sorted, so that no larger element occurs before a smaller element. We call these sequences Set objects.
  4. Fourth Problem: Count the sorted sequences, even if they include repeated elements. We call these sequences Multiset objects.

We will thus have a class Sequence and classes Perm , Set, and Multiset extending Sequence. Here is something like the API for Sequence:

    public class Sequence {
       public int n; // elements will be in {1,...,n}
       public int k; // number of elements 
       public int [] values = new int[k]; // the elements 

       public Sequence(int n, int k) 
       {// constructor, gives first sequence, all 1's
          for (int i=0; i<k; i++) values[i] = 1;}

       public String toString() {
          if (k == 0) return "";
          else {
             String w = Integer.toString(values[0]);
             for (int i=1; i<k; i++)
                w += (" " + Integer.toString(values[i]));}
          return w;}

       public boolean isFirst()
       {// returns whether this is the first sequence of its type
           for (int i=0; i<k; i++)
              if (values[i] != 1) return false;
           return true;}

       public void iterate ()
       {// changes this sequence to next one in order
        // you write code
        // last sequence iterates to first one
       }

       public Sequence next ()
       {// returns sequence after this one in order
        // you write code
       }

       public static void printAll(int n, int k)
       {// prints all sequences with of length k and range n
           Sequence s = new Sequence(n,k);
           do {
              System.out.println(s.toString);
              s.iterate();}
              while (!s.isFirst());}

We then have to write the three classes extending Sequence, and overwrite:

That's a start. The other idea we discussed on Friday 1 February was whether we could make a recursive sequence lister, to avoid the difficulty in particular of coding the Perm.iterate method. The idea is that to list all Perm objects with parameters n and k, we let a variable i loop from 1 through n, and for each i we list length-k perms starting with i and continuing with a translated version of all perms with parameters n-1 and k-1. For example, let n=4, k=3, and i=2. There are six perms of length 3 starting with 2, which are 213, 214, 231, 234, 241, and 243. If we take the six perms of length 2 with elements from {1,2,3}, we get 12, 13, 21, 23, 31, and 32. We make each of the length-3 perms by putting a 2 first and then translating the two elements of the length-2 perm, with 2's becoming 3's and 3's becoming 4's.

The problem with implementing this is that our sequence lister must have an interface allowing it to accept the output of another version of itself. I think the easiest way to do this is to have the lister be an iterator object, which we can initialize and iterate as needed -- then the length-k iterator can contain a length-(k-1) iterator within it.

Here's the promised additional detail on the alternate implementation. Let's define a PermIterator class:


     public class PermIterator
     {// lists all Perms of range n and length k
         int n; // entries range from 1 to n
         int k; // range of entries
         PermIterator sub; // PermIterator variable for recursive call
         int i; // index for looping through value of (virtual) current[0]

         public PermIterator (int newN, int newK)
         {// sets up sub if required
             n = newN;
             k = newK;
             if (k > 0) {
                i = 1;
                sub = new PermIterator(n-1; k-1);}}

         public void reset()
         {// sets current to [1,2,...,k], i to 1, resets sub if it exists
          // code missing
         }
         public boolean hasNext()
         {// returns whether another Perm is available in the list
             if (i < n) return false;
             if (k == 0) return false;
             return sub.hasNext();}

         public Perm next()
         {// returns next Perm in canonical ordering
             Perm out = new Perm(n,k);
             if (sub.hasNext())
                {// return i followed by translation of sub.next()
                 // code missing...
                 }
             else {
                if (i < n) i++; 
                else i = 1;}}}

Last modified 19 February 2008