Visit the collatz-conjecture exercise on Exercism to read the full instructions and download the exercise files.
Dig Deeper
while loop
while loop
class CollatzCalculator {
int computeStepCount(int start) {
if (start < 1) {
throw new IllegalArgumentException("Only positive integers are allowed");
}
int steps = 0;
while (start > 1) {
if ((start & 1) == 1) {
start = start * 3 + 1;
} else {
start >>= 1;
}
steps++;
}
return steps;
}
}
This approach defines a steps variable initialized to 0 that will be incremented for each iteration of the while loop.
The while loop iterates as long as the input number is greater than 1.
If the number is already 1 before control flow gets to the while loop, then the while loop won’t run.
Bitwise operators are used to check if the number is odd and to divide it in half if it is even.
The bitwise AND operator (&) compares the number with 1 to see if it is odd.
Another way to go about checking if the number is even or odd is to see if it is evenly divided by `2`
by using the [modulo (also know as the remainder) operator](https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/).
So, to see if it is even we could use `if (start % 2 == 0)`.
That might be slightly less performant but perhaps more readable for intent, especially for those who don't "speak binary".
If the number is even, then the right shift equals operator (>>=) shifts all of the bits once to the right, which is the equivalent
of dividing the number by 2.
Another way would be to use the division equals operator start \= 2 which might be slighly less performant but more readable
for intent, especially for those who don’t “speak binary”.
After the condition for the while loop is satisifed, it ends and the value of steps is returned.
IntStream.iterate()
IntStream.iterate()
import java.util.stream.IntStream;
class CollatzCalculator {
long computeStepCount(int start) {
if (start < 1) {
throw new IllegalArgumentException("Only positive integers are allowed");
}
return IntStream.iterate(start, num -> num != 1, num -> (num & 1) == 1 ? 3 * num + 1 : num >> 1).count();
}
}
This approach starts by importing from packages for what is needed.
The real work begins by calling the IntStream.iterate() method which is passed the input number
as the initial element.
Before each iteration a lambda is used to check if the input number is not the value of 1.
If the value is not 1, the iteration runs.
If the value is 1, then all iteration stops.
Another lambda is used to process the input number.
Bitwise operators are used to check if the number is odd and to divide it in half if it is even.
The bitwise AND operator (&) compares the number with 1 to see if it is odd.
Another way to go about checking if the number is even or odd is to see if it is evenly divided by `2`
by using the [modulo (also know as the remainder) operator](https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/).
So, to see if it is even we could use `start % 2 == 0`.
That might be slightly less performant but perhaps more readable for intent, especially for those who don't "speak binary".
If the number is even, then the right shift operator (>>) shifts all of the bits once to the right, which is the equivalent
of dividing the number by 2.
Another way would be to use the division operator start \ 2 which might be slighly less performant but more readable
for intent, especially for those who don’t “speak binary”.
When the input number is the value of 1, then the count() method is called to count the number of iteratons for the
IntStream.
The function returns the result of the count() method.
Source: Exercism java/collatz-conjecture