Introduction to Programming (CPSC 124)
—Hobart & William Smith Colleges, Fall 2014
Thursday Lab #6: Arrays, I/O Redirection
Home | Syllabus | Calendar | Class Notes | Labs and Projects | General Notes

Due by 2:59 pm on Friday, 10/10/2014)

New Tools: DrJava

Beginning with this assignment, and continuing on for a few weeks, we'll use the DrJava development environment for Java. This environment offers a number of nice features for editing Java source code, including automatic indentation, syntax highlighting, and an integration of the Java compiler and runtime system.

If you want to install it on your own system, you can obtain a copy for free at http://www.drjava.org/.

Note for Mac users: The "Mac OS App" will not work with any version of Java later than 6.0. We're using version 7.0 in this class, and the most recent version is 8.0. Instead, download the "JAR file". This will download an "executable archive", which is almost the same thing as an app, but lacks some of the polish of more conventional applications. The current version is named drjava-stable-20140826-r5761.jar. You can launch it by the usual double-click method, or you can run it from the command line by typing

John-Lasseter:~ jlasseter$ java -jar drjava-stable-20140826-r5761.jar &

New Tools: I/O Redirection

As we've seen in previous labs, standard input for a program is taken from the keyboard by default. This can be changed. All Unix-based command-line environments (Linux, Mac OS Terminal, etc.), as well as the Windows command-line, provide the capability of changing the input source for a program's standard input, by using operators for I/O redirection. Here we'll learn to use the input redirection operator, <.

Here's a program that reads a series of numbers, then prints the smallest, largest, and average values:

import java.util.Scanner;

public class Avg {
  public static void main(String[] args) {
    Scanner inp = new Scanner(System.in);
    
    double least = Double.MAX_VALUE;  // "infinity"
    double most = Double.MIN_VALUE;
    double sum = 0;
    int ct = 0;
    
    while (inp.hasNextDouble()) {
      double x = inp.nextDouble();
      if (x < least) { 
        least = x;
      } 
      if (x > most) {
        most = x;
      }
      
      sum = sum + x;
      ct = ct + 1;
    }
    
    System.out.println("Max value:  " + most);
    System.out.println("Min value:  " + least);
    System.out.printf("Average:  %1.4f \n",sum/ct);
  } // main
} // Avg

Note that there's no prompting for values: when the program runs, the Scanner just suspends execution until input is given:

John-Lasseter:~ jlasseter$ java Avg
5   -23    0.4   5  5.2   6.7  8.9  47.8  1   q
Max value:  47.8
Min value:  -23.0
Average:  6.3333 

Notice how we included the non-number "q" at the end to terminate the input. Now save only the numbers in a file called nums.dat (in the same directory as your Avg program). Run Avg again like this:

John-Lasseter:~ jlasseter$ java Avg < nums.dat

Adding the "< nums.dat" to the end of the Avg invocation, redirects keyboard input to the contents of the nums.dat file. The input terminates on the file's "end of file" marker (which closes the input stream for the Scanner reading it).

Your Job (overview)

Working With Data Formats

Now that we've been introduced to arrays, we are able to begin working with more substantial data sets. Most applications adopt a convention for the kind of files they can read and write. The conventions vary, and as the programmer, you can often decide on your own format, but certain ideas come up again and again. File formats often include not only the basic data but also "metadata" information, which is used to direct the program in correctly reading the data itself. In this lab, we'll work with a slightly contrived example: a file format that describes decks of playing cards, ways for a dealer to shuffle them, and the order of shuffles to apply to the decks.

Input Format

To begin, we need a convention to map the integers 1 ... 52 to the cards in a standard deck. A deck has four suits—Clubs, Diamonds, Hearts, Spades—and each suit has 13 cards—2 through 10, Jack, Queen, King, and Ace. Our mapping will associate the integers 1–13 with Clubs, 14–26 with Diamonds, 27–38 with Hearts, and 39–52 with Spades. Within each suit, the values are associated in order 2–10, Jack, Queen, King, and Ace. For example, 13 is the Ace of Clubs, while 36 is the Queen of Hearts.

