Я не знаю, как они обнаружили, чтобы поднять до четвертой степени, но -15, потому что FizzBuzz имеет дело с кратными 3 или кратными 5 или кратными как 3, так и 5 (т.е. кратными 15) .. затем отрицание приводит к тому, что он работает с отрицательными показателями довольно хорошо. Мы видим, что он работает с Модульное экспонирование . В разделе Метод с эффективным использованием памяти там написано:
c mod m = (a ⋅ b) mod m
c mod m = [(a mod m) ⋅ (b mod m)] mod m
В нашем случае c является нашим n , поэтому мы имеем
c ** 4 % m
используя закон экспонент , мы знаем, что (c ** e1) * (c ** e2) = c ** (e1 + e2)
, поэтому c ** 4 = (c ** 2) * (c ** 2)
, так что теперь у нас есть a
и b
, которые оба равны 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
являются (-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 '
дает нам:
'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