CSC 161.01 Grinnell College Fall 2018
Scribbler 2
CSC 161.01:
Imperative Problem Solving with Lab
Scribbler 2
Course Home References Course Details: Syllabus, Schedule, Deadlines, Topic organization MyroC Documentation Project Scope/
Acknowledgments

Note: Although this course is well developed,
expect adjustments in some details as the semester progresses and the course evolves.

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. However, no more than 2 extra-credit problems may be turned in during the last week of classes (December 8-14, 2018). (If more than 2 extra-credit supplemental problems are submitted during the last week of classes, only the first two submitted will be graded.)

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 instructions regarding code, submission, and testing of supplemental problems.

Some Grading Notes:

Problem Statements

  1. Grocery-Gas Loyalty Program

    Several grocery stores have programs that encourage customer loyalty. In one common approach, a customer has a card from the grocery store that keeps track of the amount the customer has spent at the store in the last two weeks. Based upon the total expenditure, the customer is entitled to a discount at a cooperating gas station. The following table shows a hypothetical type of discount policy that represents a composite of several store programs:

    Amount Spent
    at Grocery Store
    Discount per Gallon on Gas Maximum Number of Gallons
    at Discounted Price
    $0.00 — $39.99 no discount no discount
    $40.00 — $79.99 2 cents per gallon up to 15 gallons
    $80.00 — $99.99 2 cents per gallon no limit on gallons
    $100.00 — $129.99 5 cents per gallon up to $1.50 discount
    $130.00 — $149.99 5 cents per gallon no limit on gallons
    $150.00 — $174.99 9 cents per gallon up to 17 gallons
    $175.00 or more 12 cents per gallon no limit on gallons

    Write a program that begins with initialized variables for the two-week total for grocery purchases, a price per gallon for gas (before any discount), and the number of gallons purchased. The program should print:

    • the initial data (grocery purchases, gasoline price per gallon, and number of gallons purchases)
    • the total cost for the gasoline, before discount,
    • he actual discount received (covering all gallons, not the actual price per gallon), and
    • the total price paid actually paid for the gas.

    Grading Forms

  1. Interest in a Savings Account

    A simple savings account earns compound interest over time, based upon an annual interest rate (e.g., 1% or 9%) per year. The basic computations proceed as follows:

    • A monthly interest rate is computed:
      monthlyRate = annRate / 1200.0;
      
    • The monthly rate determines the interest the bank adds to the account each month, according to the formula:
      interest = monthlyRate * (old balance)
      new balance = (old balance) + interest
      

    For example, at an annual rate of 8%, the monthly rate is 0.00666667. With a starting balance of $100, the computations proceed as follows for the first year:

           Starting   Monthly   Ending
    Month   Balance   Interest  Balance
      0      ------     ----     100.00
      1      100.00     0.67     100.67
      2      100.67     0.67     101.34
      3      101.34     0.68     102.01
      4      102.01     0.68     102.69
      5      102.69     0.68     103.38
      6      103.38     0.69     104.07
      7      104.07     0.69     104.76
      8      104.76     0.70     105.46
      9      105.46     0.70     106.16
     10      106.16     0.71     106.87
     11      106.87     0.71     107.58
     12      107.58     0.72     108.30
    

    This problem asks to you

    • write a procedure computeUntilDouble that computes monthly balance until the amount in the account doubles from the initial balance.
    • write a program that uses computeUntilDouble in several ways.

    The following notes provide additional information regarding this work.

    • procedure computeUntilDouble

      • The procedure should have the following signature:
        void computeUntilDouble (double initial_balance, double annual_rate,
                                 char print_option, int * months_to_double)
        
        • initial_balance gives the initial balance, before any interest has accrued.
        • annual_rate gives the annual percentage interest rate
        • print_option specifies one of three alternatives:
          • 'n': no printing is to be done by the procedure
          • 'm': the status of the account (i.e., month number, starting balance, interest for that month, and ending balance) is printed every month.
          • 'y': the status of the account (i.e., month number, starting balance, interest for that month, and ending balance) is printed every year (i.e., every 12 months).
      • months_to_double refers to an integer variable in the main program, and the number of months required for the account balance to double is stored in this variable when the procedure concludes.
      • Processing in computeUntilDouble continues until the balance in the account doubles from its original value.
      • Regardless of what printing option is selected, computeUntilDouble may have only one loop. Within the loop, the print_option should be consulted to determine whether or not to print the account balance for that loop iteration.
    • The program should compute and print the following:

      • An initial table should be printed, giving a monthly status report for an account that starts with $100 at an 8% annual percentage rate. (That is, the first part of this table should agree exactly with the sample table given above — although spaces on a line may be inserted or deleted.)
      • A second table should be printed, giving an annual status report for an account that starts with $300 at a 2% annual percentage rate.
      • Starting with $100.00 in an account, the program should print a table giving the number of months for the account to double with annual interest rates of 1%, 2%, 3%, ..., 9%.

    Grading Forms

  1. Playing Modified Scrabble

    The game of Scrabble is a word game, in which players place letters on a grid to form words. After the first word is placed on the board, subsequent words must intersect one or more existing words. In the game, letters from a player are connected to letters already on the board to form words. Many descriptions of the game are available online, including a reasonably thorough discussion on Wikipedia.

    This problem considers the addition of a word to the board, where a new word will intersect with an existing word. For example, consider the following grid:

    
            P R O G R A M 
      M E M O R Y
          N E T W O R K 
      S Y S T E M                   E
            S T R I N G     A N T I Q U E
                    O       L       U
                  C O L L E G E     A
        T P       A D       E       T S
        H H       L L       B       I C
        E Y       C E       R       O H I O
        O S       U         A       N E
      G R I N N E L L                 M
        Y C       U                   E
          S       S
    

    This grid contains numerous words arranged horizontally or vertically, and each word is connected to one or more other words at various letters. When inserting a word, it is not required that every letter of the new word must form a word with every adjacent letter. For example, the words PROGRAM, MEMORY, NETWORK, SYSTEM and STRING at the top left are positioned along the vertical word POETS. Reading down in the next column from POETS, one gets the sequence RRTET; this is not a word, but that is irrelevant to the rules for this problem.

    Within this context, a first word may be placed anywhere on the grid. Thereafter adding a new word requires that the word connect with at least one existing letter already on the grid. If the new word would extend over several existing letters, then the corresponding letters must match. For example, in the illustration, the word RARE could be added vertically using the R in PROGRAM and the R in NETWORK. However, the word RAKE could not be added in this position. The first R would fit with the R of PROGRAM, but the K in RAKE does not match the grid element already on the grid (the R in NETWORK).

    This problem asks you to write a program to support the addition of new words for this type of word grid. In particular, the program should do the following.

    • When the program starts, it should ask for the number R of rows and the number C of columns for the grid, and a blank grid of this size should be created internally. (This blank grid need not be printed.)

           rows   columns
      
    • Subsequent processing will consider squares identified with a row and column, i and j, with 0 ≤ i ≤ R and 0 ≤ j ≤ C.
    • The user inputs new words, specifying two or four pieces of data:
      • If the user enters a word, followed by a space and the letter R, then the program is free to place the word any place at random where the word fits.
             word R
        
      • If the user enters a word, followed by a space, the letter H, a space, a number i, a space, and another number j, then the word is to be placed horizontally with the first letter at row i and column j.
             word H rowi colj
        
      • If the user enters a word, followed by a space, the letter V, a space, a number i, a space, and another number j, then the word is to be placed vertically with the first letter at the row i and column j.

             word V rowi colj
        
    • If the word placement is given and is valid, the word is added to the grid, and the grid is printed. (I.e., the word is added if it intersects with at least one letter already on the board, and the letters match each time the new word intersects an existing one letter in the grid).

    • If the word placement is not given (letter R is entered), then the word is added to the grid once at any valid position (if such a position exists), and the grid is printed.

    • If the word cannot be added at the specified location or if no position is possible for an open placement, then an error message is printed.

    • The program continues to ask the user to enter words until the user enters QUITQUIT, in which case the program stops.

    Programming Notes:

    • In placing any word, it should not run off the edge. That is, if a word is too long to fit in the space from its designated start to the edge of the grid, then no part of the word may be inserted.
    • The program should contain a function check_horizontal that determines if a word can be added horizontally to the grid at a given location:
      /* check if the given word can be added horizontally at the given location
         pre-conditions
            row is a valid row location within the grid
            col is a valid column location within the grid
            word is a valid string
            num_rows is the total number of rows in the grid
            num_cols is the total number of columns in the grid
            grid is the two-dimensional array representing the grid
         post-conditions
            returns true (i.e., 1) if the word can be added to the grid
                    horizontally with the first letter at the given row and col
            returns false (i.e., 0) otherwise
            the grid is NOT changed
      */
      int check_horizontal (char * word, int row, int col, 
                            int num_rows, int num_cols, char grid[num_rows][num_cols])
      
    • The program should contain a function check_vertical that determines if a word can be added vertically to the grid at a given location:
      /* check if the given word can be added horizontally at the given location
         pre-conditions
            row is a valid row location within the grid
            col is a valid column location within the grid
            word is a valid string
            num_rows is the total number of rows in the grid
            num_cols is the total number of columns in the grid
            grid is the two-dimensional array representing the grid
         post-conditions
            returns true (i.e., 1) if the word can be added to the grid
                    vertically with the first letter at the given row and col
            returns false (i.e., 0) otherwise
            the grid is NOT changed
      */
      int check_vertical (char * word, int row, int col, 
                            int num_rows, int num_cols, char grid[num_rows][num_cols])
      

    Grading Forms

  1. Course Listings

    Overview: Once information on individual courses is stored in an array, then the array may be sorted and printed in several ways (e.g., by department prefix and course number, course title, enrollment capacity, and instructor's last name. This problem asks you to write a program to read course information for several courses and then sort the courses according to various criteria.

    Some Details

    Information for an individual course may be stored in a struct:

    struct course {
       char dept_prefix [4];  // examples: CSC, MAT, POL
       int number;            // examples: 151, 131, 101
       char title [100];      // example: Functional Problem Solving
       int capacity;          // examples:  32, 28, 25 
       char instr_name [40];  // examples: walker, Wolf, Hess
    };
    
    1. Write functions that return true (e.g., 1) if one course comes before another, based on course prefix/number, title, capacity, instructor's name:

         /* Deterime if one course precedes another by course prefix and number
            post-condition:
               returns true (1)
               if course1.dept_prefix comes before course2.dept_prefix as strings, or
                  or the dept_prefixes of course1 and course 2 are equal
                     and course1.number < course2.number
               returns false (0) otherwise
          */
         int comes_first_ID (struct course course1, struct course course2)
      
         /* Deterime if one course precedes another by course title
            post-condition:
            returns true (1)
            if the title of course1 comes before the title of course2 as strings
            returns false (0) otherwise
          */
         int comes_first_title (struct course course1, struct course course2)
      
         /* Deterime if one course precedes another by enrollment capacity
            post-condition:
            returns true (1)
            if course1.capacity < course2.capacity
            returns false (0) otherwise
          */
         int comes_first_capacity (struct course course1, struct course course2)
      
         /* Deterime if one course precedes another by instructor's name
            post-condition:
            returns true (1)
            if the instructor's name for course1 comes before the instructor's
               name for course2 as strings
            returns false (0) otherwise
          */
         int comes_first_instructor (struct course course1, struct course course2)
      

    With the above declaration for a course, an array of n courses could be declared:

    struct course arr [n];
    
    1. Write a sorting procedure that uses an insertion sort to place elements in any array in ascending order, according to the notion of a function comes_before:
        /*
         pre-conditions:  n > 0;
                          arr is an array of at least n course elements
         post-condition:  elements arr[0]..arr[n-1] are placed in assending order
                          that is, all of the following expressions are true:
                              comes_before (arr[0], arr[1])
                              comes_before (arr[1], arr[2])
                              comes_before (arr[2], arr[3])
                              ...
                              comes_before (arr[n-2], arr[n-1])
         */
        void sort (int n, struct course arr [],
                   int comes_before (struct course course1, struct course course2));
      
    2. Write a program that
      • Reads an integer n,

      • Read data for n courses (each field of each struct on a separate line, and courses separated by blank lines).

      • Allows the user to sort and print the courses according to any of the criteria given at the start of this problem.

    Notes:

    • To get started, file course-sort.c provides a basic shell for this program.

    • As this template indicates, your program may contain only one sorting procedure. Following a functional problem-solving style (e.g., from CSC 151), different sorting outcomes can be obtained by utilizing a function parameter that indicates when one data elements comes before another. See the reading on function parameters for details on using functions as parameters.

    • Testing of this program may seem tedious, as each run of the program requires the user to enter data for many courses and then to specify which option(s) should be utilized. To reduce typing for repeated testing, one can write a separate test file that tells the computer to [compile and] run the program and also contains each line of input the user might type.

      File course-shell-script illustrates a simple testing script. The first two lines:

      gcc -o course-shell course-shell.c
      course-shell << !
      

      compile the program with the usual gcc command and then run the program. When running the program, the phrase << ! tells the computer to use what follows as the input to the program, with that input continuing until the character ! appears at the start of a new line. Each subsequent line in this file contains exactly what a user would enter when running the program — character-by-character and line-by-line.

      To use this program:

      • Download course-shell-script, and store it in the same directory as your program.

      • Change the permissions for this file, so that you can run the file as a program:

        chmod 755 course-shell-script
        
      • Run the script in the same way you would run a program, by typing the name of the script in a terminal window:

        course-shell-script
        

        Naturally, you will want to either extend this script or write some new ones, in order to cover a full range of testing.

      Grading Forms

  1. Library Book Borrowing

    A public library allows residents to check out up to five books at a time. Assuming the town is small, everyone is known by name, so only a person's name, the number of books, and the due date are stored. (No need to keep track of addresses or telephone numbers — that information is well known throughout the town.) In support of this application, we will store the relevant data on a singly-linked list using node declarations:

         #define maxStrLen 100
         #define maxDateLen 40
         #define maxBooks 5
         struct item {
             char name [maxStrLen];
             int numBooks;
             char booksBorrowed [maxBooks] [maxStrLen];
             char dueDate [maxDateLen];
             struct item * next;
             }
    

    To make processing easy (at least for this problem), a resident checks out one to five books with a common due date. Further checkouts are not allowed, until all previous books are returned. Residents can inquire about what books they have checked out at any time.

    Initial processing notes:

    • The main menu for working with residents and checked out books is as follows:

      Library checkout  options:
         c:  check out 1-5 books (but only if resident has no books currently checked out)
         p:  print all residents with checked out books
         s:  search the checkout list for a given resident, 
                printing the resident's name, books checked out (if any), and due date
         r:  return a book, given resident's name and book title
         q:  quit
      
    • When a resident checks out books, the titles are stored as rows in the booksBorrowed array. For convenience in printing, the titles are all in the first rows of the table. If the resident has not borrowed the maximum of five books, the last rows are left blank.

    • When a resident wants to check out books (option c), the list is searched. If the resident has no books outstanding, a new node is created for the resident. For efficient insertion, this node should be added at the front of the linked list. (For example, one might use the approach of Scheme-like lists.)

    • Printing (option p) should display resident names with checked out books, the books they have borrowed, and the common due date. The resident's records may appear in any order. However, printing should not change the list itself.

    • Some residents inquire often about their checked-out books, and some residents ask rarely. Thus, in improve efficiency for curious residents, whenever a search for a resident (option s) is performed, the resident's record is moved one node closer to the front of the list. (Assuming the resident has checkout books to find. If the resident's name is already first, the list is not changed.) This movement of nodes will help ensure that commonly accessed nodes stay near the front of the list.

    • When a book is returned (option r), the book title is removed from the resident's record in the node.

      • If other books remain checked out, the book titles are moved down in the two-dimensional array. so they are all together as the first rows of the table.
      • If no other books remain checked out, the resident's record is removed from the list.
    • Each menu option for this problem (except quit) should be performed by a separate function. (Helper functions are allowed. As long as the main program calls a function for each menu option, processing may be organized in whatever way seems appropriate.

    • Global variables may not be used in this problem. (Each declaration of a global variable will yield a 15 point penalty, so the use of two global variables guarantees 0 points for this problem.)

    Grading Forms


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. [approximately 10 points]

    Computing nth Roots

    Basic Algorithm: The Bisection Method

    Suppose we are given a continuous function f, and we want to approximate a value r where f(r)=0. While this can be a difficult problem in general, suppose that we can guess two points a and b (perhaps from a graph) where f(a) and f(b) have opposite signs. The four possible cases are shown below:

    four cases for the bisection method

    We are given a and b for which f(a) and f(b) have opposite signs. Thus, we can infer that a root r must lie in the interval [a, b]. In one step, we can cut this interval in half as follows. If f(a) and f(m) have opposite signs, then r must lie in the interval [a, m]; otherwise, r must lie in the interval [m, b].

    Applying the Bisection Method to f(x) = xn - r

    As a special case for the Bisection Method, consider the function f(x) = xn - r, where n is a positive integer and r is a positive real number. A root of this function occurs when r = xn, or r is the nth root of r.

    Write a program that inputs a positive integer n, a positive real number r, and a positive real number acc and uses the bisection method to compute the nth root of r.

    Programming Notes:

    • The only arithmetic operations allowed in this program are addition (+), subtraction (-), multiplication (*), and division (/). Use of any other operations or library functions will result in an immediate -10 on this problem (that's right, your score on supplemental problems will be reduced by 10 points, for taking up time without making progress on the problem.) For example, use of C's power function pow in the math library would yield negative points for this problem.
    • Your program should use the bisection method with the function f(x) = xn - r.
    • Computations should continue until the size of the interval is less that acc, the accuracy desired for the answer.
    • Once the loop stops,
      • if an interval endpoint happens to be a root of the function, return that endpoint as the answer.
      • otherwise, use the midpoint of the interval as final approximation to the desired nth root.
    • The Bisection Method requires an initial guess at endpoints. Although you can use whatever guesses you wish (as long as the function at those points has opposite signs), the following are suggestions to consider (as easy guesses that always work).
      • Choose 0 as the left endpoint (a in the figure).
      • If r ≤ 1.0, choose 1.0 as the right endpoint (b in the figure).
      • If r ≥ 1.0, choose r as the right endpoint (b in the figure).
    • Whatever starting endpoints you use, include a paragraph about why those initial values fulfill the conditions for the Bisection Method.
  1. [approximately 10 points]

    Times for Walking and Running

    When running or walking for exercise, it is not uncommon for an individual to determine the time it takes to travel 1/4 mile (in minutes and seconds) and to compute one's speed in miles per hour or kilometers per hour.

    Write a program that prints a table of speeds in the following format:

               Speed in MPH and KPH, Given Time for 1/4 mile
                                  Minutes
    Seconds    3          4          5          6          7
       0
       1
       2
       3
     ...
      29
      30                          2.7/4.4
      31
     ...
      59
    

    For example, in this table, if an individual covers 1/4 mile in 5 minutes, 30 seconds, then the person is traveling about 2.7 miles per hour (MPH) or, equivalently, 4.4 kilometers per hour (KPH).

    Programming Notes:

    • 1 mile is approximately 1.60344 kilometers

    • Your solution must include a function compute_mph to compute miles per hour, given time in minutes and second for traveling 1/4 mile. The function should have the following signature:

      double compute_mph (int min_time, int sec_time)
      
    • Your solution also must include a function compute_kph to compute kilometers per hour, given time in minutes and second for traveling 1/4 mile. The function should have the following signature:

      double compute_kph (int min_time, int sec_time)
      
    • compute_kph should call compute_mph to obtain MPH and then convert miles to kilometers.

    • To print double numbers to one decimal place, use %3.1lf format (or %4.1lf). The .1 indicates 1 digit will be printed after the decimal point.

  1. [up to approximately 5 points per part; 15 points total]

    Web Server Log Files

    When working with a Web browser, you may request that a Web page be displayed. For example, in your browser, you might specify the following URL:

    http://www.cs.grinnell.edu/~walker/courses/161.fa18/suppl-prob.php

    With this request, your brower and computing environment send a request for the desired page (suppl-prob.php) to the serer www.cs.grinnell.edu, otherwise known as baran.cs.grinnell.edu.

    When the Web server receives this request, it performs at least two basic tasks:

    • The server tries to locate the requested material and send it back to your browser, and
    • the server records your request in a "log" file.

    For example, one request to the above page on June 1, 2018 was logged with the following file entry:

    12.196.104.253 - - [01/Jun/2018:19:35:45 -0500] "GET /~walker/courses/161.fa18/suppl-prob.php HTTP/1.1" 200 54122
    

    In brief, this entry can be understood with the following annotations:

    • 12.196.104.253: The address of the computer requesting the page had Internet (IP) address 12.196.104.253 (an address at the Crowne Plaza Hotel in Kansas City, MO. (This information is necessary, so the Web server will know where to send the requested page.)

    • 01/Jun/2018:19:35:45 -0500: The date and time the request was made.

    • GET: The request method utilized by your browser.

    • /~walker/courses/161.fa18/suppl-prob.php: The Web page requested on the server.

    • HTTP/1.1: The specific format that the Web server will use to send the material.

    • 200: A code indicating that the Web server could retrieve and send the desired material without trouble.

    • 54122: The size of the requested material (not including some behind-the-scenes details).

    As already noted, this amount of material is recorded for every request made by every user for material from a Web server.

    On MathLAN for the Mathematics and Computer Science Department at Grinnell College, the Web server is called baran.cs.grinnell.edu, and the file for current logging is called /var/log/apache2/access.log

    Users with MathLAN accounts can access this material by logging into baran.cs.grinnell.edu. From most MathLAN workstations, this can be accomplished with the command:

    ssh baran.cs.grinnell.edu
    

    You may be asked to confirm you want to access this server and then provide for your account password. Once logged in, you can use cd to move through your home directory and files.

    When you have a program prog.c, you can compile it (e.g., to get prog, and then run the program using the Web log file as your input:

    gcc -o prog prog.c
    prog < /var/log/apache2/access.log
    

    Using this environment, this problem asks you to scan this log file to answer each of the following questions.

    1. How many times has a 161 file from /~walker/ been accessed?

    2. From a MathLAN workstation, type

      hostname -i
      

      With this information, how many times has someone from your local workstation accessed a 161 file from /~walker/

    3. What are the unique names (names without duplicates) of all /~walker/ 161 files accessed by your local workstation?

    Notes:

    • One way to approach this problem involves reading one line at a time (e.g., with fgets) from stdin, using the redirected input show above.

    • The file /var/log/apache2/access.log is available on the the server baran.cs.grinnell.edu. Thus, although you can write and compile on any MathLAN workstation, you will need to use ssh to run your program, as described above.

    • For each line, use string functions to search for the desired string(s) in the line, and count (or print) those that match.

    • Log files often are very large . For example, when this problem was first written (June 1, 2018), the log file contained 5,004,828 lines of entries, including 577,519,698 characters. With files of this size, processing should involve only one pass through the file, and multiple passes through the data to obtain different answers is likely not practical.

    • This problem illustrates that Web browsing need not be anonymous. A log file indicates the Internet (IP) address of a machine, not the user. However, other logs may indicate who logged into a machine when, so putting a few pieces of data together from multiple sources may allow an interested party to determine who accessed what and when.

    • Further, a more detailed analysis might indicate the number of times one or more users accessed a site or what combination of pages they viewed on a regular basis.

    • Summary: You likely should NOT consider browsing the Web to be private or secret!

  1. [approximately 12 points]

    Directing a Robot to Follow a Tape

    Assume that tape has been place on the floor, and suppose that the color of the tape is significantly different (i.e., darker or lighter) than the floor. This problem asks you to write a program that will control the robot to follow the tape for at least a minute or two.

    Some programming notes:

    • In the lab on two-dimensional arrays, one exercise asks to locate an area of the brightest light in a picture. In this problem, use a similar approach to find the edge of a piece of tape on the floor. Since the color of the tape contrasts with the floor, one should scan a picture from the robot to determine where the color changes substantially from light to dark or dark to light.
    • If the color change is approximately straight ahead, the robot might go forward a short distance before taking another picture.
    • If the color change on the left side of the picture, the right motor might be directed to move more quickly than the left motor, so the robot will move somewhat to the left. The farther the color change is to the left, the more the difference between the right and left motors. After moving a short distance, the robot might stop and take another picture.
    • If the color change is to the right, the right motor might be directed to move less quickly than the left motor, so the robot will move somewhat to the right. The farther the color change is to the left, the more the difference between the right and left motors. After moving a short distance, the robot might stop and take another picture.

    Overall, the robot should follow a tape that winds left and right around the floor for at 10 or more feet.

  1. [approximately 12 points]

    Assigning Lab Partners

    In CSC 161 and numerous other courses, students may work on labs or projects (sometimes other assignments) in small groups (usually pairs). These groups are assigned by the instructor, and groups are changed frequently. This problem seeks a program to determine these assigned groups. (Currently, the assignments are done manually, with a labor-intensive process.) The basic requirements follow:

    • Suppose there are N students in the class (where N is between 24 and 38). For the purposes of this problem, the students are numbered 1, ..., N.
    • Early in the semester, students are given the option of indicating
      • which 1-3 students they would like to work with a few times over the semester, and
      • which 1-3 students they would like NOT to work with during the semester.
      Following past history, for this problem, we assume no more than 6 students indicate preferences of whom to work with, and no more than 6 identify 1 or 2 people they do not want to work with. (Usually the numbers are just 2 or 3 in each category.)
    • Groups of 2 are preferred for an assignment, but a group of 3 is needed if N is odd.
    • Students expressing an interest in working with another designated person may be assigned that person up to 3 times during the semester, and these repeated assignments should be spread out over several groupings. Otherwise, students should be working with someone different with each assignment.
    • During the semester, a student should not be asked to work in a group of three more than once.
    • Sometimes during the semester (but not often), a student drops the course. That is, the student may be assigned a group for the first several weeks, but the student should not be assigned a partner after a designated week.

    Write a program that identifies and prints up to 14 assignments of students (i.e., up to one new assignment of pairs each week). The program should have the following features:

    • The program is deterministic. That is, the program makes the same assignments every time it is run. (This allows the program to be run several times during the semester, if a few people drop.)
    • The program provides the option that up to 8 students may drop the course after varying assignments. (In practice, there are rarely more than 2 drops, so allowing 8 is intended to be safe.)
    • Under varying circumstances, it may not be possible to make different assignments each week. However, in all cases, a student should never have to work with someone they explicitly wanted to avoid. Also, the resulting assignments should have as few repeated pairs of students as possible, with students wanting to work together never having more than 4 assignments together.
  1. [approximately 12 points]

    Making Change

    Suppose a store's cash register stocks as many coins (pennies, nickels, dimes, quarters, fifty-cent pieces, and one-dollar coins) and as many bills (one-dollar, five dollar, ten dollar, and twenty dollar denominations) as possible.

    Write a program that reads an amount of change (up to $40.00) and prints:

    • all possible ways to make change, and
    • the number of this alternatives.

    Programming Notes:

    • Permutations of coins should be counted only once. That is, to make change for $0.11, four options should be counted: eleven pennies, six pennies and one nickel, one penny and two nickels, and one penny and one dime. The program should not count one penny and two nickels as being different from one nickel one penny and another nickel or as being different from two nickels and one penny.
    • Use of one-dollar coin should be considered as being different from a one-dollar bill.
    • The program should be reasonably efficient.
    • To help save paper in testing, the program may have a command-line argument "print" or "no-print" that turns on or off the listing of all possible ways to make change. If this is implemented, "no-print" would indicate that the total number of ways to make change would be printed, but not the actual listing of all of those alternatives.

    Hint: Although this problem can be solved in many ways, one reasonably efficient, simple, and elegant algorithm makes heavy use of recursion.

  1. [approximately 10 points]

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

    Notes:

    • 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 inrface 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. [approximately 12 points]

    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. [approximately 12 points]

    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. [approximately 12 points]

    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:

              11111111112222222222333333333344444444445555555555666666666677777
    012345678901234567890123456789012345678901234567890123456789012345678901234
    
                    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.