CSCI A201/A597

Lecture Notes Seventeen

Second Summer 2000


Problem set six.
Here's a program that helps with problem 1. What does it do?

Reads lines, one by one. When does it end?

When you type Control-D. Which is EOF (end of file).

Yes, in that case the line is null. What does it do, line by line?

Looks at the tokens, and prints them in uppercase. Let's see the program.

Here it is:
import java.util.*;
import java.io.*; 

/* pages 239 - 241 and 246 - 250 */ 

class One {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Hello>"); 
        String line = console.readLine(); 
        while (line != null) { // ^D would do it 
	    StringTokenizer tokenizer = new StringTokenizer(line); 
            while (tokenizer.hasMoreTokens()) {
		String token = tokenizer.nextToken(); 
		System.out.println(token.toUpperCase()); 
	    } 
            System.out.print("Hello>"); 
            line = console.readLine(); // what if we take this out? 
        }
	System.out.println("End of program.");
    } 
} 

class ConsoleReader { 
    public ConsoleReader(InputStream inStream) { 
        reader = new BufferedReader(
                   new InputStreamReader(
                     inStream));     
    }
    public String readLine() { 
        String inputLine = "";
        try {
            inputLine = reader.readLine(); 
        } catch (IOException e) {
            System.out.println(e); 
            System.exit(1); 
        } 
        return inputLine; 
    }
    public int readInt() { 
        String inputString = readLine(); 
        int n = Integer.parseInt(inputString); 
        return n; 
    }
    public double readDouble() { 
        String inputString = readLine(); 
        double x = Double.parseDouble(inputString); 
        return x; 
    } 
    private BufferedReader reader; 
}
Looks good.

For both problem 2 and 3 the trick is to interpret input. I think I can demo that.

You're going to read a rate, then numbers, finished by zero... ... then numbers again, finishing everything with EOF.

Which is Control-D. I could even end it with a keyword, such as "quit" or "bye", or some other meaningful word.

Really, how?
Take a look.
import java.util.*;
import java.io.*; 

class TwoAndThree {
    public static void main(String[] args) {
	ConsoleReader console = new ConsoleReader(System.in); 
	System.out.print("Rate>"); 
	String line = console.readLine(); 
	StringTokenizer tokenizer = new StringTokenizer(line); 
	double rate = Double.parseDouble(tokenizer.nextToken()); 
	double amount; 
	do {
	    System.out.print("Dollars>"); 
	    line = console.readLine(); 
	    tokenizer = new StringTokenizer(line); 
	    amount = Double.parseDouble(tokenizer.nextToken()); 
	} while (amount > 0); 
	do {
	    System.out.print("Euros>"); 
	    line = console.readLine(); 
	    if (line == null || line.equalsIgnoreCase("quit")) 
		break; 
	    tokenizer = new StringTokenizer(line); 
	    amount = Double.parseDouble(tokenizer.nextToken()); 
	} while (true); 
	System.out.println("Thank you for using this program."); 
    } 
} 

class ConsoleReader { 
    public ConsoleReader(InputStream inStream) { 
        reader = new BufferedReader(
                   new InputStreamReader(
                     inStream));     
    }
    public String readLine() { 
        String inputLine = "";
        try {
            inputLine = reader.readLine(); 
        } catch (IOException e) {
            System.out.println(e); 
            System.exit(1); 
        } 
        return inputLine; 
    }
    public int readInt() { 
        String inputString = readLine(); 
        int n = Integer.parseInt(inputString); 
        return n; 
    }
    public double readDouble() { 
        String inputString = readLine(); 
        double x = Double.parseDouble(inputString); 
        return x; 
    } 
    private BufferedReader reader; 
}

I see that you're assuming the user will never type more than one number on a line. Also, my error checking is minimal: the program ends with EOF, or by typing "quit", but otherwise the user is expected to type numbers.

There are many ways of solving problem 4. Yes, but empathy would not be one of them.

Of course. What I meant was that you need to generate random directions. And you have more than one way to produce random numbers.

Let's use whatever the book uses. It's a good book.

I know. Page 253.

In addition to that I want to use an object oriented approach. And bring a drunkard into the picture.

Exactly. A drunkard is like a BankAccount.

I was going to say.
Well, here's my program.
import java.util.*;

class Drunkard {
    int x, y; 
    Drunkard(int x, int y) {
	this.x = x; 
	this.y = y;
    } 
    void moveNorth() {
	this.y -= 1; 
    }
    void moveEast() {
	this.x += 1; 
    }
    void report() {
	System.out.println("Hiccup: " + x + ", " + y); 
    } 
} 

class Four {
    public static void main(String[] args) {
	Random generator = new Random(); 
	Drunkard drunkard = new Drunkard(100, 100); 
	int direction; 
	for (int i = 0; i < 100; i++) {
	    direction = Math.abs(generator.nextInt()) % 4; 
	    if        (direction == 0) { // N
		drunkard.moveNorth();
	    } else if (direction == 1) { // E
		drunkard.moveEast(); 
	    } else if (direction == 2) { // S
		System.out.println("Should move South."); 
	    } else if (direction == 3) { // W
		System.out.println("Should move West."); 
	    } else {
		System.out.println("Impossible!"); 
	    } 
	    drunkard.report(); 
	} 
    }
} 


Not bad at all. Now let's look at 5 and 6.

