Достаточно ли хорошее решение задачи из Ruby Koans?

Привет всем, идущим путем Ruby.



Для закрепления навыков программирования на Ruby, я решил таки добить Ruby Koans.



Для объяснения, что это такое, процитирую egoholic из его поста:

… проект Ruby Koans, который представляет собой учебную среду построенную на базе Test::Unit. Суть состоит в том, чтобы все тесты проходили правильно, в результате вашей правки содержимого тестовых матчеров. RubyKoans можно скачать на свою машину, но специально для таких лентяев как я был реализован веб интерфейс, что означает, что устанавливать ничего не нужно, просто пройдите по указанному далее адресу и заполняйте поля так, чтобы в матчерах не было ошибок. Сайт проекта: rubykoans.com/, онлайн версия: koans.heroku.com/.


Мой вопрос касается этой части: about_scoring_project

Задача: написать метод, подсчитывающий количество очков в результате выброса игральных костей.

Аргумент — массив содержащий до 5 значений. Например [1, 4] или [4, 4, 4, 1, 5]

Правила подсчета:

  • Три единицы дают 1000 очков.
  • Любое другое число встречающееся 3 раза, даёт 100 умноженное на это число (три пятерки дадут 500).
  • Встречающаяся единица дает 100. Кроме случаев, когда она входит в набор из трех единиц (см пункт 1).
  • Пятерка дает 50 Кроме случаев, когда она входит в набор из трех пятерок (см пункт 2).
  • Все остальное 0.


Как вам мое решение? Не проглядывается образ человека, пришедшего из PHP?



<pre><code class="ruby">def score(dice)
  # no dice given
  return 0 if dice.empty?

  total = 0

  # find triple match
  # collect duplicates into array (not more than 3)
  duplicates = dice.map do |n|
    n if dice.count{|d| d == n} &gt; 2
  end.compact
  # get number or nil
  triple = duplicates.pop

  # if there IS triple match
  if triple
    # triple one gives 1000
    if triple == 1
      total += 1000
    # other values give x100
    else
      total += triple*100
    end
    # remove those numbers from the collection
      # also ensure that only 3 array items can be removed
    array_min_size = dice.count - 3
    dice = dice.delete_if do |n|
      true if (n == triple && dice.count &gt; array_min_size)
    end 
  end

  # look for 1 or 5
  dice.each do |n|
    total += 50 if n == 5
    total += 100 if n == 1
  end

  return total
end


Буду очень благодарен за любую критику.



Если вы тоже играли с Ruby Koans, выкладывайте решения сюда. Уверен, что каждый прошедший эту часть, идет искать как сделали другие.
  • Вопрос задан
  • 4943 просмотра
Решения вопроса 1
jj_killer
@jj_killer
Вот как-то так, я не совсем понял может ли попасться [1, 1, 1, 1, 1, 1].
def score(dice)
  result = 0;

  (1..6).each do |digit|
    multiplier = 100
    multiplier = 1000 if digit == 1
    triple  = dice.count(digit) / 3 # принять во внимание [1, 1, 1, 1, 1, 1]
    result += digit * multiplier * triple
  end

  result += dice.count(1) % 3 * 100
  result += dice.count(5) % 3 * 50
end
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
traneblow
@traneblow
Всё таки перейти с PHP на руби очень трудно. Сам не могу освоиться пока.
Ответ написан
Комментировать
jj_killer
@jj_killer
Проглядывается еще как. Но это пройдет со временем. Я продублирую тут некоторые рекомендации традиционные для Руби.
  1. Не используйте return, если без него можно обойтись.
  2. Избегайте вложенных if-ов. Актуально не только для качества кода, но и производительности.
  3. Вообще, избегайте лишней логики, вроде:
    return 0 if dice.empty?
  4. Ну и сам алгоритм немного куцый, я бы по другому это сделал бы.


Сейчас попробую по своему переписать.
Ответ написан
Комментировать
@aaz86
Тесты проходит, хотя честно говоря этих тестов маловато чтобы гарантировать корректность реализации

def score(dice)
  # You need to write this method

  digits = Hash.new(0)
  dice.each { |n| digits[n] += 1  }

  result = 0

  result += 1000 if digits[1] >= 3           # 1

  (digits.keys - [1]).each do |n|            # 2
    result += n * 100 if digits[n] >= 3
  end

  result += 100 * (digits[1] % 3)            # 3

  result += 50 * (digits[5] % 3)             # 4

  result
end
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы