CSCI A201/A597 and I210

Practical Advice

Second semester 2000-2001

"On a clear day you can see forever..."

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,


In which we take the problems apart one by one, and piece by piece.
General Advice:
First read the problem a few times, and make a rough draft of your plan of action. In what follows I will just show you the steps I take to solve the problem, roughly following the actual text of the problem. Be creative, always have a positive attitude!
Problem 1.

Write a program that greets the user

class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
  } 
} 
then asks the user for a positive number
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.println("Please enter the size of the array of prices: ");
  } 
} 
(we, of course need to read it)
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    // see the change we made above?
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt();  
    // make sure you have ConsoleReader.java in the same directory
  } 
} 
(and also to allocate the space for the array of prices)
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
  } 
} 
Then the program asks the user to enter the prices,
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
    System.out.println(
      "Please start entering the " + size + 
      " prices one by one at the prompt(s)."); 
  } 
} 
one by one. Each price is to be entered on a line of its own.
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
    System.out.println(
      "Please start entering the " + size + 
      " prices one by one at the prompt(s)."); 
    for (int i = 0; i < size; i++) {
      System.out.print("What is the next price? Enter it here: "); 
      prices[i] = console.readDouble(); 
    } 
  } 
} 
Have the computer keep track of how many prices are being entered
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
    System.out.println(
      "Please start entering the " + size + 
      " prices one by one at the prompt(s)."); 
    for (int i = 0; i < size; i++) {
      System.out.print("What is price " + i + "? Enter it here: "); 
      prices[i] = console.readDouble(); 
      System.out.println(
        "There are " + (size - i - 1) + " prices still to be entered."); 
    } 
  } 
} 
and how many are still to be entered at any time.

Then, at the end, the computer prints the largest price

class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
    System.out.println(
      "Please start entering the " + size + 
      " prices one by one at the prompt(s)."); 

    for (int i = 0; i < size; i++) {
      System.out.print("What is price " + i + "? Enter it here: "); 
      prices[i] = console.readDouble(); 
      System.out.println(
        "There are " + (size - i - 1) + " prices still to be entered."); 
    } 
    double largestThusFar = prices[0]; 
    for (int i = 0; i < prices.length; i++) {
      if (largestThusFar < prices[i]) {
        largestThusFar = prices[i];
      }
    }
    double largest = largestThusFar; 
    System.out.println("The largest price is: " + largest);
  } 
} 
the smallest price
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
    System.out.println(
      "Please start entering the " + size + 
      " prices one by one at the prompt(s)."); 

    for (int i = 0; i < size; i++) {
      System.out.print("What is price " + i + "? Enter it here: "); 
      prices[i] = console.readDouble(); 
      System.out.println(
        "There are " + (size - i - 1) + " prices still to be entered."); 
    } 
    double largestThusFar = prices[0]; 
    double smallestThusFar = prices[0];
    for (int i = 0; i < prices.length; i++) {
      if (largestThusFar < prices[i]) {
        largestThusFar = prices[i];
      }
      if (smallestThusFar > prices[i]) {
        smallestThusFar = prices[i]; 
      } 
    }
    double largest = largestThusFar; 
    double smallest = smallestThusFar;
    System.out.println("The largest price is: " + largest);
    System.out.println("The smallest price is: " + smallest);
  } 
} 
and the average of all prices:
class One {
  public static void main(String[] args) {
    System.out.println("Hello, and welcome to Problem One!"); 
    System.out.print("Please enter the size of the array of prices: "); 
    ConsoleReader console = new ConsoleReader(System.in);
    int size = console.readInt(); 
    double prices[] = new double[size];
    System.out.println(
      "Please start entering the " + size + 
      " prices one by one at the prompt(s)."); 

    for (int i = 0; i < size; i++) {
      System.out.print("What is price " + i + "? Enter it here: "); 
      prices[i] = console.readDouble(); 
      System.out.println(
        "There are " + (size - i - 1) + " prices still to be entered."); 
    } 
    double largestThusFar = prices[0]; 
    double smallestThusFar = prices[0];
    double sumSoFar = 0;
    for (int i = 0; i < prices.length; i++) {
      if (largestThusFar < prices[i]) {
        largestThusFar = prices[i];
      }
      if (smallestThusFar > prices[i]) {
        smallestThusFar = prices[i]; 
      } 
      sumSoFar = sumSoFar + prices[i]; 
    }
    double largest = largestThusFar; 
    double smallest = smallestThusFar;
    System.out.println("The largest price is: " + largest);
    System.out.println("The smallest price is: " + smallest);
    double totalSum = sumSoFar; 
    System.out.println("The average price is: " + totalSum / size);
  } 
} 
This concludes the program.

Here's a list of bibliographical references (pages in the book) that might help crystalize it:

  1. page 435: finding the lowest value in an array
  2. page 81: using ConsoleReader
  3. page 240: reading a set of numbers
  4. page 241: calculating their average
Hope you find this useful.

Problem 2.

We assume you understand problem 1 completely, so we start from:

class Two {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("Size> "); 
	int size = c.readInt(); 
	double prices[] = new double[size];
	for (int i = 0; i < size; i++) {
	    System.out.print("[" + i + "]> "); 
	    prices[i] = c.readDouble(); 
	}
	System.out.print("Your array: "); 
	for (int i = 0; i < size; i++) {
	    System.out.print(prices[i] + " "); 
	} 
	System.out.println(); 
    }
} 
Using the second formula in P6.9 (page 265) we need to compute:

  1. the sum of squares
    class Two {
        public static void main(String[] args) {
    	ConsoleReader c = new ConsoleReader(System.in); 
    	System.out.print("Size> "); 
    	int size = c.readInt(); 
    	double prices[] = new double[size];
    	for (int i = 0; i < size; i++) {
    	    System.out.print("[" + i + "]> "); 
    	    prices[i] = c.readDouble(); 
    	}
    	System.out.print("Your array: "); 
    	for (int i = 0; i < size; i++) {
    	    System.out.print(prices[i] + " "); 
    	} 
    	System.out.println(); 
    	double sumOfSquares = 0; 
    	for (int i = 0; i < size; i++) {
    	    sumOfSquares += prices[i] * prices[i]; 
    	}         
        }
    }
  2. the square of sum
    class Two {
        public static void main(String[] args) {
    	ConsoleReader c = new ConsoleReader(System.in); 
    	System.out.print("Size> "); 
    	int size = c.readInt(); 
    	double prices[] = new double[size];
    	for (int i = 0; i < size; i++) {
    	    System.out.print("[" + i + "]> "); 
    	    prices[i] = c.readDouble(); 
    	}
    	System.out.print("Your array: "); 
    	for (int i = 0; i < size; i++) {
    	    System.out.print(prices[i] + " "); 
    	} 
    	System.out.println(); 
    	double sumOfSquares = 0; 
    	for (int i = 0; i < size; i++) {
    	    sumOfSquares += prices[i] * prices[i]; 
    	} 
            double sum = 0; 
    	for (int i = 0; i < size; i++) {
    	    sum += prices[i]; 
    	}       
    	double squareOfSum = sum * sum; 
        }
    }

And then we compute a formula and take a square root.

class Two {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("Size> "); 
	int size = c.readInt(); 
	double prices[] = new double[size];
	for (int i = 0; i < size; i++) {
	    System.out.print("[" + i + "]> "); 
	    prices[i] = c.readDouble(); 
	}
	System.out.print("Your array: "); 
	for (int i = 0; i < size; i++) {
	    System.out.print(prices[i] + " "); 
	} 
	System.out.println(); 
	double sumOfSquares = 0; 
	for (int i = 0; i < size; i++) {
	    sumOfSquares += prices[i] * prices[i]; 
	} 
        double sum = 0; 
	for (int i = 0; i < size; i++) {
	    sum += prices[i]; 
	}       
	double squareOfSum = sum * sum; 
        double stdDev = 
	    Math.sqrt(
		      (sumOfSquares - squareOfSum / size) / (size - 1)
		     ); 
	System.out.println("Standard deviation: " + stdDev); 
    }
}
The other formula should be just as easy for you to use.

Also, the code can be simplified a lot.

Problem 3.

Calculating Fibonacci numbers is described in text and in lecture notes fourteen.

We start from the already known framework:

class Three {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("How many numbers: "); 
	int size = c.readInt(); 
	double numbers[] = new double[size];

	for (int i = 0; i < size; i++) 
	    System.out.print(numbers[i] + " "); 
        System.out.println(); 
    }
} 
Let's populate the array with Fibonacci numbers:
class Three {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("How many numbers: "); 
	int size = c.readInt(); 
	int numbers[] = new int[size];
	numbers[0] = 1; 
	numbers [1] = 1; 
	for (int i = 2; i < size; i++) {
	    numbers[i] = numbers[i-1] + numbers[i-2]; 
	} 
	for (int i = 0; i < size; i++) 
	    System.out.print(numbers[i] + " "); 
	System.out.println(); 
    }
} 
Now you can apply the solution developed for problem 2.

Problem 4.

Given a number that a user enters:

