FizzBu​​zz Ruby红线

时间:2018-07-01 19:49:25

标签: ruby math substring modulo fizzbuzz

Rosettacode.org在Ruby中具有出色的单行FizzBu​​zz解决方案。

1.upto(100){|n|puts'FizzBuzz '[i=n**4%-15,i+13]||n}

麻烦是,我不明白。令我感到困惑的部分是“ n以4模-15的幂”。有人有解释或对解释的引用吗?我想在其他问题中使用这种选择子字符串的方式。 有关FizzBu​​zz的更多信息,请参见[https://rosettacode.org/wiki/FizzBuzz]

3 个答案:

答案 0 :(得分:6)

我不知道他们是怎么发现升到四次方的,但是-15是因为FizzBu​​zz处理3的倍数或5的倍数或3和5的倍数(即15的倍数)。然后否定它最终可以很好地处理负索引。我们可以看到它适用于Modular Exponentiation。此处的内存有效方法部分:

  

c mod m =(a⋅b)mod m
  c mod m = [(a mod m)⋅(b mod m)] mod m

在我们的例子中, c 是我们的 n ,所以我们有

c ** 4 % m

使用law of exponents,我们知道(c ** e1) * (c ** e2) = c ** (e1 + e2),也就是c ** 4 = (c ** 2) * (c ** 2),所以我们现在有了ab,它们都是{{ 1}}。因此:

c ** 2

并再次执行相同的步骤:

(c ** 4) % m = ((c ** 2) * (c ** 2)) % m
             = (((c ** 2) % m) * ((c ** 2) % m)) % m
             = (((c ** 2) % m) ** 2) % m

最后:

(c ** 2) % m = (c * c) % m
             = ((c % m) * (c % m)) % m
             = ((c % m) ** 2) % m

(c ** 4) % m = ((((c % m) ** 2) % m) ** 2) % m 时,m = -15的唯一值是c % m,我们可以建立一个简单的表格进行查看。由于我们只对模的结果进行运算,因此我们只需要证明这15个数字是有效的:

(-14..0)

现在,看我们的表,3的所有倍数的值为c%m **2 %m **2 %m -14 => 196 => -14 => 196 => -14 -13 => 169 => -11 => 121 => -14 -12 => 144 => -06 => 36 => -09 -11 => 121 => -14 => 196 => -14 -10 => 100 => -05 => 25 => -05 -09 => 81 => -09 => 81 => -09 -08 => 64 => -11 => 121 => -14 -07 => 49 => -11 => 121 => -14 -06 => 36 => -09 => 81 => -09 -05 => 25 => -05 => 25 => -05 -04 => 16 => -14 => 196 => -14 -03 => 9 => -06 => 36 => -09 -02 => 4 => -11 => 121 => -14 -01 => 1 => -14 => 196 => -14 00 => 0 => 00 => 0 => 00 ,5的所有倍数的值为-09,并且3和5的倍数的值设置为-05;其他所有内容都是00(如果我们使用15而不是-15,则我们将分别具有6、10、0和1,并且需要进行查找才能将其转换为字符串索引)。使用字符串-14String#[]的start参数插入这些字符串可以得到:

'FizzBuzz '

并在这些数字上加13以得到长度:

'FizzBuzz '[-9] # => 'F'
'FizzBuzz '[-5] # => 'B'
'FizzBuzz '[0]  # => 'F'
'FizzBuzz '[-14]# => nil

答案 1 :(得分:2)

非常棘手。

模量是周期函数。 您可以在相同的模式下获得更多周期函数,更改指数(k)和除数(h):

y = x**k % h

或者只是看到x,y对:

h = 4 # exponent
k = -15 # divisor

xy = []
1.upto 100 do |n|
  i= n**h % k
  xy << [n, i]
end
p xy

选择y = x % 2k = 1h = 2的基本示例就很明显。 您会得到一系列1, 0, 1, 0, 1, ...

要可视化在这种情况下使用的功能,例如可以使用gnuplot gem在红宝石中进行绘制。

require 'gnuplot' 

Gnuplot.open do |gp|
  Gnuplot::Plot.new( gp ) do |plot|

    plot.title  "Periodic function for FizzBuzz"

    x = (0..100).collect { |v| v }
    p y = x.collect { |v| v ** 4 % -15 }

    plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
      ds.with = "linespoints"
    end
  end
end

答案 2 :(得分:2)

我将尝试为@Simple Lime的出色答案添加一个更简单的解释。 如果n是3的倍数,则将其表示为3k,现在:

(3k)^4  == 81(k^4)

81 % 15 == 6,我们减去15(因为是模-15),得到-9。

同样,当n是5的倍数时,它是625(k^4)625 % 15 == 10,减去后得到-5。

否则,n可能是2、7、11和13的倍数。在所有这些情况下,n ^ 4%15将为1(请参见Simple Lime表),而-15将使我们成为-14。