6.170 Laboratory in Software Engineering
Spring 2000
Problem Set 0: Solution


There are a couple of ways of solving this problem:
  1. Using an array of 26 elements, and mapping character 'a' to the first element of the array, 'b' to the second, etc.
  2. Using a full-fledged hashtable
  3. Sorting the array
  4. Passing over the array multiple times (once for each character)
Solution (1) is the most elegant.  It works if Here's the Java code.  The code is more robust than required by the problem.
public class Main {
/** Number of letters in the alphabet */
    public static final int LETTERS=26;

    public static void printStats(String str) {
        /** requires: <str> contains only lower case letters
          * effects:  For each character c appearing i times in <str>,
          *           where i>0, prints "c : i" to standard output.
          */

        // counts[j] is the number of times the j'th letter of the alphabet
        // has been found in str
        int counts[]=new int[LETTERS];

        // For each character <c> in <str>...
        for (int i=0; i<str.length(); i++) {
            int c=str.charAt(i);
            //If lower case, increment count; otherwise ignore
            //The 'if' test isn't required by the problem.
            if (c>='a' && c<='z')
                counts[c-'a']++;
        }

        // Print all non-zero counts
        for (int i=0; i<LETTERS; i++)
            if (counts[i]!=0)
                System.out.println((char)('a'+i) +" : "+ counts[i]);
    }

    public static void main(String args[]) {
        String str="abzbz";
        System.out.println(str+":");
        printStats(str);
    }
}


Here's an example of (2) using Scheme.  Note that it is more robust but doesn't print the results in alphabetic order.  This algorithm is also less efficient.

(define (count clist)
  ;;requires: <clist> is a list of symbols
  ;;effects: returns a list L '((x_1 . y_1) ... (x_n . y_n)) s.t.
  ;;           1.  x_i=x_j ==> i=j
  ;;           2.  x is in <clist> ==> x is in (map car L)
  ;;           3.  (x . y) is in L ==> x occurs y times in <clist>
  (define (iter clist alist)
       ;;<alist> is an association list between symbols and numbers
       (if (null? clist)
           alist
           (let* ((char (car clist))
                  (rest (cdr clist))
                  (pair (assq char alist)))
             ;;Found char in alist?
             (if pair
                 ;;Destructively increment char's associated value
                 ;;in alist and tail recurse.
                 (begin
                   (set-cdr! pair (+ 1 (cdr pair)))
                   (iter rest alist))
                 ;;Add an association between char and 1 in alist
                 ;;before tail recurse.
                 (iter rest
                       (cons (cons char 1)
                             alist))))))
  (iter clist '()))

(count '(m i s s i s s i p p i))