class Four {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter a number: "); 
	int number = console.readInt(); 

    } 
}
we need to consider all the numbers smaller than it:
class Four {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter a number: "); 
	int number = console.readInt(); 
	for (int i = 2; i < number; i++) {

	} 
    } 
}
and for each test if it's a factor
and if it is print it, while taking it out of the number completely.
class Four {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter a number: "); 
	int number = console.readInt(); 
	for (int i = 2, temp = number; i < number && i <= temp; i++) {
	    while (temp % i == 0 ) { 
		System.out.println(i); 
		temp = temp / i;
	    }
	} 
    } 
}
Elementary mathematical knowledge about factoring of integers is assumed.

Problem 5.

Let's define a Wizard first.

class Wizard {

}
An object of type Wizard will be able to count the factors of a number as in problem 4.

class Wizard {
    int countFactors(int number) {
	int count = 0; 
	for (int i = 2; i < number; i++) {
	    while (number % i == 0 ) {
		count += 1; 
		System.out.println(i);
		number = number / i;
	    }
	}
	return count; 
    } 
}
What's more or less new is in blue.

Now, having a Wizard around simplifies the original problem drastically.

class Five {
    public static void main(String[] args) {
	Wizard w = new Wizard(); 
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the number you want to test: "); 
	int number = console.readInt(); 
	int numberOfFactors = w.countFactors(number); 
    } 
}
A number is prime if there are no factors.

class Five {
    public static void main(String[] args) {
	Wizard w = new Wizard(); 
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the number you want to test: "); 
	int number = console.readInt(); 
	int numberOfFactors = w.countFactors(number); 
	if (numberOfFactors == 0) {
	    System.out.println("Yes, " + number + " is prime."); 
	} else {
	    System.out.println("No, " + number + " is not prime."); 
	} 
    } 
} 
Now that we know how to do that we can increase the wizardry of a Wizard.

class Wizard {
    int countFactors(int number) {
	int count = 0; 
	for (int i = 2, temp = number; i < number; i++) {
	    while (temp % i == 0 ) {
		count += 1; 
		System.out.println(i);
		temp = temp / i;
	    }
	}
	return count; 
    } 
    boolean isPrime(int number) {
	int numberOfFactors = this.countFactors(number);
	if (numberOfFactors == 0) {
	    return true; 
	} else {
	    return false; 
	}
    } 
}
And that's going to come in so handy with the next problem.

Problem 6.

Just ask the Wizard about each number:

class Six {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter an integer: "); 
	int integer = console.readInt(); 
	Wizard w = new Wizard(); 
	for (int i = 2; i <= integer; i++) {
	    if (w.isPrime(i)) {
		System.out.println(i); 
	    } 
	} 
    } 
}
Note that wizards are a bit more introvert this time.
class Wizard {
    int countFactors(int number) {
	int count = 0; 
	for (int i = 2, temp = number; i < number; i++) {
	    while (temp % i == 0 ) {
		count += 1; 
		// System.out.println(i);
		temp = temp / i;
	    }
	}
	return count; 
    } 
    boolean isPrime(int number) {
	int numberOfFactors = this.countFactors(number);
	if (numberOfFactors == 0) {
	    return true; 
	} else {
	    return false; 
	}
    } 
} 
Of course, you can do this problem in many other ways.

Problem 7.

Write a program stenographer

class Stenographer {
    public static void main(String[] args) {

    } 
}
that accepts lines of text from the user
class Stenographer {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("Please type a line of text: "); 
	String line = c.readLine(); 

    } 
}
and translates them (character by character)
class Stenographer {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("Please type a line of text: "); 
	String line = c.readLine(); 
	for (int i = 0; i < line.length(); i++) {
	    String temp = line.substring(i, i+1); 
            System.out.print(temp); 
        }
	System.out.println(); 
    } 
} 
in shorthand. For our purposes shorthand means removing the vowels everywhere.
class Stenographer {
    public static void main(String[] args) {
	ConsoleReader c = new ConsoleReader(System.in); 
	System.out.print("Please type a line of text: "); 
	String line = c.readLine(); 
	for (int i = 0; i < line.length(); i++) {
	    String temp = line.substring(i, i+1); 
	    if (temp.equalsIgnoreCase("A") ||
                temp.equalsIgnoreCase("E") ||
                temp.equalsIgnoreCase("I") ||
                temp.equalsIgnoreCase("O") ||
		temp.equalsIgnoreCase("U")) {
		// skip that letter 
	    } else {
		System.out.print(temp); 
	    }
	}
	System.out.println(); 
    } 
} 
Here's running it twice:
school.cs.indiana.edu%java Stenographer
Please type a line of text: Good evening, and welcome to Minneapolis!
Gd vnng, nd wlcm t Mnnpls!
school.cs.indiana.edu%java Stenographer
Please type a line of text: The Stenographer program works pretty well!
Th Stngrphr prgrm wrks prtty wll!
school.cs.indiana.edu%
Of course, you could change or enhance it in many ways, so go ahead and experiment with it!

Problem 8.

How do you read numbers separated by spaces on a line?

Use a StringTokenizer as in the text (page 247).

OK, let's take this in stages:

class Eight {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 

    } 
}
Now let's collect the lines of integers from the user:
class Eight {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line; 
	for (int i = 0; i < size; i++) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 

	} 
    } 
} 
And for each line let's split it into tokens:
import java.util.StringTokenizer; 

class Eight {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0; i < size; i++) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
	    } 
	} 
    } 
} 
Tokens are Strings, though, so we need to convert them.

import java.util.StringTokenizer; 

class Eight {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0, j = 0; i < size; i++, j = 0) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
		numbers[i][j] = Integer.parseInt(currentToken); 
		j = j + 1; 
	    } 
	} 
    } 
} 
And we print the array back:
import java.util.StringTokenizer; 

class Eight {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0, j = 0; i < size; i++, j = 0) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
		numbers[i][j] = Integer.parseInt(currentToken); 
		j = j + 1; 
	    } 
	} 
	for (int i = 0; i < numbers.length; i++) {
	    for (int j = 0; j < numbers[i].length; j++) {
		System.out.print(numbers[i][j] + " "); 
	    } 
	    System.out.println(); 
	}
    } 
}
Problem 9.

The code we start from is identical to the one above (minus the class's name).

import java.util.StringTokenizer; 

class Nine {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0, j = 0; i < size; i++, j = 0) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
		numbers[i][j] = Integer.parseInt(currentToken); 
		j = j + 1; 
	    } 
	} 
	for (int i = 0; i < numbers.length; i++) {
	    for (int j = 0; j < numbers[i].length; j++) {
		System.out.print(numbers[i][j] + " "); 
	    } 
	    System.out.println(); 
	}

    } 
} 
Reminder that the problem is on page 475, bottom. We need to answer a few questions. The first one is: did the user enter the right number of numbers (that is, size2)? The answer is that given the way we wrote it the program crashes if that is not the case.

The second question is whether each of the numbers from 1 to size2 occur exactly once? For this question we have two answers here, see below.

import java.util.StringTokenizer; 

class Nine {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0, j = 0; i < size; i++, j = 0) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
		numbers[i][j] = Integer.parseInt(currentToken); 
		j = j + 1; 
	    } 
	} 
	int[] counts = new int[size*size]; 
	for (int i = 0; i < numbers.length; i++) {
	    for (int j = 0; j < numbers[i].length; j++) {
		System.out.print(numbers[i][j] + " "); 
                counts[numbers[i][j] - 1] += 1; 
	    } 
	    System.out.println(); 
	}
	int product = 1; 
	for (int i = 0; i < size * size; i++) {
	    product *= counts[i]; 
	} 
	if (product != 1) {
	    System.out.println(
	      "Sorry, the numbers don't appear each exactly once"
            ); 
	    System.exit(0); 
	} 
    } 
} 
If the numbers are out of range the counts array gets out of bounds. If the numbers don't appear once and only once then product is not 1. So this second question is also taken care of. Which leaves us with the last question:

2. Are the sum of the rows, columns, and the two diagonals the same?

We calculate the sum of the elements in row 0 (zero) and then calculate all other sums of elements on the size rows, size columns, and the two diagonals. The first time such a sum differs from the sum of the elements in the first row (with index 0) we announce that the square is not a magic square. Otherwise (that is, if we never encounter this case) all the sums are equal, and the report is that the square is a magic square (see below).

import java.util.StringTokenizer; 

class Nine {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0, j = 0; i < size; i++, j = 0) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
		numbers[i][j] = Integer.parseInt(currentToken); 
		j = j + 1; 
	    } 
	} 
	int[] counts = new int[size*size]; 
	for (int i = 0; i < numbers.length; i++) {
	    for (int j = 0; j < numbers[i].length; j++) {
		System.out.print(numbers[i][j] + " "); 
                counts[numbers[i][j] - 1] += 1; 
	    } 
	    System.out.println(); 
	}
	int product = 1; 
	for (int i = 0; i < size * size; i++) {
	    product *= counts[i]; 
	} 
	if (product != 1) {
	    System.out.println(
	      "Sorry, the numbers don't appear each exactly once"
            ); 
	    System.exit(0); 
	} 
	int sum = 0; 
	for (int j = 0; j < numbers[0].length; j++) {
	    sum += numbers[0][j]; 
	} 
	int tempSum = 0; 
	for (int lin = 0; lin < size; lin++, tempSum = 0) {
	    for (int col = 0; col < size; col++) {
		tempSum += numbers[lin][col]; 
	    }
	    if (sum != tempSum) {
		System.out.println("Sorry, line " + lin + " does not match."); 
		System.exit(0); 
	    }
	} 
	tempSum = 0; 
	for (int col = 0; col < size; col++, tempSum = 0) {
	    for (int lin = 0; lin < size; lin++) {
		tempSum += numbers[lin][col];
	    } 
	    if (sum != tempSum) {
		System.out.println("Sorry, column " + col + " does not match."); 
		System.exit(0); 
	    }
	}
	System.out.println("Yes, this is a (" + size + "/" + size + 
			   ") magic square with a sum of: " + sum);
    } 
} 
The colors indicate the four different aspects of the computation: the sum of the first row (navyblue), checking all horizontal sums (blue), checking all vertical sums (green), and reporting that all is fine (brown) if none of the previous checks have stopped the program already. The program at this stage takes care of the rows and columns, so we need to calculate only two more sums: the diagonals.

