Модификация метода класса Fixnum

#ruby

#ruby

Вопрос:

Это описание ката кода, над которым я работаю для code wars. Цель ката — выполнить это:


Цель этого ката — изменить класс Fixnum, чтобы присвоить ему метод palindrome_below . Этот метод возвращает все числа от 1 до 1 включительно, но не включая себя, которые являются палиндромами для данной базы.

Например, в базе 2 (двоичной)

  1 = "1"
 2 = "10"
 3 = "11"
 4 = "100"
 

Следовательно, 1 и 3 являются палиндромами в базе два, и метод должен возвращать следующее.

 5.palindrome_below(2)
=> [1, 3]
 

Вот код, который я написал до сих пор для этого ката:

 class Fixnum
  def self.palindrome_below(binary)
    palindrome_match = []
    until self == 0
      if to_s(binary) == to_s(binary).reverse
       palindrome_match << self
       self -= 1
      end
    end
    palindrome_match
  end
end
 

Я попытался уменьшить self на 1 . Возвышенный говорит мне, что я не могу уменьшить значение self , но мне нужно уменьшить self . Поскольку это метод класса, мне нужно изменить self .

Это то, что я пытался обойти:

 class Fixnum
  def self.palindrome_below(binary)
    palindrome_match = []
    self_placeholder = self
    until self_placeholder == 0
      if self_placeholder.to_s(binary) == self_placeholder.to_s(binary).reverse
        palindrome_match << self_placeholder
        self_placeholder -= 1
      end
    end
    palindrome_match
  end
end
 

На этот раз я поместил self в переменную-оболочку, чтобы я мог ее изменить. Когда я пытаюсь это сделать, он говорит, что вызывается неопределенный метод palindrome_below . При выполнении этой реализации обезьяна должна быть исправлена Fixnum . Я не уверен, что я делаю неправильно. Может кто-нибудь указать мне правильное направление?

Комментарии:

1. Нет проблем. Вы можете найти его здесь codewars.com/kata/530d0298e09e54a3620006c2/train/ruby Однако вам, возможно, потребуется зарегистрироваться / войти.

2. Как сказал @sawa, вам, несомненно, нужен метод экземпляра, как у вас в вашем примере: 5.palindrome_below(2) . Нет необходимости изменять self , и на самом деле вы не смогли бы, даже если бы захотели. (Единственными способами изменения self являются вызов метода или создание класса или модуля.) Попробуйте это: def palendrome(base); 1.upto(self-1).select { |n| ....} . 1 to self-1 будет передан в блок и назначен переменной блока n . Вы должны добавить выражение к блоку, которое возвращает true значение if и только n вычисляет значение palendrome для заданного значения параметра base .

3. @CarySwoveland — Я думаю, что ваше решение намного лучше, чем общепринятый ответ — почему вы не опубликовали его как один?

4. Спасибо, @Uri, но у меня не было достаточно времени, чтобы опубликовать правильный ответ. Если это поможет, этого достаточно.

Ответ №1:

Рабочее решение (основанное на вашей второй попытке выше):

 class Fixnum
    def palindrome_below(base)
        palindrome_match = []
        num = self - 1
        until num == 0
            if num.to_s(base) == num.to_s(base).reverse
                palindrome_match << num
            end
            num -= 1
        end
       palindrome_match.reverse
    end
end
 

Что я изменил:

  1. Вы были правы, добавив self_placeholder — я назвал эту переменную num . В Ruby Fixnum s являются неизменяемыми, поэтому вы не можете изменить значение самого конкретного Fixnum .
    • Я вычел 1 из num самого начала, чтобы избежать включения самого числа в результирующий массив
  2. palindrome_below(base) должен быть метод экземпляра. Вы очень заботитесь о значении конкретного экземпляра класса Fixnum (т. Е. О значении числа).
  3. Вам нужно вычесть 1 из num -за пределов вашего if оператора.
  4. Я перевернул palindrome_match массив так, чтобы он возвращался в правильном порядке возрастания.

Гораздо лучшее решение (любезно предоставлено комментарием @CarySwoveland выше).

 class Fixnum
    def palindrome_below(base)
        1.upto(self-1).select { |num| num.to_s(base) == num.to_s(base).reverse }
    end
end