Consider the following algorithm to generate a sequence of numbers. Start with an integer n. If n is even, divide by 2. If n is odd, multiply by 3 and add 1. Repeat this process with the new value of n, terminating when n = 1. For example, the following sequence of numbers will be generated for n = 22:
For an input n, the cycle-length of n is the number of numbers generated up to and including the 1. In the example above, the cycle length of 22 is 16. Given any two numbers i and j, you are to determine the maximum cycle length over all numbers between i and j, including both endpoints.
1 10 100 200 201 210 900 1000
1 10 20 100 200 125 201 210 89 900 1000 174
*** my Java solution
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
final static BufferedReader reader_ = new BufferedReader(new InputStreamReader(System.in));
/**
* @param args
*/
public static void main(String[] args) {
new Problem().run();
}
static String[] ReadLn() {
String[] tokens = null;
try {
String line = reader_.readLine();
String REGEX_WHITESPACE = "\\s+";
String cleanLine = line.trim().replaceAll(REGEX_WHITESPACE, " ");
tokens = cleanLine.split(REGEX_WHITESPACE);
} catch (Exception e) {}
return tokens;
}
}
class Problem implements Runnable {
long CACHE_SIZE = 65536;
private final long[] cache_ = new long[(int) CACHE_SIZE];
/**
* Compute cycle length for a single number
*
* @param n number for which we find cycle length
* @return cycle length
*/
long cycleLen(long n) {
long len = 1;
if (n != 1) {
len = getFromCache(n);
if (len == 0) { //not yet in cache
// Recursively compute and store all intermediate values of cycle length
if ((n & 1) == 0) {
len = 1 + cycleLen(n >> 1);
} else {
len = 1 + cycleLen(n * 3 + 1);
}
putInCache(n, len);
}
}
return len;
}
void putInCache(long n, long len) {
if(n < CACHE_SIZE) {
cache_[(int)n] = len;
}
}
long getFromCache(long n) {
long result = 0;
if(n < CACHE_SIZE) {
result = cache_[(int)n];
}
return result;
}
/**
* Find max cycle on interval
*
* @param from interval start
* @param to interval end
* @return max cycle
*/
Long maxCycle(Long from, Long to) {
Long result = 0L;
Long cycle = 0L;
// Get all values of cycle length on the interval and put these values into a sorted set
for (long i = from; i <= to; i++) {
cycle = cycleLen(i);
if (cycle > result)
result = cycle;
}
return result;
}
public void run() {
String[] tokens = null;
long from, to, result = 0;
long arg1, arg2 = 0;
while ((tokens = Main.ReadLn()) != null) {
if (tokens.length == 2) {
arg1 = new Long(tokens[0]).longValue();
arg2 = new Long(tokens[1]).longValue();
from = (arg1 <= arg2) ? arg1 : arg2;
to = (arg2 >= arg1 ) ? arg2 : arg1;
result = maxCycle(from, to);
out(arg1+" "+arg2+" "+result);
}
}
}
static void out(String msg) {
System.out.println(msg);
}
}