CSC 161 Grinnell College Fall, 2014
Imperative Problem Solving and Data Structures

Supplemental Problems

Supplemental Problems extend the range of problems considered in the course and help sharpen problem-solving skills. To support this objective, all Supplemental Problems are to be done individually.

Problems numbered 6 or higher may be turned in for extra credit.

Quick links: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

Submission Details

Use the link, Detailed Coursework Instructions, to find specific insturctions regarding code, submission, and testing of supplemental problems.

Some Grading Notes:

  1. Currency Conversion

    In the United Kingdom and some British Crown dependencies, modern currency is based on the pound sterling, often identified simply as the pound or by the abbreviation GBP. Further, the pound may be subdivided into 100 pence. (The singular form of pence is penny.) When this problem was written,

    1.00 GBP = $1.69759 (United States dollars)

    Write a program that begins with a specification of a quantity using British currency, such as the following:

       int pounds = 17;
       double pence = 32.85

    The program then should compute the corresponding amount in United States dollars and cents. This amount should then be specified in one-, five-, ten-, and twenty-dollar bills, and pennies. Your computation should use the fewest number of bills. Also, fractions of a cent should be ignored — that is, you should not round up fractions of a penny.

    For example, the program might print the following:

       17 pounds 32.85 pence translates to $29.41
       This may be paid as
       1 twenty-dollar bill
       1 five-dollar bill
       4 one-dollar bills
       41 cents in change


    • 17 pounds 32.85 pence actually translates to $29.4166883. Since fractions of a cent are ignored (no rounding as currency exchanges never give more), the customer would receive $29.41.
    • Do NOT try to compute how many of each coin type should be given to the customer (pennies, nickels, dimes, and quarters).
    • In translating this amount to dollars and cents, note that only bills actually used are printed. (No ten-dollar bill is listed in the above output.)
    • When one bill of a given type is mentioned, the output uses the singular form "bill" (e.g., "1 twenty-dollar bill"); but when multiple bills of a given type are needed, then the plural form is given (e.g., "4 one-dollar bills").
    • If no pennies are needed, the "cents" line should not be printed. If only one penny is needed, then the singular form, "1 cent in change", should be printed.
    • The program should not use loops to compute bills or change. Rather, use integer division (/) and remainder (%) in computations. For example, if usd is the amount of dollars involved (as an int), then usd / 20 will compute the number of twenty-dollar bills required, and usd % 20 is the amount of money needed in smaller bills.

    Grading Forms

  1. Making Early Loan Payments

    When investigating a loan, a customer typically states the amount of money (loanAmount) and specifies the loan's length (number of months N). A bank or other lender proposes an annual interest rate (annRate) for the loan. With this information, the monthly payment for the loan is given by the formulae:

         monthlyRate = annRate / 1200.0
    payment = loanAmount * monthlyRate / (1.0 - (1 + monthlyRate)(-N))

    For example, a loan to purchase a house might involve $26,000 for 25 years (300 months) at an annual rate of 8.75%, yielding a monthly payment of $213.76.

    The expectation is that the customer will pay this amount (in dollars and cents) each month, although a slight adjustment may be needed the last month to make up for any rounding in the computation.

    The expected payment notwithstanding, the terms of many loans allow the customer to pay an additional amount for one or more months in order to shorten the length of the loan and possibly save some interest charges. This problem investigates the consequences of paying twice the required amount for the first few months.

    More specifically, the program should have these charactertistics:

    • The beginning of the program should specify the values of the loan amount, length (in months), and annual interest rate.
    • The program should compute the normal loan payment using at least two functions:
      • double compute_neg_power (double value, int n)
        that returns 1 / (value)n.
        (In the computation, the function should use successive multiplications rather than the more general, but less efficient, C library pow function.)
      • double compute_payment (double annRate, int months, double amt)
        that returns the monthly payment for the given parameters.
      • compute_payment should call compute_neg_power.
    • The main procedure should determine the actual length of the loan and the total amount paid assuming each of three payment options:
      • The customer pays exactly the expected amount each month (except that the last month may be smaller, if appropriate)..
      • The customer pays twice the expected amount the first month and then the expected amount each subsequent month (except that the last month may be smaller, if appropriate).
      • The customer pays twice the expected amount each month in the first year and then the expected amount each subsequent month (except that the last month may be smaller, if appropriate).
    • Some programming constraints:
      • No global variables may be used in this program.
      • When using functions, all relevant values must be passed as parameters.
      • Values may be returned from functions either through a return statement or via parameters (with addresses).
      • No printf statements are allowed in any final function except main. (printf may be used in functions for testing, but these should be commented out for any final runs.) In particular, neither function compute_neg_power nor function compute_payment should print anything.
    • Computations of actual payments and the cost of the loan should be given to the nearest cent. Note that if double value is a real number, then
      • ((int)(value * 100.0)) / 100.0 truncates value to two decimal places, and
      • ((int)(value * 100.0 + 0.5)) / 100.0 rounds value to two decimal places.
    • In addition to computing the cost of the loan for the three payment plans, the program should indicate the additional costs (if any) of each of the first two payment options over the third.

    Grading Forms

  1. Family Size Simulation and Histogram

    Module 001 includes programs couple-1.c and couple-2.c that address the following question:

    Family size simulation: A couple decides to have children. They decide to continue to have children until they have at least one boy and one girl. Then they decide to stop having children. How many children might the couple expect to have?

    To address this question, the programs simulate the genders of successive children and determine the number of children for each couple.

    • couple-1.c prints the results for one couple.
    • couple-2.c prints the average number of children for 1000 couples.

    This problem asks you to tabulate the results of a simulation in both a table and a histogram. File couple-histogram.txt shows the results for one run of a simulation involving 60 children. This output has several features:

    • Records are kept based on these program variables:
        /* the number of couples in the simulation */
        const int numberOfCouples = 60;
        /* number of children is recorded for sizes 1 .. maxRecordedSize */
        const int maxRecordedSize = 30;
        int famSize [maxRecordedSize + 1];
        /* the highest point of the histogram will have heightOfHistogram *'s */
        const int heightOfHistogram = 20;

      By defining these programs at the start of the program, a user should be able to easily set the number of couples in the simulation, the range of family sizes being recorded, and the height of the resulting histogram.

    • For your convenience, the above variables are combined in the stub of a program at family-size-stub.c. This program compiles and runs on MathLAN using the standard command
      gcc -o family-size-stub family-size-stub.c && family-size-stub
    • The number of children recorded will range from 1 to maxRecordedSize. If a couple has a larger number of children, then the number of children is recorded as the maximum (maxRecordedSize).
    • The program counts the number of children for each couple and prints both the average and the maximum.
    • The program prints a table of the number couples with total children 0, 1, 2, ..., maxRecordedSize.
    • The program prints a histogram showing visually how many couples have how many children. In a simulation of hundreds or thousands of couples, giving a histogram showing each couple is impractical — the height of the histogram could be very large. Rather, the vertical scale on the histogram should be scaled. The top row of the histogram should show the maximum number of couples with a specific count (likely for couples with 2 children). Each successive row should scale the family size. Although the scale of the histogram should be approximately linear, some rounding or adjustment may be required in the vertical scale because the number of couples of a given family size may not be divided evenly by the heightOfHistogram.
    • Testing should include a range of values for the variables numberOfCouples, maxRecordedSize, and heightOfHistogram.

    Grading Forms

  1. A Daily Calendar Program

    This problem outlines a simplified version of a program to maintain a person's daily calendar. Individual appointments will be stored in a struct:

       const maxLen = 80;
       struct appt {
          int year;
          int month; /* 1=January, 2=February, ..., 12=December */
          int day;
          char text [maxLen];

    As this struct suggests, in this problem ignores the time of day for an appointment.

    The program should handle the following processing tasks:

    • The user may enter an appointment by specifying information in a standard date/text format:
      month (chars) day (int), (comma) year (int): (colon) text (chars). For example,
           September 23, 2014:  Module 001 Project Due
           October 20, 2014:  Fall Break begins
           October 24, 2014:  Fall Break ends
           November 27, 2014:  Thanksgiving Day
           November 28, 2014:  Thanksgiving Recess 
    • The user may sort appointments either chronologically by date or alphabetically by appointment text.
    • The user may print the list of appointments.

    When running this program, a user should be given a menu of options, such as the following:

    Calendar program options:
       e:  enter a new appointment (date, text)
       d:  sort appointments by date
       a:  sort appointments alphabetically by appointment text
       p:  print current appointments
       q:  quit

    Within the program, the collection of appointments will be stored in an array, because sorting an array with an insertion sort is reasonably efficient. Of course, use of an array is complicated by the need to allocate space for the array. One way to accomplish this would be to declare an array of a specific size:

         int maxSize = 100; /* some specified maximum */
         struct appt apptArray [maxSize];

    With such an array, a separate variable int numAppts would keep track of how many appointments are actually recorded in apptArray. Thus, numAppts would be initialized to 0 and then incremented by 1 each time a new apppointment was entered.

    While this approach will work for awhile, it is still limited by maxSize; the program must maintain the condition that numAppts<=maxSize.

    To remove this restriction, the array could be stored in dynamic memory. The revised declarations would be:

         int maxSize = 100; /* current size of the apptArray */
         struct appt * apptArray = malloc (maxSize * sizeof (struct appt)):
         int numAppts = 0;

    With this initialization, addition of new appointments can continue until the array is full. When no more space is available in apptArray,

    • a new and larger array would be allocated,
    • the appointments in the old array would be copied into the new array,
    • the old array would be deallocated,
    • the apptArray would point to the new array
    • additional appointments can now be added

    Write a program to implement this calendar program.

    As extra credit, add one menu option to read appointments from a file rather than from the keyboard, and add a second menu option to write the current collection of appointments to a file.

    Programming notes:

    • Although the program may add a name anywhere in the array, it is suggested that a new appointment be inserted after all existing appointments.
    • During insertion, the user must type the full month (e.g., January, February), not a number, a single letter, or other abbreviation.
    • If the user enters an invalid month name, the program should report the error, disregard the appointment entered, and continue with the menu again.
    • The program is not responsible for checking that the day numbers are valid for the month (e.g., February 30 need not be flagged as an error).
    • When printing, the program should print the full month, day, year, and text. Printing just the number of the month is not adequate.
    • Converting from a month's name to an internal number may be accomplished in any way a programmer wishes (as long as January is stored as 1, etc.). For example, two possibilities are:
      • A sequence of if ... else statements might be used.
      • An array of month names might be used.
    • Printing may be accomplished in any way a programmer wishes, as long as the full month name, etc. are given. For example, three possibilities are:
      • A sequence of if ... else statements might be used.
      • A switch statement might be used.
      • An array of month names might be referenced.
    • Sorting must use an insertion sort with a parameter comesFirst that indicates when one struct appt comes before another. The program also should define two comparison procedures:
      /* returns 1 if the date for appointment app1 comes before the 
         date for app2, and returns 0 otherwise */
      int comesFirstByDate (struct appt app1, struct appt app2)
      /* returns 1 if the text for appointment app1 comes before the 
         date for app2, and returns 0 otherwise */
      int comesFirstByText (struct appt app1, struct appt app2)

      With this framework, implementing the "sort by date" option involves a simple call to the insertion sort procedure with comesFirstByDate as one parameter. Implementing the "sort by text" option involves a simple call to the insertion sort procedure with comesFirstByText as one parameter.

    Grading Forms

  1. Commodities and Prices

    A store sells a wide range of items. For this problem, we will store the price of each item and its name on a singly-linked list using node declarations:

         const maxNameLen = 50;
         struct item {
             char name [maxNameLen];
             double price;
             struct item * next;

    From time to time, the store adjusts all prices in its inventory by applying a function to each price. In this problem, three price-adjustment functions (unimaginatively called "a", "b", and "c") will be defined. When running the program, a user is given the following menu:

       Store-inventory options:
          e:  add an item (cost, name) to the inventory
          p:  print all items in the inventory
          a:  apply function "a" to all prices in the inventory
          b:  apply function "b" to all prices in the inventory
          c:  apply function "c" to all prices in the inventory
          s:  sort the inventory by placing the items in ascending order of price
          q:  quit

    Programming notes:

    • Addition of a new inventory item should be at the front of the linked list. (For example, one might use the approach of Scheme-like lists.)
    • Printing should display item names and prices from the front of the list to the end. Printing should not change the list itself.
    • Functions a, b, and c should all act on one double parameter and return a double. No assumptions should be made regarding the nature of these functions. Here are some possible examples:
      /* reduce a price by 10% */
      double a (double orig_price)
         return 0.90 * orig_price;
      /* increase a price using a linear formula */
      double b (double orig_price)
         return 2.50 + 1.15 * orig_price;
      /* change prices up and down in a curious way, using the cosine function
      from math.h (compile with -lm) */
      double c (double orig_price)
         return 12.00 + 9 * cos(orig_price);
    • Application of a function to all inventory prices should use a variant of Scheme's map function. In Scheme, the map procedure takes a procedure and one or more list(s) as parameters and returns the list obtained by applying the procedure parameter to the list(s).

      In this problem you should write a basic version of map in C with the following signature:

      void (double f (double), struct item * lst)

      where f is a function that can be applied to an double to obtain another double.


      • The parameter lst points to the first node of a singly-linked list of inventory items.
      • The list designated by lst is changed by map by applying the function f to each price in the inventory list.
      • This map function may be solved either iteratively or recursively.

      With this map function, menu options a, b, and c can be implemented simply by calling map with the relevant function parameter.

    • Sorting should proceed by starting with a null list and successively removing nodes from the original list and inserting them in order. In outline, such an approach is quite similar to an insertion sort for arrays.

      • A new list starts with no items.
      • Successive items are inserted, so that the list is sorted after each add.

      Throughout this process, no nodes should be created or freed. Rather only pointers should be changed to reflect a new ordering of the existing nodes.

      The relevant procedure would have the following signature:

         /* param:  lst designates a list of inventory items, sorted by price
            post-condition:  lst designates a list, containing the same elements
            as the original, but sorted by price
          void sort (struct item ** first)
    • Since this problem involves a linked list of inventory items, arrays of inventory items or prices are not appropriate in a program solution.

Any of the following problems may be done for extra credit. As noted in the course syllabus, however, a student's overall problems' average may not exceed 120%.

  1. Defective, Perfect, and Superperfect Numbers

    Definitions: For a positive integer n:

    • A number k is a factor of n if k divides n with no remainder. For example, integers 1, 2, 3, 4, 6, and 12 are factors of 12, but 5, 7, 8, 9, 10, and 11 are not factors of 12.
    • The numbers 1 and n are called trivial factors of n; 1 divides every positive integer, and every positive integer divides itself.
    • A number k is a non-trivial factor of n if k is a factor of n other than 1 or n.
    • A number k is a proper factor of n if k is a factor of n other than n.

    • The number 1 is called a unit.
    • A number n is called prime if it not a unit and if its only factors are trivial.
    • A number n is called defective if it is neither a unit nor a prime and if the sum of its proper divisors is smaller than n. For example, 8 is defective, because its proper divisors are 1, 2, and 4, and the sum 1+2+4 = 7 which is less than 8.
    • A number n is called perfect if the sum of its proper divisors is exactly n. For example, 6 is perfect, because its proper divisors are 1, 2, and 3, and the sum 1+2+3 is the number 6.
    • A number n is called super perfect if the sum of its proper divisors is greater than n. For example, 12 is super perfect, because the sum of its proper divisors is 1+2+3+4+6 = 16 which is greater than 12.

    Write a program that reads a number max and prints, for each integer between 1 and max,

    • followed by its non-trivial factors,
    • the sum of its proper factors, and
    • its classification.

    The results should be printed in a table with the following format (shown when max is 12).

        The classification of numbers
        n : non-trivial factors : sum of proper factors : classification
        1 : : 0 : unit
        2 : : 1 : prime
        3 : : 1 : prime
        4 : 2 : 3 : defective
        5 : : 1 : prime
        6 : 2, 3 : 6 : perfect
        7 : : 1 : prime
        8 : 2, 4 : 7 : defective
        9 : 3 : 4 : defective
       10 : 2, 5 : 8 : defective
       11 : : 1 : prime
       12 : 2, 3, 4, 6 : 16 : super perfect
    Programming Notes:
    • Use C's remainder operator (%) to check remainders; integer division (/) should not be used without the instructor's explicit approval.
    • Arrays should not be used in this problem.
    • The program should be reasonably efficient. For example, a single set of nested loops (one outer loop and one inner loop) or a loop and a single recursive fucntion should be adequate for this problem.

    Bonus Option: Bonus points are possible with this problem if the table is formatted with the listing of non-trivial factors at the end:

        The classification of numbers
                             sum of proper
        n : classification :  factors      :  non-trivial factors
        1 : unit           :      0        :
        2 : prime          :      1        :
        3 : prime          :      1        :
        4 : defective      :      3        : 2 
        5 : prime          :      1        :
        6 : perfect        :      6        : 1, 2, 3 
        7 : prime          :      1        :
        8 : defective      :      7        : 2, 4
        9 : defective      :      4        : 3
       10 : defective      :      8        : 2, 5 
       11 : prime          :      1        :
       12 : super perfect  :     16        : 2, 3, 4, 6 
    Programming Hint:
    • In addition to the earlier notes for this problem, one might consider a recursive fucntion for printing part of a row in the table.
  1. Checking Proximity to Electrical Service

    Archetectural plans for a building often show the location of electrical outlets. In this problem, a program reviews the minimum distances from room locations to elctrical outlets throughout the building.

    Since walls often are constructed with 2" by 4" studs, consider placing the floor plan of a building on a 4" grid. A sample floor plan is shown below for a 25' by 15' structure (grid size 76 by 46) (where the numbers show distance in feet):

                                      1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2
        0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
     0  wwwwwwwwwwwwwwwwwvwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwvwwwwwwwwwwwwwwwwwwwww
        w                                w                                         w
        w                                w                                         w
     1  w                                w                                         w
        w                                w                                         w
        .                                w                                         w
     2  .                                =                                         <
        .                                w                                         w
        .                                w                                         w
     3  .                                w                                         w
        .                                w                                         w
        .                                .                                         w
     4  .                                .                                         w
        .                                .                                         w
        .                                .                                         w
     5  .                                .                                         w
        .                                .                                         <
        .                                .                                         w
     6  w                                .                                         w
        w                                .                                         w
        w                                .                                         w
     7  w                                .                                         w
        w                          f     w                                         w
        w                                w                                         w
     8  wwwwwwwwwwwwww|wwwwwwwwwwwwwwwwwwwwwwww.............www|wwwwwwwwwwwwwwwwwwww
        w                                                                          w
        w                                                                          w
     9  w                          f                                               <
        w                                                                          w
        w                                                                          w
    10  w                                                                          .
        w                                                                          .
        w                                                                          .
    11  w                                                                          .
        w                                                                          .
        >                                                                          .
    12  w                                                                          .
        w                                                                          .
        w                                                                          .
    13  w                                                                          .
        w                                                                          .
        w                                                                          w
    14  w                                                                          w
        w                                                               f          w
        w                                                                          w
    15  wwwwwwwwwww^wwwwwwwwwwwwwwwwwwwwwwwwww^wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    This floor plan uses a simple notation for these main elements:

    • w represents part of a wall
    • . represnets part of a door
    • a space represents open space within a room
    • <, > and = represent electrical outlets in the left, right side, and both sides of a wall shown vertically on the diagram,
    • ^, v, and | represent electrical outlets on the top, bottom, and both sizes of walls shown horizontally on the diagram.
    • f represents the location of a floor plug inside a room.

    In the example, the left wall has two electrical outlets accessible to the room on the right, the right wall has two outlets accessible to the left, and the middle wall has one location where outlets are available on both the left and right. Similarly the wall at the top has two outlets available to the rooms at the top, the wall at the bottom as two outlets available to the room above, and the middle wall has two locations with outlets available to the rooms on both sides.

    Although this representation is reasonably primitive, it translates simply to a 2-dimensional character array. Pragmatically, this should be set up by first asking the user for the size of the grid and then entering the character codes row by row.

    Write a program that reads the grid and then reads positions in the grid. For each position read, the program should compute the approximate shortest distance (in inches) to an electrical outlet.

    Programming notes:

    • Each horizontal character in the grid represents 4".
    • Each vertical character in the grid represents 4".
    • Diagonal distances can be computed using the Pythagorean Theorem.
    • Of course, wires cannot go through walls — only through open space and through doors.
  1. Dealing Bridge Hands

    Write a program that simulates the dealing of a deck of cards to give four bridge hands. Each run of the program should give a different random assignment of the cards. The program should print both the cards held for each hand and the point-count for bidding.

    A simple scoring system gives an ace 4 points, a king 3 points, a queen 2 points, and a jack 1 point, with an extra point given if a hand contains all aces and a point deducted if it contains no aces. Points also are given for distribution, with a point given if a hand contains only 2 cards in a suit (a doubleton), 2 points given if a hand contains a single card in a suit (a singleton), and 3 points given if a hand has no cards in some suit.

  1. A Simplified Eliza Program

    One of the early, well-known programs within the field of artificial intelligence was called Eliza, a program by Joseph Weizenbaum. The idea was to simulate conversation between a patient and psycho-therapist, based on a series of patterns and corresponding responses. Although the original program had an extensive sequence of patterns, this assignment focuses on the following five rules:

    Pattern     Response Template
    ---1 my singleWord ---2 me ---3 tell me about your singleWord
    ---1 i am ---2 i am sorry to hear you are ---2
    ---1 am i ---2 do you believe you are ---2
    ---1 you ---2 me --- 3 why do you think i ---2 you
    ---1 in what way

    In this table, the blank spaces in a pattern, denoted by subscripted dashes, can be filled in with any sequence of words. Similarly, singleWord represents exactly one word in a sentence. For example, these patterns might generate the following "conversation," where the responses are indented and in italics:

    Sample Dialogue:

    well my friend made me come here
        tell me about your friend
    he says i am depressed
        i am sorry to hear you are depressed
    i think i need help
        in what way
    i wonder if you would help me learning to program Scheme
        why do you think i would help you
    when i registered for the course i wondered am i crazy
        do you believe you are crazy

    Each of these statements and responses follows the template/response patterns given. For example, in the first statement:

    well my friend made me come here

    the presence of the word my near the start of the sentence with the word me later on corresponds to the first pattern, with the following matches:

    Pattern Element     Words from this Sentence
    ---1 well
    my my
    singleWord friend
    ---2 made
    me me
    ---3 come here

    After identifying these pattern elements for the first pattern, the Eliza program uses the corresponding response template. In this case, the program prints "Tell me about your friend". The first four of these words come directly from the template. For the final word, singleWord in the template was matched with the word "friend" in the above analysis.

    Historical Note

    Although this approach may seem simple today, Joseph Weizenbaum used this approach as the basis for his widely heralded Eliza in 1966. In 1976, Weizenbaum noted he "was startled to see how quickly and how deeply people conversing with [ Eliza] became emotionally involved" in the conversation. People shared their hopes and secrets, and they became annoyed if other people looked over their shoulders or otherwise interrupted. Even when they knew Eliza was a program, they often talked as if it were a close personal friend.


    Write a C program to solve this Eliza-based pattern-matching problem. For example, if you entered the successive dialog strings from the "Sample Dialog" above, the program would respond as the example indicates. The program should continue to read user input until the user types "quit".

  1. Simulation of Hi Ho! Cherry-O

    This problem explores statistics for the game of Hi Ho! Cherry-O. For our purposes, we will follow the description of the game as described in Wikipedia. Note, however, that the number of cherries on a player's tree is always between 0 and 10.

    • If one spins 1, 2, 3, or 4, that number of cherries is removed from the tree (except that the number of the tree can never be negative).
    • If one spins a bird and the number of cherries on the tree is 9 or fewer, then the number of cherries on the tree goes up by 1. However, if one spins a bird and the number of cherries on the tree is 10, then the number of cherries on the tree is unchanged.
    • If one spins a dog and the number of cherries on the tree is 8 or fewer, then the number of cherries on the tree goes up by 2. However, if one spins a dog and the number of cherries on the tree is 9 or 10, then the number of cherries on the tree becomes 10 (not higher).
    • If one spins a spilled bucket, then all of the cherries return to the tree.

    The game progresses in rounds, during which each player in turn spins a game spinner that has seven outcomes (as described in the Wikipedia article). In our simulations, we will assume that each outcome of the spinner arises randomly with equal probability.

    Within this framework, the specific purpose of this supplemental problem is general statistics on how many rounds the game is likely to continue, based on the number of people playing the game. The required work for this problem involves three C procedures, combined within a main program.

    • Procedure turn simulates one turn of a player; that is, it takes a number init_cherries as parameter, and adjusts the number of cherries on the tree appropriately — using C's rand function to determine the outcome of the spinner.
    • Procedure playGame has players, the number of players, as input parameter, and returns the number of rounds taken until some player wins.
    • Procedure playNGames has two parameters: players, the number of players in a game, and games, the number of games to be simulated. playNGames returns a list with the maximum, minimum, and average number of rounds taken by the players over the full number of games.

    Hints: Although you are free to approach this problem however you want, the following pieces might help.

    • Write a procedure init_games that takes a number of players as parameter and generates a list of that number of 10's (the initial number of cherries on the trees for each of those players).
    • Write a procedure play_round that takes a list of tree-cherry numbers as parameter, plays one round for each player, and returns a list of new totals for the number of cherries for each player.
    • Write a procedure check_win that takes a list of tree-cherry numbers as parameter and checks if any of the players has won.
  1. Shopping Bargains

    A store has two policies to encourage shoppers to buy as many goods as possible:
    1. The purchase of 1 item is full price, but the cost of a second identical item is 10% off, the cost of a third identical item is 20% off, etc., although no item is sold for less that 10% of its original price.
    2. The shop offers a global discount for high spenders:
      • If a shopper's overall bill is between $100 and $200 (inclusive), then the shopper is given a 15% discount (beyond any reduction for purchases of multiple identical items).
      • If a shopper's overall bill is over $200 (i.e., $200.01 or higher), then the shopper is given a 25% discount (beyond any reduction for purchases of multiple identical items).

    Write a program that reads a sequence of original item costs as input and computes the total charge a customer will pay after discounts. Reading should continue on one or more lines until the user enters a cost of 0.00. For this exercise, assume that the costs of identical items will be grouped together, and all consecutive equal costs relate to identical items. To illustrate, consider this sequence of costs:

    1.25 8.73 5.55 5.55 5.55 12.84 5.55 5.55 20.30 20.30 20.30 20.30 0.00

    Here, we assume the first item purchases costs $1.25 and the second costs $8.73. The third, fourth, and fifth items have the same cost, so we assume they are identical items (the cost of these items after multiple-item discount will be 5.55 + 0.9*5.55 + 0.8*5.55). The sixth item costs 12.84. The next two items again cost 5.55, but these must represent a different item than the earlier ones of the same price, since these costs are not contiguous with the previous run of 5.55 prices. Thus, the cost of the seventh and eighth items is 5.55 + 0.9*5.55. The last four items again are considered identical, with costs 20.30 + 0.9*20.30 + 0.8*20.30 * 0.7*20.30. The number 0.00 at the end signifies the end of the input.


    • Processing should make one pass only through the initial list of costs.
    • The program may utilize any helper functions that seem convenient, although the user interface must be as prescribed. (However, even with helper functions, processing should not make multiple passes through the data.)
    • The program should print a cost of 0.00 if the initial sequence of costs is empty.
    • The program should produce an error message, if any of the prices is a non-number or if any of the items are negative numbers.
  1. Elementary Text Analysis

    Write a C program that takes the name of a file as a command-line argument, opens the file, reads through it to determine the number of words in each sentence, displays the total number of words and sentences, and computes the average number of words per sentence. The results should be printed in a table (at standard output), such as shown below:

         This program counts words and sentences in file "comp.text ".
         Sentence:  1    Words: 29
         Sentence:  2    Words: 41
         Sentence:  3    Words: 16
         Sentence:  4    Words: 22
         Sentence:  5    Words: 44
         Sentence:  6    Words: 14
         Sentence:  7    Words: 32
         File "comp.text" contains 198 words words in 7 sentences
         for an average of 28.3 words per sentence.

    Notes for this problem:

    • A word is defined as any contiguous sequence of letters. Apostrophes at the beginning or the end of a word should be ignored. Apostrophes with letters immediately before and after are considered part of a word. For example, "O'Henry", "I've", "you're", "friend's" and "friends'" should each be considered as one word.

    • A sentence is defined as any sequence of words that ends with a period, exclamation point, or question mark, except a period after a single capital letter (e.g., an initial) or embedded within digits (e.g., a real number) should not be counted as being the end of a sentence.

    • Digits and punctuation (other than apostrophes, periods, explanation points, and question marks) should be considered the same as white space. Thus,

         After they walked, talked, and ate, the first person said, "I'd like 
         to swim: crawl, side stroke, and butterfly."

      Should be considered the same as

         After they walked  talked  and ate  the first person said   I'd like 
         to swim  crawl  side stroke  and butterfly
    • White space (e.g., spaces, tabs, line feeds, and return characters) are considered as equivalent. Multiple white space characters are considered the same as one space character. Thus, the above passage would equivalent to the following:

      After they walked talked and ate the first person said I'd like to swim crawl side stroke and butterfly
  1. County Data

    The file /home/walker/207/data-sets/iowa-population-by-county.txt contains population and race information for Iowa counties from the 2010 census. County information is contained on two successive lines, followed by a blank line (for readability).

    1. The first county line contains the county name
    2. The second county line specifies the population of various racial groups within the county.
      • Column 1 gives the total population
      • Column 2 gives the number of whites only (no mixed race)
      • Column 3 gives the number Black or African Americans only
      • Column 4 gives the number of American Indians and Alaska Natives only
      • Column 5 gives the number of Asians only
      • Column 6 gives the number of Native Hawaiians and Other Pacific Islanders only
      • Column 7 gives the number of people identifying two or more races

    Write a program that reads a filename from the terminal and then determines the ranking of Poweshiek County regarding the total number of Black/African Americans. The result should be a ranking number (where 1 means that the county has the largest number of Black/African Americans and 99 means that the count has the smallest number of Iowa's 99 counties).

    Programming Notes:

    • In consideration of space efficiency, arrays may not be used in this problem. Arrays place constraints on the number of counties that might be present in a state.
    • In consideration of processing efficiency, the program should read through the file no more than twice. Multiple passes through the data would require many disk accesses, which involves substantial overhead.
  1. Filtering and Reporting Data

    Gemstones are attractive forms of rock crystal, commonly used for decoration and in jewelry. Gemstones also have interesting mineral properties. Gemstones may be classified in a variety of ways, including chemical composition, crystal structure, color, specific gravity, refractive index, and hardness:

    1. Chemical Composition: While some gemstones are primarily composed of atoms of one element (e.g., diamonds are mostly carbon, with coloring coming from traces of other elements), other gemstones are made up of atoms of several atoms (e.g., mica molecules include oxygen, hydrogen, silicon, aluminum, iron, and/or many others). On-line sources of information include general references (e.g., Common Mineral Groups) and references to specific minerals (e.g., micas).

    2. Color may be classified informally (e.g., red, yellow, etc.) or more formally by viewing thin slices of mineral crystals through the microscope, using polarized light (see, for example, Minerals under the Microscope).

    3. Specific Gravity is a measure of the density of a mineral. More precisely, specific gravity is the ratio of the weight of the mineral in air to its weight in an equal volume of water. More details are available from various on-line sources (see, for example, the Mineral and Gemstone Kingdom's glossary for specific gravity.

    4. Refractive Index provides a measure of how much light bends within a crystal. The higher the refractive index, the more bending and the more brilliant a crystal is likely to appear. For more information, see various on-line sources, such as Refractive Index.

    5. Crystal Structure: Crystals typically have one of several standard shapes or structures, including cubic, tetragonal, orthorhombic, hexagonal, monoclinic, and triclinic. While the details of such structures are beyond the scope of this problem, the World Wide Web contains many useful references, including crystal forms (at the macro-level) and the (atomic-level) representation of structures prepared as part of lecture series by S. J. Heyes.

    6. Hardness often is measured on the (nonlinear) Mohs Scale, which associates a hardness number to each mineral, from 1 (softest) to 10 (hardest):

      1. Talc
      2. Gypsum
      3. Calcite
      4. Fluorite
      5. Apatite
      6. Orthoclase
      7. Quartz
      8. Topaz
      9. Corundum
      10. Diamond

      As a comparison, a fingernail has hardness 2.5, glass has hardness 5.5, and a steel file has hardness 6.5. Minerals of the same hardness should not scratch each other, but a mineral of one hardness will scratch minerals with a lower hardness number.

    File /home/walker/151s/labs/gems.txt contains information on several gemstones, including color, hardness, specific gravity, and refractive index. Within the file, each line contains information about a specific gemstone.

    Here are a couple of sample lines, and a character 'ruler' to show how wide the fields are:

                    Zircon        RED           7.5         4.50         1.95
                     Topaz     YELLOW             8         3.53         1.62

    To clarify, the names of the gemstones come first in a line and are right-justified in a column. The colors come next, followed by hardness (on a scale 1 to 10), then specific gravity, and finally refractive index (generally between 1.3 and 2.5).

    Write a program print-by-color that will let you select the gemstones of a certain color and print the information about those gemstones, where the resulting table is in alphabetical order by gemstone name and where the columns are labeled.

    For example, if this procedure is invoked with the statement

    (print-by-color "GREY")
    the procedure should return a table, such as the following:
                                                          Specific   Refractive
                  Gemstone       Color       Hardness      Gravity      Index
                 Alabaster       GREY             2         2.32         1.53
                  Bakelite       GREY           2.5         1.28         1.65
                   Calcite       GREY             3          2.7         2.71
                    Casein       GREY           2.5         1.33         1.55
                  Celluoid       GREY             2         1.35         1.50
                Chalcedony       GREY             7         2.62         1.53
                  Corundum       GREY             9         3.99         3.99
                   Diamond       GREY            10         3.52         3.52
                  Hematite       GREY             6         5.10         5.05
                     Ivory       GREY           2.5         1.80         1.54
                   Jadeite       GREY             7         3.34         3.33
               Labradorite       GREY             6          2.7         2.70
                    Marble       GREY             3         2.71         1.50
                Meerschaum       GREY             2         1.50         1.53
                  Nephrite       GREY           3.5         3.00         2.96
                      Opal       GREY             6         2.10         2.10
                    Quartz       GREY             7         2.65         1.55
                    Quartz       GREY             7         3.33         2.65
                      Talc       GREY             1         2.70         2.75
    Another possible format might be:
                                           Specific   Refractive
    Gemstone Name       Color    Hardness   Gravity      Index
    Alabaster            GREY       2         2.32        1.53
    Bakelite             GREY       2.5       1.28        1.65
    Calcite              GREY       3         2.70        2.71
    Casein               GREY       2.5       1.33        1.55
    Celluoid             GREY       2         1.35        1.50
    Chalcedony           GREY       7         2.62        1.53
    Corundum             GREY       9         3.99        3.99
    Diamond              GREY      10         3.52        3.52
    Hematite             GREY       6         5.10        5.05
    Ivory                GREY       2.5       1.80        1.54
    Jadeite              GREY       7         3.34        3.33
    Labradorite          GREY       6         2.70        2.70
    Marble               GREY       3         2.71        1.50
    Meerschaum           GREY       2         1.50        1.53
    Nephrite             GREY       3.5       3.00        2.96
    Opal                 GREY       6         2.10        2.10
    Quartz               GREY       7         2.65        1.55
    Quartz               GREY       7         3.33        2.65
    Talc                 GREY       1         2.70        2.75

    As shown in each example, the gemstone names and properties must appear in labeled columns. Gemstone names may be either left-justified or right-justified.

    Note that some gemstones, such as Quartz above, appear several times in the table, since variations of a gemstone may have different properties.

  1. Parenthesis Checking

    Write a program that reads a line of text from the terminal and checks if the parentheses in the line are balanced.


    1. The program should distinguish among three types of parentheses, { }, [ ], ( ).
    2. Parentheses checking should involve working from the inside of nested parentheses to the outside.
    3. In each case, the appropriate right parenthesis should be matched with a left parenthesis of the same type.


    1. ( these { parentheses[] match } perfectly ) !!!
    2. (the {right [parentheses ) on } this line ] are in the wrong order.
    3. this ( line { is missing } one (round ) right parenthesis.

    Comments on a solution to the problem: This problem can be solved reasonably easily using a single left-to-right scan of a line, if left parentheses are placed on a stack as they are encountered. Then, when a right parenthesis is found, the stack can be popped and one can check if the right parenthesis has the same type as the left one.

    Programming Note: Your program should use a self-contained Stack library package, as described in the lab on Stacks and implemented as lists.