public
Description: deepblue's thoughts
Homepage: http://myruby.net/
Clone URL: git://github.com/deepblue/snippets.git
snippets / chalenge / collatz / collatz.rb
100644 53 lines (44 sloc) 1.184 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
%w(rubygems facets/ruby facets/memoize).each{|lib| require lib}
 
class Fixnum
  def next_number
    even? ? self / 2 :
      self * 3 + 1
  end
end
 
class Solver
  def collatz_from(num)
    num == 1 ? [1] :
      [num] + collatz_from(num.next_number)
  end
  memoize :collatz_from
 
  def find_length(num)
    collatz_from(num).length
  end
 
  def max_length(from, to)
    (from..to).to_a.map{|n| find_length(n)}.max
  end
end
 
require 'benchmark'
 
describe "3N + 1" do
  describe "Fixnum" do
    it "should calculate next number" do
      4.next_number.should == 4/2
      5.next_number.should == 5*3+1
    end
  end
  
  describe "Solver" do
    it "should calculate 3N+1" do
      answer = [22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
      Solver.new.collatz_from(22).should == answer
      Solver.new.find_length(22).should == answer.length
    end
 
    it "should calculate max length" do
      Solver.new.max_length(1,10).should == 20
      Solver.new.max_length(100,200).should == 125
      Solver.new.max_length(900,1000).should == 174
    end
    
    it "should benchmark" do
      puts Benchmark.measure { Solver.new.max_length(1, 10000)}
    end
  end
end