CS 415, Section 001 Sonoma State University Spring, 2023
 
Algorithm Analysis
Instructor: Henry M. Walker

Lecturer, Sonoma State University
Professor Emeritus of Computer Science and Mathematics, Grinnell College

Although much of this course is well developed, some details can be expected to evolve as the semester progresses.
Any changes in course details will be announced promptly during class.

Worksheet/Lab on Binary Exponentiation, Dynamic Programming, and Hashing

Binary Exponentiation

  1. For this problem, refer to Levitin, Section 6.5, for discussions of right-to-left and left-to-right binary exponentiation.

    1. How many multiplications are needed to compute a11, a12, a13, and a14 for left-to-right and right-to-left binary exponentiation? For example, is the number of multiplications the same in each case, are they all different, or are some the same and some different? Explain briefly.
    2. Apply the left-to-right binary exponentiation algorithm to compute a13, where a = 3.
    3. Apply the right-to-left binary exponentiation algorithm to compute a13, where a = 3.

    Notes: For Part b and c of this problem:

Dynamic Programming

  1. Recall that the Fibonacci sequence is defined recursively as follows: In practice, this sequence arises is a surprising number of applications!

    Program fibonacci.c defines two procedures to compute the nth Fibonacci number.

    1. Compile and run the program to clarify what it does. (In the interests of time, you may want to change the upper bound of the loop in the main procedure from 45 to 41.)
    2. In fibSeq2, why do you think fibSeq2 has only an int as parameter, rather than an int and an array as defined in fibSeq2Helper?
    3. Explain in a few sentences the role of the array arr.
    4. In fibSeq2Helper, why not declare and initialize the array in one step?
          int arr [n+1] = {0};
          
    5. Write a sentence or two to explain the test
          if (fibArr[n] != 0)
          
    6. Explain why an assignment is included in the return statement
          return fibArr[n] = 1;
          

Computing Combinations

A widely-used problem in computer science involves determining the number of ways that k items can be chosen from a pool of n distinct objects, ignoring the ordering of elements selected. In writing and speech, this quantity is denoted several ways:

This "binomial coefficient" is discussed in CS 242 and on many Web sites, such as Combinations and Permutations by Maths is Fun.

Computationally, discussions of these combinations often specify a computational formula involving factorials (where k factorial or k! = k*(k-1)*(k-2)*...*3*2*`)

C(n,k) = n! / [k! (n-k)!]

For example, the number of 5-card hands possible from a deck of 52 cards would be C(52, 5).

Although this formula works well on paper, a pragmatic problem is that the computation of factorials produces large numbers very quickly:

  1. The program factorial.c computes successive factorials (1!, 2!, 3, ...) until integer overflow occurs—the integer is too large to be stored in an integer variable.

    1. Compile and run this program and observe the output.
    2. How large can an integer n be, so that n! can be computed as an int? (Note that if b! has 0 as its right-most digit, then m! must also have at least one 0 as its right-most digit for any m ≥ b why? Similar patterns hold for n! ending in more than one zero.)
    3. Modify the program so the fact variable and associated elements use a long integer rather than an int How much does this increase in storage allow factorials to be computed.

Since factorials are often too large for many simple computations, alternative approaches are needed for computation. One approach uses the recurrence relation:

As well as being explained in CS 242, many online sources provide a proof of this relation, including ON A RECURSIVE FORMULA FOR BINOMIAL COEFFICIENTS by G. BERKOLAIKO, Texas A & M University.

With this recurrence relation, alternative ways to compute C(n, k) could follow either of two approaches:

These alternatives form the basis for the following programming task.

  1. Write a program that reads values for n and k and computes C(n, k) in the two ways described above.

    1. Run your code with sufficient test cases, so you can give a strong argument that the functions work properly. (And include your argument in your solution of this problem.)
    2. Once your functions work properly, add code to determine the timing of each of these approaches. Write a brief commentary to indicate the extent to which the table in the second approach increases efficiency.
    3. From your work in Problem 3, you know values of n for which the computation of n! fails, so the expression n! / [k! (n-k)!] fails. Determine what, if any, larger values of C(n, k) can be computed with your current program.

Hashing

A hash function returns integers between 0 and 15 based on the first letter of a data item according to the following table.

A B C D E F G H I J K L M
15 11 6 11 13 15 4 11 12 9 7 3 4
 
N O P Q R S T U V W X Y Z
11 5 13 6 12 15 7 3 9 10 13 10 4

For example, according to this hash function, the string TM would hash to the value 7 (based on the initial letter T; the hash function does not look at the second letter M).

  1. Consider the following sequence of 13 data items:

    UQ  GR  GD  WZ  QS  NW  DT  AX  SL  CY  EM  MR  NZ

    Suppose the above sequence is to construct each of the following data structures 16 locations (labeled 0 through 15), based on the hash function given above.

    1. Closed, unbucketed hash table, using linear probing
    2. Closed, unbucketed hash table, using quadratic probing (use both -i2 and +i2)
    3. Open, bucketed hash table (with chaining)

    Show the resulting structure by filling in the following tables:
    (If collision resolution does not find a location for an element, explain the trouble, omit that that element, and go on to insert any remaining elements.)

    Closed, unbucketed hash table
    using linear probing
    Closed, unbucketed hash table
    using quadratic probing
    Open, bucketed hash table (with chaining)
    0     
    1     
    2     
    3     
    4     
    5     
    6     
    7     
    8     
    9     
    10     
    11     
    12     
    13     
    14     
    15     
    0     
    1     
    2     
    3     
    4     
    5     
    6     
    7     
    8     
    9     
    10     
    11     
    12     
    13     
    14     
    15     
    0  
    1  
    2  
    3  
    4  
    5  
    6  
    7  
    8  
    9  
    10  
    11  
    12  
    13  
    14  
    15  
created December, 2021
revised December-January 2021
revised and expanded July 29, 2022
minor editing October 20, 2022
adjustments of problem 4 for C and C++ October 24, 2022
revised December 31, 2022–January 3, 2023
revised Summer, 2023
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.
ccbyncsa.png

Copyright © 2011-2022 by Henry M. Walker.
Selected materials copyright by Marge Coahran, Samuel A. Rebelsky, John David Stone, and Henry Walker and used by permission.
This page and other materials developed for this course are under development.
This and all laboratory exercises for this course are licensed under a Creative Commons Attribution-NonCommercial-Share Alike 4.0 International License.