CSC 161 Grinnell College Spring, 2013
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


In turning in any programs for the course, please follow these directions:
  1. The first lines of any C program should be comments containing your name, your mailbox number, this course number (161), an identification of assignment being solved, and an Academic Honety certification. (You may not talk to anyone, except the instructor, a class mentor, or an evening lab tutor, for any Supplemental Problem.) For example:
         * Henry M. Walker                                               *
         * Box:  Science                                                 *
         * Supplemental Problem 1 for CSC 161                            *
         * Assignment for Friday, February 8                             *
        /* ***************************************************************
         * Academic honesty certification:                               *
         *   Written/online sources used:                                *
         *     [include textbook(s),                                     *
         *       CSC 161 labs or readings;                               *
         *       complete citations for Web or other written sources]    *
         *     [write "none" if no sources used]                         *
         *   Help obtained                                               *
         *     [indicate names of instructor, class mentors              *
         *      or evening lab tutors, consulted                         *
         *      according to class policy]                               *
         *     [write "none" if none of these sources used]              *
         *   My signature below confirms that the above list of sources  *
         *   is complete AND that I have not talked to anyone else       *
         *   [e.g., CSC 161 students] about the solution to this problem *
         *                                                               *
         *   Signature:                                                  *
    Also, a comment is needed for every definition of a C function, stating both pre- and post-conditions for that program unit.

  2. Email your program to, as follows:
    • The subject line should include "CSC 161", the assignment name, and your name (when the program involves work with a collaborator, put both names in the subject line).
    • Include the C program as an attachment. If the program involves several files, attach all relevant (.c and .h) files. (Include only the source code (e.g., .c and .h files; do not include compiled code.)
    • Include an attachment that shows test runs of the program.
    • To count as being submitted on time, the time stamp on the email must be before the start of the class in which the work was due.
  3. Turn in a printed copy of your program, relevant output, and a discussion of testing.
    • A printed copy of the program should be on top. (Since your name, box, etc. are required to be at the start of the program, this printout will identify that this is your work.)
    • If your work involves several files, list the main program first; then list any supplementary files.
    • Write a statement that documents the testing process for this program. The statement should include:
      • A numbered listing of the circumstances that can reasonably arise in this problem.
        • For example, if a program is to categorize data, the listing should include a statement of the categories; If some category could be obtained in several ways, the statement should identify each circumstance that could lead to the category.
        • As another example, if the order of initial data might impact processing, then the listing should include circumstances to test the order of input data.
      • A listing of test cases to be considered, with the expected outcome.
        • For each numbered item in the listing of possible circumstances, there should be a corresponding test case identified.
        • Each test case should be specific, including what data will be considered and what output is expected.
    • Compile your program with the gcc command, and run it.
      • If the program does not use the Scribbler 2, include the full range of test cases that demonstrate the correctness of your program. (You should print the full interaction from the terminal during the test runs.)
      • If the program uses the Scribbler 2, include a description of what test runs you used and what results you obtained.
      • The actual test runs should follow the above listing of test cases.
      • Each test run should be annotated (writing on the printout is acceptable), identifying which test case is being run and whether or not the output produced is correct.
    • Once testing is completed, prepare a separate statement that argues why your program is correct, based upon the evidence from your test runs.

Some Grading Notes:

Making Change:

  1. Write a program that contains the cost of an item and the amount paid by the customer, and then prints out the difference (the amount owed to the customer). Also print out how many bills of each denomination should be given to the customer (one-, five-, ten-, and twenty-dollar bills), and the remainder to be paid in coins.


    • Rather than read the cost and amount paid, the program should assign the cost of an item and the amount paid by the customer to variables at the very beginning of the program.
    • The output should have the following form, using correct grammar:
      Item cost:  $ 12.75
      Amount paid:  $ 20.00
      Change:  $ 7.25
         0 twenties
         0 tens
         1 five
         2 ones
         0.25 change

      Here is another example:

      Item cost:  $ 18.45
      Amount paid:  $ 50.00
      Change:  $ 31.55
         1 twenty
         1 ten
         0 fives
         1 one
         0.55 change

      In summary, "twenty", "ten" "five", "one" (singular) appear if the number of bills is one, but "twenties", "tens", "fives", and "ones" (plural) appear if the number of bills is either zero or greater than one.

    • Your computation should use the fewest number of bills.
    • Do NOT try to compute how many of each coin type should be given to the customer (pennies, nickels, dimes, and quarters).

    Problem-specific grading form for Supplemental Problem 1

  1. Mortgage Payments

    The monthly payment on a mortgage which will amortize (be paid off) in N years with a given annual interest rate is given by the formulae:

        monthlyRate = rate / 1200.0
        payment = amount * monthlyRate / (1.0 - (1 + monthlyRate)(-12*N))

    where amount is the amount borrowed.

    Write a program that computes the monthly payment and total amount paid over the life of the loan, and produces a table of the following form:

    annual rate years amount monthly payment total paid
    8.75 25 26000 213.76 64128.00
    5.35 30 90000
    5.35 20 90000
    4.35 25 90000

    Your program should have these features:

    • Three functions should be defined:
      • 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 years, double amt)
        that returns the monthly payment for the given parameters.
      • double total_paid( (double annRate, int years, double amt)
        that returns the total amount paid over the life of the loan.
      • Neither function should print anything.
        Rather each function should return the desired value, to be used or printed elsewhere.
      • total_paid should call compute_payment.
    • The main procedure should have three parallel arrays, each with the same number of entries:
      • array annualRate should contain various annual interest rates.
      • array years should contain various lengths of mortgages, given in years.
      • array amount should contain various amounts borrowed.
    • The ith row of the table should given the monthly payment and total amount paid for a computation involving annualRate[i], years[i], and amount[i].
      For example, for the table given above, the first part of each array would be as follows:
      array values for first table row:
      • annualRate[0] = 8.75;
      • years[0] = 25;
      • amount[0] = 26000;
      array values for second table row:
      • annualRate[1] = 5.35;
      • years[1] = 30;
      • amount[1] = 90000;
      array values for third table row:
      • annualRate[2] = 5.35;
      • years[2] = 20;
      • amount[2] = 90000;
      array values for fourth table row:
      • annualRate[3] = 4.35;
      • years[3] = 25;
      • amount[3] = 90000;

    Problem-specific grading form for Supplemental Problem 2

Histogram of Letters

  1. When given a number of data elements, it sometimes is convenient to visualize how many times each outcome occurs. For example, in reviewing text, we might count the number of times each letter occurs (ignoring case), and the print this number of asterisks (*) for each letter. The resulting diagram is called a histogram. As an illustration, the following diagram shows a histogram for the letter counts in this paragraph.

    Histogram follows:
             *                             *            
             *                             *            
             *                             *            
             *                             *            
             *                             *            
             *       *                     *            
             *       *                     *            
     *       *       *                     *            
     *       *       *                     *            
     *       *       *                     *            
     *       *       *                     *            
     *       *       *         * *     * * *            
     *       *       *         * *     * * *            
     *       *       *         * *     * * *            
     *       *       *         * *     * * *            
     *       *       *         * *     * * *            
     *       *       *         * *     * * *            
     *       *     * *         * *     * * *            
     *       *     * *       * * *     * * *            
     *       *     * *       * * *     * * *            
     *   *   *     * *       * * *     * * *            
     *   *   *     * *     * * * *     * * *            
     *   *   *   * * *     * * * *     * * *            
     *   *   *   * * *     * * * *     * * * *          
     *   *   *   * * *     * * * *     * * * *          
     *   *   *   * * *     * * * *     * * * *          
     *   *   *   * * *     * * * *     * * * *          
     *   *   * * * * *     * * * *     * * * *          
     *   *   * * * * *     * * * *     * * * *   *      
     *   * * * * * * *     * * * *     * * * *   *      
     *   * * * * * * *     * * * * *   * * * * * *      
     * * * * * * * * *     * * * * *   * * * * * *      
     * * * * * * * * *     * * * * *   * * * * * * *    
     * * * * * * * * *   * * * * * *   * * * * * * * * *
     a b c d e f g h i j k l m n o p q r s t u v w x y z

    Programming Notes:

    • This program should allow any number of characters to be entered before the # character is typed, and the input may be on one or more lines.
    • In this histogram of letters, all non-letters should be ignored.
    • Use of C functions, tolower and isalpha, within the ctype.h library is encouraged.
    • In order to determine the number of lines in the histogram, the program will need to determine the maximum count for any letter. For letters with this maximum count, the histogram will have a column of asterisks that goes from the top row to the bottom (just before the row of printed letters).

    Problem-specific grading form for Supplemental Problem 3

    Clarifying Examples

A Simple Route Cipher

  1. When sending a message from one place to another, it is common for the sender to encode the message before it is sent with the understanding that the receiver would know how to decode the message when it is sent. With this encoding process, anyone intercepting the message in transit would not be able read the text.

    For encoding, one approach is a substitution cipher, in which each letter in original message is replaced by another letter. (For example, each "a" in the message might be replaced by "d" and each "t" might be replaced by "w". This type of cipher is commonly used in many word puzzles in newspapers and puzzle books.

    A second approach for encoding is called transposition, in which the characters of the original message are rearranged in a different order. This problem implements a simple type of transition cipher, called a route cipher. (Historically, the Union forces in the American Civil War used a variation of a route cipher, called the Union Route Cipher.)

    Encoding: In a simple route cipher, letters of a message are placed into a rectangular table. As an example, suppose the cipher is based on a table of 5 rows and 9 columns, and suppose we wish to encode the text "this short example illustrates a route cipher". The first step of a route cipher is to insert the message row-by-row into the table, on character at a time.

    t h i s   s h o r
    t   e x a m p l e
      i l l u s t r a
    t e s   a   r o u
    t e   c i p h e r

    With this arrangement, the encoded message is obtained by retrieving the letters according a designated path or route from the rectangle. For this problem, we will retrieve the letters from the table column by column. For example, reading column-by-column from the above table, we obtain the coded message "tt tth ieeiels sxl c auaisms phptrholroereaur".

    Decoding: Given an encoded message, the receiver places the text character-by-character into the rectangle according the prescribed path (e.g., column by column). With the letters in the rectangle, the original message can be restored by reading the rectangle row-by-row.

    Extensions: In the basic encoding approach, the original message is placed in a rectangle of a designated size. If the rectangle has r rows and c columns, this approach works well if the message has length r*c, the size of the rectangle. Extensions are needed if the original message has length other than r*c characters.

    • If the original message has less than r*c characters, additional characters might be added to get the needed number. For example, we might add letters of the alphabet a, b, c, d, e, ... at the end of message as needed to fill the rectangle.
    • If the original message has more than r*c characters, the message is divided into blocks of r*c characters, and each block is encoded separately.

    As another example, suppose the rectangle is specified with 3 rows and 4 columns, and suppose we want to encode the message "this extended example shows the full algorithm".

    Encoding follows these steps:

    1. Divide the message into blocks of 3*4 = 12 characters. The last block would have only 10 characters, so "a" and "b" have been added to complete the block.

      t h i s   e x t e n d e
      d   e x a m p l e   s h
      o w s   t h e f u l l
        a l g o r i t h m a b
    2. Place each block into a rectangle, row-by-row:
      t h i s       d   e x       o w s           a l g
        e x t       a m p l       t h e       o r i t
      e n d e       e   s h       f u l l       h m a b
    3. Read characters from each block, column-by-column:
      "t ehenixdste"   "dae m epsxlh"   "otfwhusel  l"   " oharmliagtb"

      Combining the encoded blocks gives:
      "t ehenixdstedae m epsxlhotfwhusel  l oharmliagtb"


    • Write a program that reads the rectangle size (a row and a column) and the text of a message and prints the encoded message.
    • Explain how the above program can also be used for decoding and illustrate your explanation with an example.

    Programming Notes:

    • Although conceptually the first encoding step reads the entire message and then divides it into pieces, in practice, the program should read and process one block at a time:
      1. Read rectangle size and create rectangle(s) of the appropriate dimensions to process a single block.
      2. Continue until all input is processed
        1. Read one block
        2. Process characters for the one block
        3. Print encoded characters for that block
    • C allows arrays to be declared of a length that is determined during run time. See Arrays of Variable Length for details.

    Reference: A nice treatment of transposition ciphers may be found in Abraham Sinkov, "Elementary Cryptanalysis: A Mathematical Approach", The New Mathematical Library, Random House and the Mathematical Association of America, 1968, Chapter 5. A revised edition of the book is available in Abraham Sinkov and Todd Feil, "Elementary Cryptanalysis Second Edition", The New Mathematical Library, Mathematical Association of America, 2009.

    Problem-specific grading form for Supplemental Problem 4

Singly-linked-list Processing

  1. Program namelist.c contains a simple framework for maintaining a singly-linked list of names (with no more than 20 characters). The program has these features:

    • A singly-linked-list structure is defined.
    • The list is initially null.
    • A basic menu identifies several processing options, the program reads a user option, and the program calls a procedure for that option.
    • Procedure addName allows names to be added anywhere on the list.
    • Procedure print allows current names to be printed from the first to the last.

    This problem asks you to implement three additional functions within this program.

    • Function addNamesFromFile asks the user for the name of a file. Then names on separate lines from that file are added to the end (not the beginning or middle) of the current list.

      • If no file exists by the given name, the program should print an error message, exit the function, and continue with other processing.
      • If the file exists, each line of the file will be considered a single name, and each name is added, in order, to the end of the list.
    • Function removeDuplicates removes duplicates from the current list:

      • The first copy of a name on the list is retained.
      • All copies of a name after the first are deleted.
      • In the final list, the first copies of the names of the original list should be in the same order as at the start.

      In this processing, duplicate nodes should be removed and space deallocated, but no new nodes should be created.

    • Function putFirst moves a node for a specified name to the front of the list.

      • The function asks the user for a name
      • If the name is found as the first item on the list, a note is printed to confirm this location, but the list is not changed.
      • If the name is found on the list, but the name is not first,
        • the first node with that name is located
        • that node is removed from its current location
        • that node is inserted at the front of the current list

        In this processing no new node is created and no existing node is freed. Rather an existing node is moved.

      • If the name is not found on the list, an error message is printed and the list is not changed.

    Programming Hints:

    • In Program namelist.c, code for addName and print should not be changed in any way.
    • Program namelist.c also contains stubs for the new operations, but the bodies of these procedures only print a message that the operations are not implemented. This problem asks you to expand these stubs to working procedures.
    • In reading from a file, a name may contain spaces and/or punctuation. However, you may assume each line of the file contains a separate name, and the name has no more than 20 characters. Multiple names will not appear on the same line of a file.
    • Although code within the existing addName procedure itself should not be changed, parts of that code could be copied, modified, and streamlined in another procedure (e.g., addNamesFromFile) for insertion of names from a file.
    • In identifying duplicate names, it is up to the programmer to decide whether or not names with letters in different cases (upper case and lower case) are considered as the same name. Names with the same string of characters (with the same case) should be considered the same, but names with the same cases in different cases may or may not be considered the same (at programmer's discretion).

    Problem-specific grading form for Supplemental Problem 5

6174 Game

  1. This problem was suggested by Professor Arnold Adelberg.
    The wording of this problem is slightly edited from Problem 21 in Section 3.2 of "Problems for Computer Solutions Using BASIC" by Henry M. Walker, Winthrop Publishers, 1980.

    The following iteration procedure begins with any four-digit number n0. The procedure is best explained by an example: Let n0 = 3087. Then n1 is set equal to the difference of two integers formed from 3087. First, the digits are arranged in descending order (8730) and then in increasing order (0378). Then

    n1 =8730 - 0378 =8352
    n2 =8532 - 2358 =6174
    n3 =7631 - 1467 =6174
    n4 = ... =6174

    It is known that for any four-digit number n0 who digits are not all the same, the process generates the number 6174 in fewer than seven iterations.

    Problem: Find all numbers n0 between 2000 and 2500 inclusive which initiate sequences for which n4 = 6174 but n3 ≠ 6174.

    Note: In solving this problem you should not use string functions. Rather, consider using C's arithmetic operations for integers, such as / (integer division) and % (integer remainder).

Alphabetizing Numbers

  1. Write a C program that generates the names of the numbers from zero to two hundred and prints them in alphabetical order.


    • All numbers should be written as lower-case names.
    • The program should be as compact as possible and utilize logic rather than brute force. (For example, a program consisting of 200 printf statements will earn very little credit.)
    • The program should run efficiently. (For example, few points will be given for a program utilizing a bubble sort.)

Computing Store Discounts

  1. 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. For this exercise, assume that the costs of identical items will be grouped together on the list, and all consecutive equal costs relate to identical items. To illustrate, suppose the program reads the following 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

    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 program should allow successive numbers to be typed on one or multiple lines.
    • The program should continue processing numbers until a cost of $0.00 is read.
    • The program should consider negative costs as errors. If a negative is encountered in input, the program should print an error message and stop.
    • Processing should make one pass only through the initial list of costs.
    • The program may utilize any functions that seem convenient. However, even with multiple functions, processing should not make multiple passes through the data.
    • The use of arrays on this problem is actively discouraged and will likely lose credit.

Printing Cross Words

  1. Consider the problem of printing two words, the first word vertically (one letter per line) and the second word horizontally, so the words cross at a common letter. For example, if the first word is FUNCTIONAL and the second is SCHEME, then the desired output is:


    In this problem, you are to write a program that reads two words from a terminal window and prints them in the crossed pattern shown above (assuming they have a letter in common). If the words have more than one letter in common, then they may be printed with the crossing at any common letter. If the words have no letters in common, then the program should print an error message.

Simulation of Hi Ho! Cherry-O

  1. 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.

Dealing Bridge Hands

  1. Write a program that simulates the dealing of a deck of cards to give four bridge hands. 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.

City Data

  1. The file ~walker/151p/labs/lab26.dat contains several items of information about large American cities. More specifically, in ~walker/151p/labs/lab26.dat , each entry consists of the name of the city (line 1), the county or counties (line 2) and the state (line 3) in which it is situated, the year in which it was incorporated (line 4), its population as determined by the census of 1980 (line 5), its area in square kilometers (line 6), an estimate of the number of telephones in the city (line 7), and the number of radio stations (line 8) and television stations (line 9) serving the city. Thus a typical entry reads as follows:

    New Mexico
    A blank line follows each entry, including the last.

    Write a procedure which has a filename as parameter and which answers the following questions about the cities represented in the data files.

    1. Which of those cities has the highest population density (population divided by area)?
    2. Which of these cities has over one million telephones?
    3. Which city has the lowest per capita number of radio and television stations (together)?
    The answers to each of these questions should be printed neatly and clearly by the procedure.

Filtering and Reporting Data

  1. 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.

Parenthesis Checking

  1. 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.