|
Second Summer 2002
|
Lecture Notes Thirteen: More practice with loops.
Loops, tokenizers, and Monte Carlo problems.
Do you like loops?
|
I don't know: so far, so good.
|
Now we need to move on.
|
First a few simple, basic exercises.
|
Can you explain this?
|
I sure can.
|
frilled.cs.indiana.edu%cat Two.java
class Two {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.print(i);
}
i = 10;
System.out.println(i);
}
}
frilled.cs.indiana.edu%javac Two.java
Two.java:6: Undefined variable: i
i = 10;
^
Two.java:7: Undefined variable: i
System.out.println(i);
^
2 errors
frilled.cs.indiana.edu%
Can you fix it?
|
I sure can.
|
frilled.cs.indiana.edu%cat Two.java
class Two {
public static void main(String[] args) {
int i;
for (i = 0; i < 10; i++) {
System.out.print(i);
}
i = 10;
System.out.println(i);
}
}
frilled.cs.indiana.edu%javac Two.java
frilled.cs.indiana.edu%java Two
012345678910
frilled.cs.indiana.edu%
How do you call that?
|
I'd say: scope of a variable.
|
frilled.cs.indiana.edu%webster scope
scope \'sko^-p\ n
[It scopo purpose, goal, fr. Gk skopos; akin to Gk skeptesthai to
watch, look at -- more at SPY]
(1555)
1: space or opportunity for unhampered motion, activity, or thought
2: INTENTION, OBJECT
3: extent of treatment, activity, or influence
4: range of operation
syn see RANGE
frilled.cs.indiana.edu%
Sounds good.
|
It's the range of operation for that variable.
|
Take a look at this:
|
It doesn't compile!
|
class Wow {
public static void main(String[] args) {
{
int i;
i = 3;
System.out.println(i);
}
System.out.println(i);
}
}
Indeed, they are defining the scope.
|
And they do it in the same way for:
-
class es
-
if statements
-
for loops
-
while loops
|
As well as other kinds of loops.
|
There's just one more, as we will see below.
|
In any event, having blocks of statements available as standalone
entities that can be placed anywhere inside the program can sometimes
be a source of confusion for the beggining Java programmer.
|
Let me see some examples.
|
Here's one:
|
That is not a source of any confusion!
|
frilled.cs.indiana.edu%cat Wow.java
class Wow {
public static void main(String[] args) {
int x = 1;
if (x > 2) {
System.out.println("Yes, " + x + " is greater than 2.");
}
}
}
frilled.cs.indiana.edu%javac Wow.java
frilled.cs.indiana.edu%java Wow
frilled.cs.indiana.edu%
I know, but consider this:
|
Ah, I see the semicolon!
|
frilled.cs.indiana.edu%cat Wow.java
class Wow {
public static void main(String[] args) {
int x = 1;
if (x > 2) ; {
System.out.println("Yes, " + x + " is greater than 2.");
}
}
}
frilled.cs.indiana.edu%javac Wow.java
frilled.cs.indiana.edu%java Wow
Yes, 1 is greater than 2.
frilled.cs.indiana.edu%
I hope you do.
|
That is an if with an empty body.
|
That's how we got an infinite loop last time.
|
There's one thing to be learned from this.
|
Syntax rules.
|
And people who use it properly, rock!
|
Let's look at other kind of loops.
|
OK, here's a program that talks to the user.
|
frilled.cs.indiana.edu%cat Three.java
class Three {
public static void main(String[] args) {
ConsoleReader c = new ConsoleReader(System.in);
String line;
do {
System.out.print("Type something: ");
line = c.readLine();
System.out.println("You typed: " + line);
} while (! line.equals("bye"));
System.out.println("Good bye!");
}
}
frilled.cs.indiana.edu%javac Three.java
frilled.cs.indiana.edu%java Three
Type something: I am here
You typed: I am here
Type something: You are there
You typed: You are there
Type something: Your name is Echo
You typed: Your name is Echo
Type something: Bye
You typed: Bye
Type something: bye
You typed: bye
Good bye!
frilled.cs.indiana.edu%
Using while is just a bit longer.
|
Yes, since the test comes first.
|
frilled.cs.indiana.edu%cat Three.java
class Three {
public static void main(String[] args) {
ConsoleReader c = new ConsoleReader(System.in);
String line;
System.out.print("Type something: ");
line = c.readLine();
System.out.println("You typed: " + line);
while (! line.equals("bye")) {
System.out.print("Type something: ");
line = c.readLine();
System.out.println("You typed: " + line);
}
System.out.println("Good bye!");
}
}
frilled.cs.indiana.edu%javac Three.java
frilled.cs.indiana.edu%java Three
Type something: Works the same, doesn't it?
You typed: Works the same, doesn't it?
Type something: It does seem so.
You typed: It does seem so.
Type something: I am happy.
You typed: I am happy.
Type something: BYe
You typed: BYe
Type something: byE
You typed: byE
Type something: bye
You typed: bye
Good bye!
frilled.cs.indiana.edu%
In both cases we work with whole loops.
|
Yes, we know we're done either at the beginning or
at the end of the loop's body of statements.
|
Sometimes we'd like to allow for being able to
realize we're done halfway through the loop.
|
And end your processing in mid-loop? Doesn't
this coding situation have a specific name?
|
Yes, it's called the loop and a half problem.
|
Very good. Here's an example: A program
that reads lines from a file, then reverses them.
|
frilled.cs.indiana.edu%cat Four.java
class Four {
public static void main(String[] args) {
ConsoleReader c = new ConsoleReader(System.in);
boolean done = false;
String line;
while (! done) {
System.out.print("Echo> ");
line = c.readLine();
if (line == null) { // EOF or ctrl-D for that
done = true;
} else {
System.out.println(line);
}
}
}
}
frilled.cs.indiana.edu%javac Four.java
frilled.cs.indiana.edu%java Four
Echo> Hello!
Hello!
Echo> I am here.
I am here.
Echo> How are you?
How are you?
Echo> I am fine, how about you?
I am fine, how about you?
Echo> You don't say...
You don't say...
Echo> I am going to type control-D now
I am going to type control-D now
Echo> Bye!
Bye!
Echo> frilled.cs.indiana.edu%
Where's the file?
|
You can pipe one into your program! (See your friendly TA
or check with the book on pages 248 and 241 for more details).
|
Alright. So we read lines, one by one. When the line
we read is empty there's nothing to be reversed. So the
program simply quits the loop.
|
Oh, I see: and we skip the lower half of the loop.
|
Indeed, at that point we simply quit it.
|
How do you do that?
|
One can do that with break (page 242), or...
|
... using a boolean variable, and an if statement.
|
We choose the second approach, because one can argue it's
a bit more structured.
|
But the first one is also often used,
and it greatly simplifies code on occasion.
|
So now we have a basic echo program.
|
Yes, but as of right now nothing is being
reversed. Wasn't that what we set out to do?
|
OK, let's make this more exciting, as if
through a looking glass.
|
Yes, s'tel esrever sretcarahc ni sdrow!
|
Well, yletanutrofnu ew t'nac od taht.
|
?neht ,elbissop si siht spahrep tuB
|
frilled.cs.indiana.edu%cat Four.java
class Four {
public static void main(String[] args) {
ConsoleReader c = new ConsoleReader(System.in);
boolean done = false;
String line;
while (! done) {
System.out.print("Echo> ");
line = c.readLine();
if (line == null) { // EOF or ctrl-D for that
done = true;
} else {
String rev = "";
int i;
for (i = line.length() - 1; i >= 0; i--) {
rev += line.charAt(i);
}
System.out.println(rev);
}
}
}
}
frilled.cs.indiana.edu%javac Four.java
frilled.cs.indiana.edu%java Four
Echo> Hello!
!olleH
Echo> I say, that's Spanish.
.hsinapS s'taht ,yas I
Echo> Arabic?
?cibarA
Echo> What's going on, can you please tell me.
.em llet esaelp uoy nac ,no gniog s'tahW
Echo> Hmmm...
...mmmH
Echo> :-)
)-:
Echo> ...ees I
I see...
Echo> .ahctoG
Gotcha.
Echo> frilled.cs.indiana.edu%
I like this guy, Gotcha.
|
Once upon a time there was a Polish carpenter, by the name of
Zbigniew Gotcha, who lived in Kracow. You know the story?
|
No.
|
I don't either, but I like the way it starts.
|
Time to wrap up.
|
Let's do random numbers.
|
Yes, we kept for dessert.
|
Do you like sherbet?
|
Let's program the following simulation:
|
|
Darts are thrown at random points onto the square with corners
(1 ,1) and (-1, -1). If the dart lands inside the unit
circle, that is, the circle with center (0, 0) and radius 1 it is
a hit. Otherwise it is a miss. Run this simulation to determine
an experimental value for the fraction of hits in the total number
of attempts, multiplied by 4.
|
Oh, this is so easy! Easy as !
|
Fine, if it's easy, why don't you do it first?
|
Relax, here it is:
|
frilled.cs.indiana.edu%cat Pi.java
import java.util.Random;
public class Pi {
public static void main(String[] args) {
Random r = new Random();
double x, y, d;
int i, count = 0;
for (i=0; i < 100000 ; i++) {
x = r.nextDouble() * 2 - 1;
y = r.nextDouble() * 2 - 1;
d = Math.sqrt(x * x + y * y);
if (d < 1) count++;
}
System.out.println("Pi is approximately " + 4.0 * count / i);
}
}
frilled.cs.indiana.edu%javac Pi.java
frilled.cs.indiana.edu%java Pi
Pi is approximately 3.13648
frilled.cs.indiana.edu%java Pi
Pi is approximately 3.15064
frilled.cs.indiana.edu%java Pi
Pi is approximately 3.14424
frilled.cs.indiana.edu%java Pi
Pi is approximately 3.1422
frilled.cs.indiana.edu%java Pi
Pi is approximately 3.1438
frilled.cs.indiana.edu%
Can you explain it?
|
The probability of a hit is the fraction that the circle
represents of the total area.
|
It is also close to the ratio of the measured frequencies:
hits divided by attempts.
|
So we write the formulas, and the radius
simplifies, as it appears on both sides.
|
But there is a factor of half (1/2)
which...
|
... is squared, so it participates as a fourth
(1/4) in the end, and there
you have it.
|
Pretty good.
|
I want to do more problems.
|
I was hoping you would.
|
I'm in great shape today.
|
Here's a program that helps with problem 6.1
|
|
import java.util.*;
import java.io.*;
/* pages 239 - 241 and 246 - 250 */
class Six {
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.");
}
}
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
back, but converted into uppercase.
|
Not much different from the one about Zbigniew,
except this one uses this StringTokenizer .
|
Exactly, that's the main difference.
|
How does that work?
|
StringTokenizer tokenizer = new StringTokenizer(line);
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
System.out.println(token.toUpperCase());
}
|
Better look this class up.
|
It's like a machine gun loaded with words.
|
Or like a stapler, if you don't mind.
|
A stapler would also be a good analogy.
|
With staples of variable length.
|
Glued together by blank spaces.
|
Staples are tokens.
|
frilled.cs.indiana.edu%webster token
to-ken \'to^--ken\ n
[ME, fr. OE ta^-cen, ta^-cn sign, token; akin to OHG zeihhan sign, Gk
deiknynai to show -- more at DICTION]
(bef. 12c)
1: an outward sign or expression
2a: SYMBOL, EMBLEM <a white flag is a token of surrender>
2b: an instance of a linguistic expression
3: a distinguishing feature: CHARACTERISTIC
[...]
frilled.cs.indiana.edu%
For both problem 6.2 and 6.3 the trick is to
interpret (read and promptly evaluate) input.
|
I think I can handle that.
|
You're going to have to read
- a rate,
- then numbers,
- finished by zero...
... then numbers again, ending with EOF.
|
Which is Control-D (in Unix).
|
Or some such thing.
|
I
could even end it with a keyword, such as "quit " or "bye ",
or some other meaningful word.
|
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.");
}
}
|
This should get you started.
|
Nice, but I see that you're assuming the user will never type
more than one number on a line.
|
So I could get by without a tokenizer. I
agree, but I used one for the sake of practice.
|
I have a larger set of problems for next time.
|
Can't wait. Let's press on with the ones for today.
Next one up: problem 6.4, page 263.
|
There are many ways of solving problem 6.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.
|
In addition to that, I would like to use an object oriented approach.
|
And bring a drunkard into the picture.
|
Exactly.
|
A drunkard is like a BankAccount .
|
|
Well, here's how I'd get started.
|
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.
|
Of course, one needs to finish it first.
|
Reminds me of homework assignment two.
|
Somewhat. Now let's look at 6.5 and 6.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("SPLOOOF! The cannonball landed!");
break;
}
}
}
}
Homework assignment one!
|
Almost, only in finer steps.
|
Could you also compute the highest point that the cannonball gets to?
|
That would almost be problem 16, wouldn't it?
|
It would.
|
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?
|
Four, and 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 6.7.
|
This one is easy.
|
Yes, from two values we compute a third. And we keep
doing this over and over again.
|
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!");
}
}
P6.14 perhaps? But what's the ... ?
|
It doesn't matter, if it has a value.
|
For this problem, at least.
|
Problems 6.9, 6.10, and 6.15 are easy,
although for 10 and 15 we need to wait until
we look at applets to do any graphics.
|
Let's do number 10.
|
OK, but I won't draw circles, I'll just create them.
|
Drunkards, circles, cannonbals: they're all the same.
|
|
|
Especially drunkards.
Here's the code:
|
import java.util.*;
class Ten {
public static void main(String[] args) {
System.out.print("Enter number of circles: ");
ConsoleReader console = new ConsoleReader(System.in);
int n = console.readInt();
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;
Circle e = new Circle(x, y, r);
System.out.println(e); // looks better when you draw it
}
System.exit(0);
}
}
class Circle {
double xCenter, yCenter, radius;
Circle (double x, double y, double r) {
xCenter = x;
yCenter = y;
radius = r;
}
public String toString() {
return "I am a circle at: (" +
xCenter + ", " + yCenter +
") with a radius of " +
radius;
}
}
Why is 6.15 easy?
|
Because it's like 10, and in addition you have complete information
about the position of the squares. You'll see, later.
|
Why is 6.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.
|
Like for the patterns we developed last week.
|
And why is 6.9 easy?
|
Because you just have to compute two sums, and take
a square root at the end.
|
Why is 6.9 hard?
|
6.9 is not hard, but you have to read the problem carefully and use the right formula.
|
Which is the last one (second of two).
|
The last one for today anyway.
|
We'll do a lot more next time.
|
As always, I can hardly wait.
|
Here's another approach to producing random numbers.
Say we need random numbers between a
, and b
,
where a
is less than b
. Let y
be
such a random number. Then we can calculate how far into the segment
y
is, as a percentage.
double p = (y - a) / (b - a); // [1]
Since y
is random that means p
can be anywhere
between 0
and 1
.
Well, such numbers can be generated with Math.random()
.
So, let's turn [1]
on its head, to obtain y
as a
function of p
.
Then, we have:
y = p * (b - a) + a;
Now replace p
by Math.random()
:
y = (b - a) * Math.random() + a;
Same as stretching followed by a translation.
End of story.
Last updated: Jun 16, 2002 by Adrian German for A201