import java.util.StringTokenizer; 

class Nine {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Please enter the size: "); 
	int size = console.readInt(); 
	int numbers[][] = new int[size][size]; 
	System.out.println("Please enter the " + size +
			   " rows of " + size + " numbers."); 
	String line, currentToken;
	StringTokenizer tokenizer;  
	for (int i = 0, j = 0; i < size; i++, j = 0) {
	    System.out.print(i + "> "); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    while (tokenizer.hasMoreTokens()) {
		currentToken = tokenizer.nextToken(); 
		numbers[i][j] = Integer.parseInt(currentToken); 
		j = j + 1; 
	    } 
	} 
	int[] counts = new int[size*size]; 
	for (int i = 0; i < numbers.length; i++) {
	    for (int j = 0; j < numbers[i].length; j++) {
		System.out.print(numbers[i][j] + " "); 
                counts[numbers[i][j] - 1] += 1; 
	    } 
	    System.out.println(); 
	}
	int product = 1; 
	for (int i = 0; i < size * size; i++) {
	    product *= counts[i]; 
	} 
	if (product != 1) {
	    System.out.println(
	      "Sorry, the numbers don't appear each exactly once"
            ); 
	    System.exit(0); 
	} 
	int sum = 0; 
	for (int j = 0; j < numbers[0].length; j++) {
	    sum += numbers[0][j]; 
	} 
	int tempSum = 0; 
	for (int lin = 0; lin < size; lin++, tempSum = 0) {
	    for (int col = 0; col < size; col++) {
		tempSum += numbers[lin][col]; 
	    }
	    if (sum != tempSum) {
		System.out.println("Sorry, line " + lin + " does not match."); 
		System.exit(0); 
	    }
	} 
	tempSum = 0; 
	for (int col = 0; col < size; col++, tempSum = 0) {
	    for (int lin = 0; lin < size; lin++) {
		tempSum += numbers[lin][col];
	    } 
	    if (sum != tempSum) {
		System.out.println("Sorry, column " + col + " does not match."); 
		System.exit(0); 
	    }
	}
	tempSum = 0; 
	for (int i = 0; i < size; i++) {
	    tempSum += numbers[i][i];
	} 
	if (sum != tempSum) {
	    System.out.println("Sorry, first diagonal does not match.");
	    System.exit(0);
	}
	tempSum = 0; 
	for (int i = 0; i < size; i++) {
	    tempSum += numbers[size-i-1][i];
	} 
	if (sum != tempSum) {
	    System.out.println("Sorry, second diagonal does not match.");
	    System.exit(0);
	}
	System.out.println("Yes, this is a (" + size + "/" + size + 
			   ") magic square with a sum of: " + sum);
    } 
} 
The program now looks very long.

But that's just because we do the same basic procedure over and over again.

Here's a test of it:

frilled.cs.indiana.edu%javac Nine.java
frilled.cs.indiana.edu%java Nine
Please enter the size: 4
Please enter the 4 rows of 4 numbers.
0> 16 3 2 13
1> 5 10 11 8
2> 9 6 7 12 
3> 4 15 14 1 
16 3 2 13 
5 10 11 8 
9 6 7 12 
4 15 14 1 
Yes, this is a (4/4) magic square with a sum of: 34
frilled.cs.indiana.edu%java Nine
Please enter the size: 1
Please enter the 1 rows of 1 numbers.
0> 1
1 
Yes, this is a (1/1) magic square with a sum of: 1
frilled.cs.indiana.edu%java Nine
Please enter the size: 2
Please enter the 2 rows of 2 numbers.
0> 1 4
1> 2 3
1 4 
2 3 
Sorry, column 0 does not match.
frilled.cs.indiana.edu%
This program was a very good practice program.

Problem 10.

Problem 11.

