Project Euler : Problem 14 - Longest Collatz sequence

3 minute read

Problem Statement : Longest Collatz sequence

Problem 14 :The following iterative sequence is defined for the set of positive integers:

Using the rule above and starting with , we generate the following sequence:

It can be seen that this sequence (starting at and finishing at ) contains terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at .

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.

Concept and Theory

As stated its a conjecture, meaning this haven’t be proven mathematically. So what we can all do is do what it says and find out the largest number.

Apparently if you will see at some point the cycle repeats. For eg. the cycle will look like

As we can see the number ’s cycle is one short than that of . Simply Cache them!!! That way we don’t have to run the code everytime. What else we can see, may result in an odd number or even number and will always result in even number. Hence we can directly jump steps when is odd and save a calculation by .

Naive Code

/**
 * A function which tells you the largest possible number below a limit having
 * longest Collatz Cycle
 *
 * @param limit : maximum number upto which we need to scan
 *
 * @return number having largest collatz cycle
 */
public static long naiveLongestCollatzSequenceFinder(long limit) {

  long maxLength = 0;
  long maxNum = 0;

  for (long i = 1; i <= limit; i++) {

    long num = i;

    long lengthSoFar = 0;

    while (num != 1) {
      if (num % 2 == 0) {
        num /= 2;
      } else {
        num = 3 * num + 1;
      }
      lengthSoFar++;
    }
    if (lengthSoFar >= maxLength) {
      maxLength = lengthSoFar;
      maxNum = i;
    }
  }
  return maxNum;
}

Optimized Code

	private static final int CACHE_SIZE = 5_000_000;

	// stores collatz sequence for number at index
	private static int[] cache = new int[CACHE_SIZE + 1];

	// stores number with max collatz sequence at index
	private static int[] collatzCache = new int[CACHE_SIZE + 1];

	public static void main() {
		precomputeCache();

		Scanner scanner = new Scanner(System.in);
		int tests = Integer.parseInt(scanner.nextLine());
		for (int i = 0; i < tests; i++) {
			int n = Integer.parseInt(scanner.nextLine());
			System.out.println(collatzCache[n]);
		}

		scanner.close();
	}

	/**
	 * A function to precompute the collatz sequence and store them in a cache
	 */
	public static void precomputeCache() {
		cache[0] = 1;
		cache[1] = 1;
		collatzCache[0] = 1;
		collatzCache[1] = 1;
		int maxSeq = 0;
		int maxNum = 0;
		for (int j = 2; j <= CACHE_SIZE; j++) {
			int collatzSeq = 0;
			long number = j;
			while (number > 1) {
				if (cache[j] > 0) {
					collatzSeq += cache[j];
					break;
				}
				collatzSeq++;
				if (number % 2 == 0) {
					number >>= 1;
				} else {
					number = 3 * number + 1;
				}
			}
			cache[j] = collatzSeq;
			if (collatzSeq >= maxSeq) {
				maxSeq = collatzSeq;
				maxNum = j;
			}
			collatzCache[j] = maxNum;
		}
	}

Test Your Skills

Wanna try a harder version of the above problem ? Check this HackerRank problem.

Solution

The solution will remain same as given in the above mentioned post, , you just need to call it for each test case.

References and Further Readings

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...