CS 136 Assignment 5

Due Wednesday, February 26 at 11:59 AM sharp (noon).

Please read the preamble in Assignment 1.

In this assignment, Only the C language features introduced up to the end of Section 07 are allowed.

You are not allowed to use recursion or arrays in this assignment.

NOTE: In this assignment, you must assert your preconditions (for C problems).

Unless otherwise stated, you do not have to worry about unexpected EOFs.

Assignment 5 Problem 0. [2*3 Marks for correctness]

Problem 0 is a "warm-up" question. You are allowed to collaborate with your fellow classmates and discuss the solution on piazza.
  1. Write a C module randnum.c that provides a randnum function:
    int randnum(void);
    That returns a random integer between 5 and 20 (inclusive). You must use the built-in rand() function and must use an initial seed of 1234 (seed only once).
    See Problem 3 for more information

    The first two calls to randnum() must return 19 and 8.

  2. Write a C program repeat.c that reads in (e.g., from the keyboard) an integer n followed by a character c and then prints the character c a total of n times, followed by a newline. You must use scanf to read in the integer, and you must continue to use getchar until a non-space character is encountered. The space ' ' and newline '\n' are the only whitespace characters you must consider. You may assume that n is a positive integer.


  3. Write a C test program test-addsqr.c that provides the same functionality as the program on slide 17 of section 07.

    The test cases on slide 18 will be used to test your program.

    Note: Your program must not include any other modules (i.e., "addsqr.h").