Problem 12.

Assume the array is coming from the command line.

class Twelve {
    public static void main(String[] args) {
	int[] a = new int[args.length]; 
	for (int i = 0; i < a.length; i++) {
	    a[i] = Integer.parseInt(args[i]); 
	} 
	for (int i = 0; i < a.length; i++) {
	    System.out.print(a[i] + " "); 
	} 
	System.out.println(); 
    } 
}
To remove the duplicates the easiest method involves using a companion value (as in section 11.1.3) and using one of the algorithms presented in section 11.3.3 (pages 445-447). I'll let you solve the problem that way, and instead I will provide here a solution that is more in the spirit of this week's homework assignment.
class Twelve {
    public static void main(String[] args) {
	int[] a = new int[args.length]; 
	for (int i = 0; i < a.length; i++) {
	    a[i] = Integer.parseInt(args[i]); 
	} 
	System.out.print("Before: ( "); 
	for (int i = 0; i < a.length; i++) {
	    System.out.print(a[i] + " "); 
	} 
	System.out.println(")"); 
	for (int i = 0; i < a.length; i++) {
	    if (countOccurrencesIn(a, a[i]) > 1) {
		a = removeElement(a, i); 
	    } // a points to a smaller and smaller array... 
	} 
	System.out.print("After:  ( "); 
	for (int i = 0; i < a.length; i++) {
	    System.out.print(a[i] + " "); 
	} 
	System.out.println(")"); 
    }
    static int countOccurrencesIn(int[] array, int value) {
	int count = 0; 
	for (int i = 0; i < array.length; i++) 
	    if (array[i] == value) 
		count += 1; 
	return count; 
    }
    static int[] removeElement(int[] array, int index) {
	int[] result = new int[array.length-1]; 
	for (int i = 0; i < index; i++) 
	    result[i] = array[i];
	for (int i = index; i < result.length; i++)
	    result[i] = array[i+1]; 
	return result; 
    } 
} 
Here's a sample session with this program:
frilled.cs.indiana.edu%java Twelve 
Before: ( )
After:  ( )
frilled.cs.indiana.edu%java Twelve 1 2 2 3
Before: ( 1 2 2 3 )
After:  ( 1 2 3 )
frilled.cs.indiana.edu%java Twelve 1 1 2 2 3 3 4 4 5 5 
Before: ( 1 1 2 2 3 3 4 4 5 5 )
After:  ( 1 2 3 4 5 )
frilled.cs.indiana.edu%java Twelve 5 4 3 2 1 2 3 4 5
Before: ( 5 4 3 2 1 2 3 4 5 )
After:  ( 4 2 1 3 5 )
frilled.cs.indiana.edu%
Hope you like it.

Problem 13.

R11.2, page 470: see problem 15, below.

Problem 14.

R11.3, page 470 in the text: we've done this in Problem 1, above.

Problem 15.

This, from my perspective, is a very attractive problem.

Here's my answer:

import java.util.Random; 

class Fifteen {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	boolean done = false; 
	do {
	    System.out.print("Enter number or 'quit'> "); 
	    String line = console.readLine(); 
	    if (line.equals("quit")) {
		done = true; 
	    } else {
		int size = Integer.parseInt(line); 
		int[] a = Fifteen.randomData(size, 100); 
		System.out.println("Array of random values between 0-100:"); 
		Fifteen.show(a); 
		System.out.println("The average is: " + Fifteen.average(a));
	    } 
	} while (! done); 
    } 
    static void show(int[] a) {
	for (int i = 0; i < a.length; i++) {
	    System.out.print(a[i] + " "); 
	} 
	System.out.println(); 
    }
    static int[] randomData(int length, int n) { // see page 444
	Random generator = new Random(); 
	int[] data = new int[length]; 
	for (int i = 0; i < data.length; i++) 
	    data[i] = generator.nextInt(n); 
	return data;
    }
    static double average(int[] data) { // almost like on page 443 
	double sum = 0; 
	for (int i = 0; i < data.length; i++) 
	    sum += data[i];
	return sum / data.length; 
    } 
}
This should also help you with the homework assignment.

Problem 16.

Problem R7.4, page 306: What's the output of the program?

I'll let you enter the code and practice with it.

Try to anticipate the results first, though (on paper) before you run the program.

Problem 17.

Section 6.5.4, page 251: Traversing the characters in a string.

We've used this in problem 7 (the stenographer program).

Problem 18.

Section 6.5.3, page 246: String tokenization.

We've used this in problem 7 (the stenographer program).

Notice that reading integers (with readInt) is a very brittle process: white space in input makes the program throw a formatting exception and the program crashes. Using a StringTokenizer eliminates the problem, as white space is accepted as a way of delimiting tokens (clearly identified now).