Input consists of an integer 0 < n ≤ 100, the number of shuffles that the dealer knows. Following this line are n lines, each one with 52 integers, defining the "shuffles". Each shuffle will list all the integers from 1 to 52 in some order. Within each set of 52 integers, i in position j means that the shuffle moves the ith card in the deck to position j.

Following these is a line with a single integer, m, indicating the number of shuffles to be performed.

After this, m lines follow; each containing an integer k between 1 and n indicating that you are to apply the kth shuffle given in the input.

Output

NOTE: This is not the problem you're solving today! You will in the coming homework assignment, but for today, it's just here to give you a sense of the overall problem.

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

Assume the dealer starts with a new deck ordered as described above. After all the shuffles had been performed, give the names of the cards in the deck, in the new order.

Sample Input

For readability, the two "shuffle definition" lines have been broken into a total of four lines (the first two lines make up the first line of real input, while the third and fourth comprise the second line in the input file):

2
2 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 52 51
52 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 1
2
2
1

Output for Sample Input

3 of Clubs
Ace of Spades
4 of Clubs
5 of Clubs
6 of Clubs
7 of Clubs
8 of Clubs
9 of Clubs
10 of Clubs
Jack of Clubs
Queen of Clubs
King of Clubs
Ace of Clubs
2 of Diamonds
3 of Diamonds
4 of Diamonds
5 of Diamonds
6 of Diamonds
7 of Diamonds
8 of Diamonds
9 of Diamonds
10 of Diamonds
Jack of Diamonds
Queen of Diamonds
King of Diamonds
Ace of Diamonds
2 of Hearts
3 of Hearts
4 of Hearts
5 of Hearts
6 of Hearts
7 of Hearts
8 of Hearts
9 of Hearts
10 of Hearts
Jack of Hearts
Queen of Hearts
King of Hearts
Ace of Hearts
2 of Spades
3 of Spades
4 of Spades
5 of Spades
6 of Spades
7 of Spades
8 of Spades
9 of Spades
10 of Spades
Jack of Spades
Queen of Spades
2 of Clubs
King of Spades

Your Job (Actual)

  1. You are to write a program, Shuffles.java, which reads a file in this format and displays the information in it. You should first report the number of shuffles that were defined. Following this, print out the integers in each shuffle, with each shuffle definition clearly indicated and the values separated by commas. Finally, you should report on the shuffles that are applied.

    For the example above, saved in an input file shufs.dat, your program should behave as follows:

    John-Lasseter:~ jlasseter$ java Shuffles < shufs.dat
    
    *** 2 shuffles defined ***
    *** Shuffle #1: *****
    2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 
    23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 
    43, 44, 45, 46, 47, 48, 49, 50, 52, 51
    *** Shuffle #2: *****
    52, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 
    23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 
    43, 44, 45, 46, 47, 48, 49, 50, 51, 1
    *** 2 shuffles applied, in the order: ***
    Shuffle #2
    Shuffle #1
    

    Note that this problem is about dealing with file formats, not arrays. You can do this with arrays (for reading the shuffle definitions), but it's not necessary.

  2. Write a second program, printDeck.java, which reads the integers 1 to 52 in some order. You may assume that there will always be 52 integers, that they will always be in the range 1–52, and that each value will occur only once. The program should print out the content of a deck of cards in the order given by these numbers. For example, if we have a file named deck.dat, with the contents

    2 52 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
    27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 1 
    51

    then your program should print out the result given in the "sample output", above.

    • HINT #1: Read the integers in to an array of 52 elements.
    • HINT #2: Use an array of String to store a table of the four suit names—"Clubs", "Diamonds", "Hearts", and "Spades"—in that order. If you have an int c, representing a "card number" , you can get the suit of this card with ((c - 1) / 13).
    • HINT #3: A trick similar to HINT #2 will give you the value for that card.
    • HINT #4: Obviously, you'll need a loop to read through each of the card numbers. If the combination of that with the translation to card names is overwhelming, start instead with a program that only reads one integer, printing the resulting card: That's basically the DateFormat problem from last week's lab tutorial!

Turn In


John H. E. Lasseter