| CSCI A201/A597Lecture Notes 5 Spring 2000 |
First I hope that this set of notes will show you that programming is as easy as planning a trip.
Second, I hope it will provide you with enough practice to become
well versed in control structures in Java, such as if
statements, and while, and for loops.
When we're done you should be just about ready to code everything in and turn it by the end of lab later this week as your Homework One assignment.
The 3x + 1 Function
The homework assignment revolves around a function (let's call it
f) which is defined on the set of strictly positive integers
(>= 1, that is) in the following way:
int f(int x) {
if (x % 2 == 0) { return 2 * x; }
else { return 3 * x + 1; }
}
Yes, this is new syntax for you, but it doesn't hurt to be exposed to
something new each time. This is the way in which we define methods in
Java. We're not going to use this today in any actual program, other
than to define the function f as a function that takes
odd numbers into 3 times the number plus 1 and even numbers into their
halves.
So given a certain number, x, if the number is even the
value that f(x) returns (or evaluates) is x/2.
Otherwise (the number is odd and) f(x) evaluates to:
3x + 1.
Let's try some examples:
f(5) evaluates to 16
f(2) evaluates to 1
f(27) evaluates to 82
f(1001) evaluates to 3004
f works.
The Iterative 3x + 1 Mapping
Now that we have f let's define the following process:
for any given positive and integer number x to iteratively
apply f to it means to compute
thenx1 = f(x)
thenx2 = f(x1)
thenx3 = f(x2)
thenx4 = f(x3)
and so on for ever, or until one of the computed values isx5 = f(x4)
1.
Let's say that after p steps xp
reaches 1. Then we call p the cost
of x as it is essentially equal to the number of steps
it takes to take x to 1 through the repeated
application of f.
Let's see some examples.
If we look at 3 then we have
f(3) is 10
f(10) is 5
f(5) is 16
f(16) is 8
f(8) is 4
f(4) is 2
f(2) is 1 at which point we need to stop.
3 is 7. Let's compute some more costs:
16 becomes 8, 4,
2, and 1 so its cost is 4
13 becomes
40,
20,
10,
5,
16,
8,
4,
2,
and finally 1 so its cost is 9
Now we should not forget that we are studying the
programming of computers in Java so the
question becomes: can we take advantage of that
and program one to compute the cost of
any number x through the iterative
3x + 1 mapping, instead of us doing
all the calculations by hand?
The answer is of course: yes.
The Flow Diagram
It looks like the whole process could be described like this:
Look at this flow diagram a little. Verify that it indeed matches your intuition and understanding about the process that we have described. Note the initialization step, in![]()
red; the conditions, or tests, marked in
blue. And the final question about the cost of the process... How do we count the steps?
What is the value of x at the end of the process?
Coding the Flow Diagram in Java
Here's a first draft:
public class Mapping {
public static void main(String[] args) {
int x = ...;
while (x != 1) {
if (x is even) {
x = x / 2;
} else {
x = 3 * x + 1;
}
}
// ... and the cost?
}
}
Let's add a counting aspect to the flow diagram.
So we enhance the source code:
public class Mapping {
public static void main(String[] args) {
int x = ...;
int count = 0;
while (x != 1) {
if (x is even) {
x = x / 2;
} else {
x = 3 * x + 1;
}
count = count + 1;
}
// ... and the cost?
System.out.print("The cost is: ");
System.out.println(count);
}
}
Now let's notice that: print followed by println
count at the end as the cost
x is lost
x in the beginning, or
We also note that
x % 2 == 0 returns true if and
only if x is even so we might as well use it where we want to
test whether x is even or not.
For the rest of this section we won't present any flow chart, and we will be working with the source code only and present subsequent refinements of it until we have the final product, that we can compile, and run, to test.
So our next version is able to compute the cost of x
while also reporting the value at the end of the iterative process,
as well.
public class Mapping {
public static void main(String[] args) {
int x = ...;
int originalValue = x;
int count = 0;
while (x != 1) {
if (x % 2 == 0) {
x = x / 2;
} else {
x = 3 * x + 1;
}
count = count + 1;
}
System.out.print("The cost of ");
System.out.print(originalValue);
System.out.print("is: ");
System.out.println(count);
}
}
But how do we initialize x? Command Line Arguments
To run a Java program you need to create a .class file
with javac. You then use java to run it. In
our case for the Mapping program we'd have the following:
followed byjavac Mapping.java
Now the news is that if you type a sequence of strings on this last command line following the name of the class Java is willing to collect them in an array (or ordered collection) of strings and pass it to your program'sjava Mapping
main method.
So all you need to clarify is how you can get to these strings to
use them.
The secret is that they will be numbered starting from 0
and they will be available in args[0], args[1],
and so on, depending on how many we typed.
So if we type the following:
the three strings will be available for us insidejava Mapping john adrian susan
main as
follows:
args[0] contains "john"
args[1] contains "adrian"
args[2] contains "susan"
main
(as we've been doing so far) Java still prepares them for us as described
above. Another example, if we type:
then inside the programjava Mapping a aa aaa a
args[0] contains "a"
args[1] contains "aa"
args[3] contains "aaa"
args[4] contains "a"
then inside the programjava Mapping 123
args[0] contains "123"
thenjava Mapping
args is empty.
For our purpose (initializing the x to compute
the cost of the iterative mapping on it) typing the number of
interest on the command line like this:
would be what we want.java Mapping 10
To get it we need only look into args[0].
To use it as an int though, we need to convert it from
the String representation that it currently is in.
We do that using a function parseInt from the
Integer class. (Using it is just like using the
println method from System.out)
Therefore the program becomes:
public class Mapping {
public static void main(String[] args) {
int x = Integer.parseInt(args[0]);
int originalValue = x;
int count = 0;
while (x != 1) {
if (x % 2 == 0) {
x = x / 2;
} else {
x = 3 * x + 1;
}
count = count + 1;
}
System.out.print("The cost of ");
System.out.print(originalValue);
System.out.print("is: ");
System.out.println(count);
}
}
You know how to run this program, you've seen it being run in lab notes 2. Here's an example on Unix:
So as you can see the output of the program can be improved a tiny little bit.frilled.cs.indiana.edu%javac Mapping.java frilled.cs.indiana.edu%java Mapping 3 The cost of 3is: 7 frilled.cs.indiana.edu%java Mapping 16 The cost of 16is: 4 frilled.cs.indiana.edu%java Mapping 13 The cost of 13is: 9 frilled.cs.indiana.edu%
Comments
We've used // to write comments in the program.
The text that follows a double slash to the end of the line is ignored by the compiler, so it's as if it didn't exist for Java. It can be used however to write down comments that will help programmers to make sense out of your source code.
Sweeping a Range of Numbers
Let's say that given x we can compute the cost of x and print it.
The homework asks you to be able to sweep a whole range of numbers and print each one's cost.
This could be easily achieved using a for loop.
public class Syracuse {
public static void main(String[] args) {
int startingValue = ...;
int endingValue = ...;
for (int x = startingValue; x <= endingValue; x += 1) {
... compute and report the cost of x as before
}
}
}
We should obviously be getting the values for the border of the range from the command line:
public class Syracuse {
public static void main(String[] args) {
int startingValue = Integer.parseInt(args[0]);
int endingValue = Integer.parseInt(args[1]);
for (int x = startingValue; x <= endingValue; x += 1) {
// ... compute the cost of x as before
int originalValue = x;
int count = 0;
while (x != 1) {
if (x % 2 == 0) {
x = x / 2;
} else {
x = 3 * x + 1;
}
count = count + 1;
}
System.out.print("The cost of ");
System.out.print(originalValue);
System.out.print(" is: ");
System.out.println(count);
}
}
}
Note that the program above is almost correct. What's missing?
(It is important to restore the value of x to the originalValue for the
iteration so that it can be incremented by one to obtain a new number, the next number in the range.)
Finishing the Program
As we get ready to finish this assignment we need to add one more feature to this program. It is supposed to also report the number with the highest cost in the range and its cost.
What do you think about this flow diagram?
Is it going to work?
Can you code it in Java?
How can we enhance it to report the number as well, rather than just the maximum cost in the range?
The answer will be given in class today.