Problem 19.

Section 6.4 (pages 237-239): Nested loops.

We just add arrays.

class Nineteen {
    public static void main(String[] args) {
	int[][] table = new int[10][8]; 
	for (int x = 1; x <= 10; x++) {
	    for (int y = 1; y <= 8; y++) {
		table[x-1][y-1] = (int) Math.pow(x, y); 
	    } 
	} 

    } 
}
Printing the array would be immediate:
class Nineteen {
    public static void main(String[] args) {
	int[][] table = new int[10][8];
	for (int x = 1; x <= 10; x++) {
	    for (int y = 1; y <= 8; y++) {
		table[x-1][y-1] = (int) Math.pow(x, y);
	    }
	}
	for (int x = 1; x <= 10; x++) {
	    for (int y = 1; y <= 8; y++) {
		System.out.print(table[x-1][y-1] + " "); 
	    }
	    System.out.println(); 
	} 
    }
}
But let's make the printing a separate function:
class Nineteen {
    public static void main(String[] args) {
	int[][] table = new int[10][8];
	for (int x = 1; x <= 10; x++) {
	    for (int y = 1; y <= 8; y++) {
		table[x-1][y-1] = (int) Math.pow(x, y);
	    }
	}
	Nineteen.show(table); 
    }
    static void show(int[][] a) {
	for (int x = 1; x <= a.length; x++) {
	    for (int y = 1; y <= a[x-1].length; y++) {
		System.out.print(a[x-1][y-1] + " ");
	    }
	    System.out.println();
	}
    }
}
Be sure to spend a minute studying the program at this stage:

  1. The program is now more general: we can make as many changes as we need in show and that won't change the main method. Also, show works for any array, not just for an array of 10 rows and 8 columns.

  2. Getting the limits and index values right requires a moment of attention. Check them out. If you think this is easy (or immediate) then put these notes aside now and try to code this program yourself. That would give you the true measure of the level of accuracy needed.
As the book says, we finish by fixing the reporting to look nice:
class Nineteen {
    public static void main(String[] args) {
	int[][] table = new int[10][8];
	for (int x = 1; x <= 10; x++) {
	    for (int y = 1; y <= 8; y++) {
		table[x-1][y-1] = (int) Math.pow(x, y);
	    }
	}
	Nineteen.show(table); 
    }
    static void show(int[][] a) {
	final int COLUMN_WIDTH = 10; 

	for (int x = 1; x <= a.length; x++) {
	    for (int y = 1; y <= a[x-1].length; y++) {
		String ptsr; 
		for (ptsr = "" + a[x-1][y-1]; 
		     ptsr.length() < COLUMN_WIDTH; 
		     /* no iteration step is needed */ ) {
		    ptsr = " " + ptsr; 
		}
		System.out.print(ptsr); 
	    }
	    System.out.println();
	}
    }
}
And that looks much better.

Note that we use a for where the book uses a while.

Otherwise all's the same.

Problem 20.

Someone was asking me the other day in the redemption points minute papers: when do you use (realistically) an array of booleans? How out an electronic road sign? I'll leave it to you to implement this problem with an array of characters, and instead I'll use a square array of booleans to indicate where I should print a star and where I should print a space (on/off as in the use of a light bulb).

So let's look at a Z pattern:

class Twenty {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("We draw scalable Z's. Please enter size here: ");  
	int size = console.readInt(); 
	for (int lin = 0; lin < size; lin++) {
	    for (int col = 0; col < size; col++) {
		if (lin == 0 || lin == (size-1) || lin + col == (size - 1)) {
		    System.out.print(" *"); 
		} else {
		    System.out.print("  "); 
		} 
	    } 
	    System.out.println();
	} 
    }
}
Let's store this pattern as an array of on/off (or true/false values).

class Twenty {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("We draw scalable Z's. Please enter size here: ");  
	int size = console.readInt();
	boolean[][] onOff = new boolean[size][size];  
	for (int lin = 0; lin < size; lin++) {
	    for (int col = 0; col < size; col++) {
		if (lin == 0 || lin == (size-1) || lin + col == (size - 1)) {
		    // System.out.print(" *"); 
		    onOff[lin][col] = true; 
		} else {
		    // System.out.print("  "); 
		    onOff[lin][col] = false; 
		} 
	    } 
	    // System.out.println();
	} 
    }
}
Printing is done like in the preceding problem.

