patternjavaMinor
The 3n + 1 algorithm for a range
Viewed 0 times
algorithmrangethefor
Problem
Essentially the Collatz Conjecture.
Challenge requirements are here.
And here is my implementation in Java:
and the test class:
Any feedback is welcome.
Challenge requirements are here.
And here is my implementation in Java:
/* User: koray@tugay.biz Date: 21/03/15 Time: 19:40 */
public class ThreeNOneForRangeSolver {
public int solveFor(int inputOne, int inputTwo) {
int maximumCycleLength = 0;
do {
if (threeNOneValueFor(inputTwo) > maximumCycleLength) {
maximumCycleLength = threeNOneValueFor(inputTwo);
}
inputTwo = inputTwo - 1;
} while (inputTwo >= inputOne);
return maximumCycleLength;
}
private static int threeNOneValueFor(int inputNumber) {
int counter = 1;
while (inputNumber != 1) {
if (inputNumber % 2 == 0)
inputNumber = inputNumber / 2;
else
inputNumber = 3 * (inputNumber) + 1;
counter++;
}
return counter;
}
}and the test class:
/* User: koray@tugay.biz Date: 21/03/15 Time: 20:54 */
public class TestClass {
public static void main(String[] args) {
int one = 1;
int two = 10;
int result = new ThreeNOneForRangeSolver().solveFor(one, two);
System.out.println(one + " " + two + " " + result);
}
}Any feedback is welcome.
Solution
Looks pretty good over all, but I have a few suggestions.
Don't call
The
I would call
Seems significantly clearer as to what the method does. Couple that with a javadoc and it becomes very well explained:
(I would probably omit the
I'm probably getting pretty annoying at this point, but I don't much like the name
Considering it's on a class that already mentions the 3n + 1 problem, I would probably name it just
In it's current form, I would probably make
In fact, I'd probably take this a step farther and have
All in all (woo boring Saturday afternoons!), I might do something like this:
I'm not very happy with some of my namings (is "Collatz sequence" a recognized thing? I don't know what to call all of this), and some of the javadocs could use some better wording and whatnot, but hopefully this shows the structure and approach well enough.
Don't call
threeNOneValueFor twice when you could store it in a variable instead (or you can use Math.max). There's a chance that the compiler will optimize that, but that's a risky thing to assume.The
do-while seems a bit odd and unintuitive. I would go with a for loop instead.int maxCycleLength = 0;
for (; inputOne <= inputTwo; ++inputOne) {
maxCycleLength = Math.max(threeNOneValueFor(inputOne), maxCycleLength);
}
return maxCycleLength;inputOne and inputTwo are pretty bad names. If you didn't already know what they were, the names would really mean much to you. Something like minimumValue, rangeBegin, etc might be better.inputNumber is a pretty meh name as well. Considering the problem domain, I'd probably just call it n since that has a well defined meaning in this context and inputNumber could mean pretty much anything (it's an int parameter -- of course it's an input number).I would call
solveFor maximumCycleLength. solveFor has the same problem as inputNumber. You could be solving for pretty much anything that takes two inputs.public int maximumCycleLength(int minN, int maxN) {Seems significantly clearer as to what the method does. Couple that with a javadoc and it becomes very well explained:
/**
* Calculate the maximum cycle length for the {@code 3n + 1} sequence over every {@code n} such that
* {@code minN <= n <= maxN}. Note that {@code maxN} must be greater than or equal to {@code minN}.
* @param minN The beginning (inclusive) of the range over which to find the maximum cycle length.
* @param maxN The end (inclusive) of the range over which to find the maximum cycle length.
* @return The maximum cycle length of the {@code 3n + 1} sequence for all {@code n} in the provided range.
*/
public int maximumCycleLength(int minN, int maxN) {(I would probably omit the
@param and @return parts if I were to write this javadoc for my own code, but people tend to vehemently disagree with that.)I'm probably getting pretty annoying at this point, but I don't much like the name
threeNOneValueFor either. It doesn't find the valueFor; it finds the cycle length.public int threeNOneCycleLength(int n) {Considering it's on a class that already mentions the 3n + 1 problem, I would probably name it just
cycleLength.In it's current form, I would probably make
solveFor static. There's no state, so there's no real reason in having it be an object. Typically I lean far more towards non-static than static, since it's much better to regret something being non-static than it is to regret having made it static, but in this case, since it's pretty much a mathematic function, I doubt it's ever going to manipulate state (hopefully not anyway).In fact, I'd probably take this a step farther and have
threeNOneCycleLength be public. It could be useful on it's own, and since both methods are static utility-like methods, there's not too much concern about having the class do too many things.All in all (woo boring Saturday afternoons!), I might do something like this:
/**
* Provides methods related to the {@code 3n + 1} sequence.
*
* @see Collatz conjecture.
*/
public class ThreeNPlusOne {
/**
* Calculate the maximum cycle length for the {@code 3n + 1} sequence over every {@code n} such that
* {@code minN <= n <= maxN}. Note that {@code maxN} must be greater than or equal to {@code minN}.
*
* @param minN The beginning (inclusive) of the range over which to find the maximum cycle length.
* @param maxN The end (inclusive) of the range over which to find the maximum cycle length.
* @return The maximum cycle length of the {@code 3n + 1} sequence for all {@code n} in the provided range.
*/
public static int maximumCycleLength(int minN, int maxN) {
int maxCycleLength = 0;
for (; minN <= maxN; ++minN) {
maxCycleLength = Math.max(maxCycleLength, cycleLength(minN));
}
return maxCycleLength;
}
/**
* Calculates the cycle length for the provided {@code n}.
*
* @param n The value of {@code n} for which the
* @return The cycle length for the provided {@code n}.
*/
public static int cycleLength(int n) {
int cycles = 1;
while (n != 1) {
n = (n % 2 == 0) ? n / 2 : 3*n + 1;
cycles += 1;
}
return cycles;
}
}I'm not very happy with some of my namings (is "Collatz sequence" a recognized thing? I don't know what to call all of this), and some of the javadocs could use some better wording and whatnot, but hopefully this shows the structure and approach well enough.
Code Snippets
int maxCycleLength = 0;
for (; inputOne <= inputTwo; ++inputOne) {
maxCycleLength = Math.max(threeNOneValueFor(inputOne), maxCycleLength);
}
return maxCycleLength;public int maximumCycleLength(int minN, int maxN) {/**
* Calculate the maximum cycle length for the {@code 3n + 1} sequence over every {@code n} such that
* {@code minN <= n <= maxN}. Note that {@code maxN} must be greater than or equal to {@code minN}.
* @param minN The beginning (inclusive) of the range over which to find the maximum cycle length.
* @param maxN The end (inclusive) of the range over which to find the maximum cycle length.
* @return The maximum cycle length of the {@code 3n + 1} sequence for all {@code n} in the provided range.
*/
public int maximumCycleLength(int minN, int maxN) {public int threeNOneCycleLength(int n) {/**
* Provides methods related to the {@code 3n + 1} sequence.
*
* @see <a href="http://en.wikipedia.org/wiki/Collatz_conjecture">Collatz conjecture</a>.
*/
public class ThreeNPlusOne {
/**
* Calculate the maximum cycle length for the {@code 3n + 1} sequence over every {@code n} such that
* {@code minN <= n <= maxN}. Note that {@code maxN} must be greater than or equal to {@code minN}.
*
* @param minN The beginning (inclusive) of the range over which to find the maximum cycle length.
* @param maxN The end (inclusive) of the range over which to find the maximum cycle length.
* @return The maximum cycle length of the {@code 3n + 1} sequence for all {@code n} in the provided range.
*/
public static int maximumCycleLength(int minN, int maxN) {
int maxCycleLength = 0;
for (; minN <= maxN; ++minN) {
maxCycleLength = Math.max(maxCycleLength, cycleLength(minN));
}
return maxCycleLength;
}
/**
* Calculates the cycle length for the provided {@code n}.
*
* @param n The value of {@code n} for which the
* @return The cycle length for the provided {@code n}.
*/
public static int cycleLength(int n) {
int cycles = 1;
while (n != 1) {
n = (n % 2 == 0) ? n / 2 : 3*n + 1;
cycles += 1;
}
return cycles;
}
}Context
StackExchange Code Review Q#84663, answer score: 8
Revisions (0)
No revisions yet.