2

The Collatz conjecture:

https://en.wikipedia.org/wiki/Collatz_conjecture

For any positive integer n we define two rules: if even: divide by two if odd: multiply by three, then add one, and repeat until the result is the number 1. The smallest value of n is 1.

This will generate sequences of numbers like below, converging to 1:

6, 3, 10, 5, 16, 8, 4, 2, 1

For each number n we can now count the number of steps in this sequence until we reach 1.

So the sequence above, starting with 6, has a length of 9 (including the starting point and the final one).

My problem:

I am trying to find the second-longest sequence of all the integers smaller or equal than 10 million. How would you go about it?

So far I came up with a solution for finding the longest sequence, but I am not sure how to find the 2nd.

def collatz_sequence_eval(n)
  array_sequence = []
  until n == 1
    if n%2 != 0
        n = 3*n + 1
        array_sequence.push(n)
      else
        n = n/2
        array_sequence.push(n)
    end
  end
  return array_sequence
end

def collatz_iterator
  counter = 1
  current_longest_sequence = []
  until counter == 10000000
    cur_seq = collatz_sequence_eval(counter)
    if cur_seq.length > current_longest_sequence.length
      current_longest_sequence = cur_seq
      counter+=1
    else
      counter+=1
    end
  end
    puts "Starting number is #{current_longest_sequence[0]}.
    Sequence length is #{current_longest_sequence.length}"
end
huxley
  • 23
  • 4

1 Answers1

4
def collatz(n)
  seq = [n]
  until n == 1
    n = n.even? ? n/2 : 3*n + 1
    seq << n
  end
  seq
end

(2..10**7).reduce([[],[]]) do |(longest, next_longest), n|
  seq = collatz(n)
  seq_size = seq.size
  if seq_size > longest.size
    [seq, longest]
  elsif seq_size < longest.size && seq_size > next_longest.size
    [longest, seq]
  else
    [longest, next_longest]
  end
end
  #=> [[8400511, 25201534, 12600767, 37802302, 18901151, 56703454, 
  #     ...
  #     106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1
  #    [8865705, 26597116, 13298558, 6649279, 19947838, 9973919,
  #     ...
  #     17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]]

By changing the final end to end.map(&:size), [686, 668] is returned, meaning the longest sequence(s) had length 686, the next longest(s), 668.

The length of the longest sequence appears consistent with results given in the Wiki, which states that for n < 10^7 685 "steps" are required.

226 seconds were required to perform this calculation when using Linux on a Pixelbook with a 1.2GHz 7th generation i5.

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100