class Twenty {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("We draw scalable Z's. Please enter size here: ");  
	int size = console.readInt();
	boolean[][] onOff = new boolean[size][size];  
	for (int lin = 0; lin < size; lin++) {
	    for (int col = 0; col < size; col++) {
		if (lin == 0 || lin == (size-1) || lin + col == (size - 1)) {
		    onOff[lin][col] = true; 
		} else {
		    onOff[lin][col] = false; 
		} 
	    } 
	} 
	show(onOff); 
    }
    static void show(boolean[][] a) {
	for (int x = 1; x <= a.length; x++) {
	    for (int y = 1; y <= a[x-1].length; y++) {
		if (a[x-1][y-1]) {
		    System.out.print(" *");
		} else {
		    System.out.print("  ");
		}

	    }
	    System.out.println();
	}
    }
}
Let's clean the expressions for indices a bit:
class Twenty {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("We draw scalable Z's. Please enter size here: ");  
	int size = console.readInt();
	boolean[][] onOff = new boolean[size][size];  
	for (int lin = 0; lin < size; lin++) {
	    for (int col = 0; col < size; col++) {
		if (lin == 0 || lin == (size-1) || lin + col == (size - 1)) {
		    onOff[lin][col] = true; 
		} else {
		    onOff[lin][col] = false; 
		} 
	    } 
	} 
	show(onOff); 
    }
    static void show(boolean[][] a) {
	for (int i = 0; i < a.length; i++) {
	    for (int j = 0; j < a[i].length; j++) {
		if (a[i][j]) {
		    System.out.print(" *");
		} else {
		    System.out.print("  ");
		}

	    }
	    System.out.println();
	}
    }
}
And that's the end of it.

Problem 21.

Here's the simulation.

class Game {
    public static void main(String[] args) {
	System.out.println("Ladies and gentlemen, the Indiana Pacers!"); 
	Player croshere = new Player("Austin Croshere", 0, 3); 
	Player miller   = new Player("Reggie Miller", 2, 5); 
	Player jackson  = new Player("Mark Jackson", 7, 3); 
	Player rose     = new Player("Jalen Rose", 9, 2);
	Player mullin   = new Player("Chris Mullin", 9, 9); 
        Ball ball = new Ball(); 
	Basket basket = new Basket(20, 20); 
	jackson.hands = ball; 
	jackson.moves(1, 0); 
	miller.moves(-2, 4); 
	rose.moves(3, -2); 
	jackson.passTo(rose); 
	mullin.moves(3, 3); 
	croshere.moves(-1, 4); 
	rose.passTo(miller); 
	jackson.moves(3, 3); 
	miller.shootsTo(basket); 
	System.out.println("Audience erupts. (Courtesy the Indiana Pacers Sports Network). "); 
    } 
} 

class Player {
    private int x;
    private int y; 
    private String name; 
    Player (String name, int x, int y) {
	this.name = name; 
	this.x = x;
	this.y = y; 
	System.out.println("Player " + this.name + 
			   " at (" + this.x + ", " + this.y + ")"); 
    }
    Ball hands; 
    void passTo(Player other) {
	other.hands = this.hands;
	this.hands = null;
	System.out.println(this.name + " sending the ball to " + other.name); 
    } 
    void moves(int dX, int dY) {
	x = x + dX; 
	y = y + dY; 
	System.out.print(this.name + " moves to (" + 
                                     this.x + ", " + this.y + ")"); 
	if (hands != null) { System.out.println(" he has the ball."); }
        else { System.out.println(); } 
    }
    void shootsTo(Basket basket) {
	basket.inside = this.hands;
	this.hands = null; 
	System.out.println(this.name + " shoots... boooommm-baby!"); 
    }    
}

class Basket {
    Ball inside; 
    int x;
    int y;
    Basket(int x, int y) {
	this.x = x;
	this.y = y; 
    }
}

class Ball {

} 
I truly hope you like it. Here's how it goes:
frilled.cs.indiana.edu%java Game
Ladies and gentlemen, the Indiana Pacers!
Player Austin Croshere at (0, 3)
Player Reggie Miller at (2, 5)
Player Mark Jackson at (7, 3)
Player Jalen Rose at (9, 2)
Player Chris Mullin at (9, 9)
Mark Jackson moves to (8, 3) he has the ball.
Reggie Miller moves to (0, 9)
Jalen Rose moves to (12, 0)
Mark Jackson sending the ball to Jalen Rose
Chris Mullin moves to (12, 12)
Austin Croshere moves to (-1, 7)
Jalen Rose sending the ball to Reggie Miller
Mark Jackson moves to (11, 6)
Reggie Miller shoots... boooommm-baby!
Audience erupts. (Courtesy the Indiana Pacers Sports Network). 
frilled.cs.indiana.edu%
(It's like Babies and Sports in lecture notes 8 (eight)).

The rest of the problems will be posted here in a similar format by the end of the day today.


Last updated: Mar 25, 2001 by Adrian German for A201