Skip to content

Instantly share code, notes, and snippets.

@RogerPodacter
Created November 28, 2012 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RogerPodacter/4163082 to your computer and use it in GitHub Desktop.
Save RogerPodacter/4163082 to your computer and use it in GitHub Desktop.
# Take a positive integer, like 9, and apply the following rule. If it’s odd, multiply it by 3 and add 1; if it’s even, divide it in half. 9 -> 28 -> 14 -> 7 -> 22 -> 11... The Collatz conjecture says that all such chains will terminate in the 1 -> 4 -> 2 -> 1 -> 4... loop. Calling “1” the end of a chain, for what integer less than a million is the Collatz chain the longest?
require 'active_support'
extend ActiveSupport::Memoizable
def apply_collatz_rule(num)
if num % 2 == 0
num / 2
else
num * 3 + 1
end
end
def compute_collatz_chain_length(num)
return 0 if num == 1
1 + compute_collatz_chain_length(apply_collatz_rule(num))
end
memoize :compute_collatz_chain_length
def find_longest_chain(upper_bound)
longest_chain = 0
num_with_longest_chain = 0
1.upto(upper_bound) do |num|
new_candidate = compute_collatz_chain_length(num)
if new_candidate > longest_chain
longest_chain = new_candidate
num_with_longest_chain = num
end
end
"#{num_with_longest_chain}: #{longest_chain}"
end
@a-warner
Copy link

including memoizable into kernel? Just do (assuming this is in a class and not on kernel)

def compute_collatz_chain_length(num)
  if num == 1
    0
  else
    @memo ||= {}
    @memo[num] ||= 1 + compute_collatz_chain_length(apply_collatz_rule(num))
  end
end

@RogerPodacter
Copy link
Author

"but what if @memo[num] == false"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment