Ruby Project Euler 26,无法思考问题的答案

时间:2018-09-07 08:13:24

标签: ruby

我整天都在想一个答案,这是我能够尝试从别人的理解方式中得到的最好的答案,但是如果以不同的方式查看每种答案对我没有太大帮助,我不知道其背后的原因和逻辑,当数值为983时我已经得到999

numberWithLargestCycle = 0
largestCycleSize = 0

for i in 1..1000
    for j in 1..i
        if ((10 ** j) % i) == 1

            puts "i is #{i}, j is #{j}, #{(10 ** j) % i}"
            if largestCycleSize < j
                numberWithLargestCycle = i
                largestCycleSize = j
            end
        end
    end
end

puts numberWithLargestCycle

我要解决的问题

  

单位分数在分子中包含1。小数   分母为2至10的单位分数的表示为   给出:

     

1/2 = 0.5 1/3 = 0.(3)1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6)1/7 =     0.(142857)1/8 = 0.125 1/9 = 0.(1)1/10 = 0.1其中0.1(6)表示0.166666 ...,并具有1位数的重复周期。可以看出1/7的重复周期为6位数。

     

查找d <1000的值,其中1 / d包含最长的值   小数部分重复循环。

2 个答案:

答案 0 :(得分:1)

主要问题是,当代码实际找到循环大小时,代码不会停止;内部for循环不断执行。

我会强烈建议使用有意义的变量名,因为这样可以更清楚地了解代码的实际作用!另外,将非显而易见的代码(((10 ** j) % i) == 1)移至方法中,以防止污染具有复杂实现细节的“主”代码。

(实际上,该方法在i = 6之类的方法上并不总是能正常工作,但目前还不是主要的阻止方法...)

让我们考虑一下您正在搜索1/9的循环大小的情况:

def is_cycle_size?(denominator, cycle_size)
  (10 ** cycle_size) % denominator) == 1
end

denominator = 9
for cycle_size in 1..denominator
  if is_cycle_size?(cycle_size, denominator)
    puts "cycle_size is #{cycle_size}"
  end
end

# Output:
cycle_size is 1
cycle_size is 2
cycle_size is 3
cycle_size is 4
cycle_size is 5
cycle_size is 6
cycle_size is 7
cycle_size is 8
cycle_size is 9

现在,问题变得更加明显。您实际上并不想遍历所有可能的循环大小;您真的只想获取周期大小!

换句话说,您的基本代码结构应如下所示:

denominator_with_largest_cycle_size = 0
largest_cycle_size = 0

def find_cycle_size(denominator)
  # Define me!!
end

for denominator in 1..1000
  cycle_size = find_cycle_size(denominator)
  puts "denominator is #{denominator}, cycle size is #{cycle_size}"
  if largest_cycle_size < cycle_size
    denominator_with_largest_cycle_size = denominator
    largest_cycle_size = cycle_size
  end
end

(还可以进行其他改进;这只是您尝试的“最小”更改。)

请注意,通过此操作,您还可以单独测试find_cycle_size,例如您应该可以运行find_cycle_size(238487)


奖金:一旦您确定了如何定义上述方法,就可以将该红宝石代码简化为:

denominator_with_largest_cycle_size = (1..1000).max_by do |denominator|
  find_cycle_size(denominator)
end

答案 1 :(得分:0)

这是一种蛮力计算任何有重复小数的有理数1/mm >= 1的重复小数的长度。

首先,1/m是终止小数或重复小数。当且仅当m的素数是2和/或5时,才是前者。 (例如,参见this Wiki。)例如,1.0/40 #=> 0.025是自40 = 2^3 * 5^1起的终止小数。 2^0(= 1),2^15^1也有终止小数点。

require 'prime'

def cycle_length(m)
  return 0 if (Prime.prime_division(m).map(&:first) - [2,5]).empty?
  r = Rational(1,m)
  1.step.find do |n|
    p = (10**n)*r
    p - r == p.to_i.to_r
  end
end

[1,2,3,7,27,40,97].each do |m|
  puts "1/#{m} = #{(1.0/m).round(15).to_s.ljust(17)}: #{cycle_length(m).to_s.rjust(3)}"
end
1/1  = 1.0              :   0
1/2  = 0.5              :   0
1/3  = 0.333333333333333:   1
1/7  = 0.142857142857143:   6
1/27 = 0.037037037037037:   3
1/40 = 0.025            :   0
1/97 = 0.010309278350515:  96