FizzBu zz Ruby单线程

问题描述 投票:7回答:3

Rosettacode.org在Ruby中提供了这个出色的单行FizzBu​​zz解决方案。

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

麻烦的是,我不明白。令我困惑的部分是“4模数-15的力量”。有没有人有解释或参考解释?我想用这种方法在其他问题中选择子串。有关FizzBu​​zz的更多信息,请参阅[https://rosettacode.org/wiki/FizzBuzz]

ruby math substring modulo fizzbuzz
3个回答
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,这两个都是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 = -15c % m的唯一值是(-14..0),我们可以构建一个简单的表来查看。由于我们只对模数的结果进行操作,因此我们只需要能够证明这15个数字是有效的:

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

现在,看看我们的表,3的所有倍数的值是-09,所有5的倍数的值是-05,3和5的倍数的值被设置为00;其他一切都是-14(如果我们使用15而不是-15,我们分别有6,10,0和1,并且需要查找将其转换为字符串索引)。使用字符串String#[]'FizzBuzz '的start参数插入到我们这里:

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

并为这些数字添加13以获得长度:

'FizzBuzz '[-9, 4]   # => "Fizz"
'FizzBuzz '[-5, 8]   # => "Buzz "
'FizzBuzz '[0, 13]   # => "FizzBuzz "
'FizzBuzz '[-14, -1] # => nil

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 % 2的基本例子:k = 1h = 2。你得到一系列的1, 0, 1, 0, 1, ...

为了可视化在这种情况下使用的函数,您可以使用gnuplot gem在ruby中绘图。

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
投票

我将尝试为@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。

© www.soinside.com 2019 - 2024. All rights reserved.