Assignment 5 Problem 1. [2*5 Marks for correctness]

  1. Write a C module exponent.c that provides the following function, implemented with iteration, not recursion:

    // exponent(a,b) returns a raised to the power of b (a^b)
    // PRE: a>0 and b>0
    // POST: returns integer > 0
    int exponent (int a, int b) {
      if (b==1) {
        return a;
      return a * exponent(a, b-1);

  2. Write a C module palindrome.c that provides the function is_palindrome from A2P2, implemented with iteration, not recursion.

Assignment 5 Problem 2. [10 Marks correctness]

Background: You wish to help your sibling (in grade 3) with their multiplication skills.

Write a C module mtable.c that provides a function:

// PRE: 1 <= w <= 14 and 1 <= h <= 70
void mtable(int w, int h);

that prints a multiplication table with w columns and h rows. Each row must be exactly 5*(w+1) characters wide, followed by a newline. See the provided examples for more details.

Tip: To print a right-aligned integer that always takes up 3 spaces, use "%3d".

mtable(2,3) produces output identical to the table in this file: mtable1.txt.
mtable(10,10) produces output identical to the table in this file: mtable2.txt.

Assignment 5 Problem 3. [25 Marks correctness]

A PseudoRandom Number Generator (PRNG) generates a sequences of integers that appears random, but is mathematically deterministic. The output of a PRNG depends on an initial "seed" value, and for a given seed it always produces the same sequence.

The rand() function in stdlib.h returns a pseudo-random integer between 0 and the constant RAND_MAX (inclusive). The function srand(int seed) initializes the PRNG.

In practice, the current time is often used seed a PRNG. For this assignment, to have consistent Marmoset testing, you are required to set the seed to the value of 1234 (i.e., srand(1234);).

When we use a PRNG, we often desire a sequence of integers within a particular interval [a,b]. Since rand() generates numbers in the interval [0,RAND_MAX], it is common practice to use the modulo (%) operator to map the PRNG sequence to a different range. For example, (rand() % 10) produces a random integer in the interval [0,9].

You still wish to help your sibling with their multiplication skills.

Write a C program mgame.c that is an interactive teaching aid to help grade 3 students with their multiplication skills. The program must operate as follows:

step 1: (multiplication question)
Generate a random number y and then a random number z in the range [1,10] (inclusive).
If you seeded correctly and compute y and z correctly, the first time you run your program, y should be 5, and z should be 10.
You must then prompt the user with "y X z = ", for example:
"5 X 10 = " (space after =, no newline)
and then read in an integer response (with scanf). If the response is correct, proceed to step 4, otherwise proceed to step 2.

step 2: (first guess is incorrect)
Generate a random number r in the range [0,2] and display the corresponding message:
0: "Incorrect.\n"
1: "That is not right.\n"
2: "That is wrong.\n"
and then re-prompt the user for a second chance and read in another response:
"Try again: y X z = " (space after =, no newline)
If the response is correct, proceed to step 4.

step 3: (second guess is incorrect)
Increment the number of incorrect answers, and display the following message:
"Sorry. The correct answer is y X z = %d\n"
proceed to step 5.

step 4: (response is correct)
Increment the number of correct answers, and then generate a random number r in the range [0,2] and display the corresponding message:
0: "Give me five!\n"
1: "Keep up the good work!\n"
2: "Way to go!\n"

step 5: (continue ?)
Prompt the user with:
"Would you like to continue (y/n)? " (space after ?, no newline)
and then read in a response (with getchar) until a 'y' or 'n' is read. If 'y', proceed to step 1.

step 6: (game over)
Display the following statistics:
"----- Session Summary -----\n"
"Correct answers: %d\n"
"Incorrect answers: %d\n"
"Percentage correct: %.2f%%\n"
Note that the percentage of correctly answered questions must be calculated using a float, and must be displayed to two decimal places using the placeholder above.

If implemented correctly, you should be able to duplicate the following interactions (bold denotes input, otherwise output):

5 X 10 = 50
Give me five!
Would you like to continue (y/n)? y
8 X 1 = 81
Try again: 8 X 1 = 8
Keep up the good work!
Would you like to continue (y/n)? y
9 X 3 = 93
That is not right.
Try again: 9 X 3 = 39
Sorry. The correct answer is 9 X 3 = 27
Would you like to continue (y/n)? n
----- Session Summary -----
Correct answers: 2
Incorrect answers: 1
Percentage correct: 66.67%

Assignment 5 Problem 4. [14 Marks correctness]

Write a C program call.c that translates alphabetic phone numbers into numeric form.
Your program must continue to call getchar() until an EOF is encountered.

For each character of input, your program must print the character, UNLESS it is one of the following upper-case letters, in which case the corresponding number must be printed. Do not print the final EOF.

2 3 4 5 6 7 8 9

input: CALLATT, 1-800-COL-LECT
output: 2255288, 1-800-265-5328

Assignment 5 Problem 5. [20 Marks correctness]

In this question, you will implement an interactive Rock-Paper-Scissors-Lizard-Spock game (see the webpage for details), which allows a human player to compete against a computer "bot".

To avoid ambiguity, we will use the letter K to represent SpocK.

You must write the module rpslk.c that implements the interface provided in rpslk.h.

We have provided you with play-rpslk.c to start the game. It requires a rpslk-bot module which is also provided for you. The rpslk-bot ("game") module requires your rpslk module.

Download the rpslk-bot.h interface file and the following implementation file: rpslk-bot.o (Virtual Box) or rpslk-bot.o (Mac Lab) and place all of the files in the same folder as your module.

At the start of the game, the user will be prompted to set the bot's challenge rating. This will be done by calling your get_challenge_rating() function. Your function should print the following message and read in an integer with scanf:

"Choose a challenge rating (1 - 1000000): " (space after :, no newline)

You do not have to check for invalid inputs. The bot will handle this for you.

Pro Tip: If a user enters a rating of 1, the bot will always lose. If a user enters a rating of 1000000, the bot will never lose :). The challenge rating is also used by the bot as a seed.

At the start of each round, the game module will call your get_player_throw() function to prompt the user for his/her throw. Your function must print the following message:

"What do you throw (r/p/s/l/k)? " (space after ?, no newline)

Your function should then use getchar until a valid character (r/p/s/l/k) is read.

After the player has entered his/her choice, the game module will call your rpslk_winner function that will decide who wins the round, update the game statistics, and display the victory message.

If the player threw "rock" and the bot threw "paper", The corresponding victory message is:

"Paper covers rock. Bot wins!\n"

The provided messages.txt includes the various victory messages (you can copy these messages into your code to avoid typos).

After each round, the game module will call your get_play_again_response() function to prompt the user to play again (similarly to get_player_throw):

"Would you like to play again (y/n)? " (space after ?, no newline)

If the player chooses 'n', the game module will call your print_game_summary() function to print a game summary, which includes the number of rounds won by the player, the number of rounds won by the computer, and the overall winner of the game. For example, if the player wins 8 rounds and the bot (computer) wins 10 rounds, your program should print the following summary (see the messages file):

----- Game Summary -----
Player won 8 rounds...
Bot won 10 rounds...
Player and bot tied 0 rounds...
Bot wins!

Have fun!

NOTE: Do not attempt to use the RunC testing framework for the full program.

Assignment 5 Problem 6. [15 Marks correctness]

Cyber Salmon is a computer science student at the University of Waterloo. He landed a co-op job as a timekeeper at a cutting edge software development company after his 1B semester. The semester just ended and he is being tossed into the "real world". His first project is to implement a timekeeper module in C.

Here is what Salmon has written:

Unfortunately, Salmon did not think that testing was very important during his first two academic semesters. He made it through CS 135 and CS 136 by relying on the public tests available on Marmoset to ensure the correctness of his modules/programs. He never bothered to test his own code! But the company that he is working for does not have Marmoset! Oh noes!

So, Salmon is hoping that you can help him ensure the correctness of his C module. He has provided you with an interactive testing module, test-timekeeper (test-timekeeper.c). Fortunately, the company he is working for uses RunC in their C development environment. He asks that you write an input file (.in file) and a corresponding comparison file (.expect file) for his interactive testing module (test-timekeeper).

For this question you must submit test-timekeeper.zip which contains all of the following files:

  1. test-timekeeper.in.1
  2. test-timekeeper.expect.1

Your input file and comparison file should be written in such a way that a correct implementation of the timekeeper module would pass all of your tests and an incorrect implementation of the timekeeper module would fail one or more of your tests.

You cannot modify test-timekeeper.c! On Marmoset we will be using the same interactive testing module.