Isn't a cannonball like a drunkard? Yes, they're both tiggers.

They all deal directly with gravitational fields.
Cannonballs require more physics, though.
class Cannonball {
    double x; 
    double y; 
    double vx; 
    double vy;
    final double g = 9.81; 

    Cannonball(double speed, double angle) {
	x = 0; 
	y = 0; 
	vx = Math.cos(angle) * speed; 
	vy = Math.sin(angle) * speed; 
    } 

    void move() {
	double deltaT = 0.01; 
	x += vx * deltaT;
	y += vy * deltaT; 
	vy -= g * deltaT;
    }

    void report() {
	System.out.println("Located at: (" + x + ", " + y + ")"); 
    }

    double height() {
	return y; 
    } 

}

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

	Cannonball c = new Cannonball(10, Math.PI / 4);

	for (int i = 0; i < 10 * 100; i++) { // flying 10 seconds 

	    c.move(); 
	    c.report(); 

	    if (c.height() < 0) {
		System.out.println("The cannonball landed!"); 
		break; 
	    } 

	}

    }
}

Could you also compute the highest point the cannonball gets to? That would almost be problem 16, wouldn't it?

Yes. We'd have to update our notion of a current maximum every time we are looking at a height.

Come to think of it the cannonball could do it. Intelligent cannonball.

Intelligent, but misguided. Well, here it is anyway:
class Cannonball {
    double x; 
    double y; 
    double vx; 
    double vy;
    final double g = 9.81; 

    double max; 

    Cannonball(double speed, double angle) {
	x = 0; 
	y = 0; 
	vx = Math.cos(angle) * speed; 
	vy = Math.sin(angle) * speed; 

	max = 0; 

    } 

    void move() {
	double deltaT = 0.01; 
	x += vx * deltaT;
	y += vy * deltaT; 
	vy -= g * deltaT;

	if (y > max) { max = y; } 
    }

    void report() {
	System.out.println("Located at: (" + x + ", " + y + ") "); 

        System.out.println("     max altitude so far: " + max); 

    }

    double height() {
	return y; 
    } 

}

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

	Cannonball c = new Cannonball(10, Math.PI / 4);

	for (int i = 0; i < 10 * 100; i++) { // flying 10 seconds 

	    c.move(); 
	    c.report(); 

	    if (c.height() < 0) {
		System.out.println("The cannonball landed!"); 
		break; 
	    } 

	}

    }
}

You just added three lines? Yes, that was all.

But how often do those get executed? They're part of the cannonball's movement.

Let's move on to problem 7. This one is easy.

Yes, starting with two values we compute a third. Now only this new value and the most recent of the two it was computed from should be kept.

And these two values are then added to compute a new value. And the whole process is repeated, as follows:
	
for (int i = 3; i <= n; i++) {    
  fnew = fold + folder; 
  folder = fold; 
  fold = fnew; 
} 

Yes, that's it. This reminds me of another problem:

What problem is that? See if you can figure it for yourself.
import java.io.*; 

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

	ConsoleReader console = new ConsoleReader(System.in);
	System.out.print("Pass the salt please: "); 
	double a = console.readDouble(); 
	System.out.print("And the butter: "); 
	int n = console.readInt(); 

	double xold, xnew; 

	xold = ... ; 

	do {

	  xnew = xold - (Math.pow(xold, n) - a) / (n * Math.pow(xold, n - 1));

	  xold = xnew; 

	  System.out.println("     " + (Math.pow(xnew, n) - a)); 

	} while (Math.abs(Math.pow(xnew, n) - a) > 0.001); 

	System.out.println(xnew); 

	System.out.println(Math.pow(xnew, n) + " " + a); 

        System.out.println("Thank you!"); 

    } 
} 

I think I know what problem it is, but what's ...? It doesn't matter, if it has a value.

For this problem, at least... Problems 9, 10, and 15 are easy.

Yes, let's do number 10. OK, but I won't draw the circles, I will just create them.

Drunkards, circles, cannonbals: they're all the same.
Especially drunkards. Here's the code:
import java.awt.*; 
import java.awt.geom.*;
import javax.swing.*; 
import java.util.*; 

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

	String input = JOptionPane.showInputDialog("Enter number: "); 
	int n = Integer.parseInt(input); 

	System.out.println("Generating " + n + " circles.");

	Random generator = new Random(); 

	for (int i = 0; i < n; i++) {

	    int x = 100 + Math.abs(generator.nextInt()) % 200; 
	    int y = 100 + Math.abs(generator.nextInt()) % 200; 

	    int r = 10 + Math.abs(generator.nextInt()) % 40;

	    Ellipse2D.Double e = new Ellipse2D.Double(x, y, r, r); 

	    System.out.println(e); // looks better when you draw it

	} 

	System.exit(0); 

    }
}

Why is 15 easy? Because it's like 10, and in addition you have complete information about the position of the squares.

Why is 15 hard? Because you should come up with a formula for the position of a square given its row and column (or line and column).

This way you can use a for loop for the lines, ... and another one for the columns.

One, ... ... inside each other.

And why is 9 easy? Because you just have to compute two sums, and take a square root at the end.

Why is 9 hard? 9 is not hard, but you have to read the problem carefully and use the right formula.

Which is the last one. The last one for today anyway.

We'll do 12, 13, and 17-21 tomorrow. I can hardly wait.

Last updated: July 18, 2000 by Adrian German for A201