Ruby Koans 182.重构帮助

时间:2011-07-18 20:02:25

标签: ruby

你能帮我重构一下我为Ruby Koans#182提出的解决方案吗?这是你在其中写一个分数方法来计算贪婪游戏的分数的公案。以下代码工作,所有测试都通过。

然而,它感觉很长而且没有红宝石般的感觉。我怎样才能让它变得更好?

def score(dice)
rollGreedRoll = Hash.new
rollRollCount = Hash.new
(1..6).each do |roll|
    rollGreedRoll[roll] = roll == 1 ? GreedRoll.new(1000, 100) :
            GreedRoll.new(  100 * roll, roll == 5 ? 50 : 0)
    rollRollCount[roll] = dice.count { |a| a == roll }
end


  score =0 


  rollRollCount.each_pair do |roll, rollCount|
    gr = rollGreedRoll[roll]  
    if rollCount < 3
        score += rollCount * gr.individualPoints
    else
        score += gr.triplePoints + ((rollCount - 3) * gr.individualPoints)

    end 
  end

  return score
end

class GreedRoll
    attr_accessor :triplePoints
    attr_accessor :individualPoints

    def initialize(triplePoints, individualPoints)
        @triplePoints = triplePoints
        @individualPoints = individualPoints
    end
end

4 个答案:

答案 0 :(得分:6)

我在https://gist.github.com/1091265进行了重构演练。最终解决方案如下:

def score(dice)
  (1..6).collect do |roll|
    roll_count = dice.count(roll)
    case roll
      when 1 : 1000 * (roll_count / 3) + 100 * (roll_count % 3)
      when 5 : 500 * (roll_count / 3) + 50 * (roll_count % 3)
      else 100 * roll * (roll_count / 3)
    end
  end.reduce(0) {|sum, n| sum + n}
end

请注意: .reduce.inject

的同义词

答案 1 :(得分:3)

你可以把rollRollCount放在第一个“每个”里面,不是吗?然后你不必迭代(1..6)两次。

答案 2 :(得分:2)

这是对它的另一种看法,将方法提取到自己的类中。有点长啰嗦,但易于阅读和理解:

def score(dice)
  GreedScore.new(dice).calculate
end

实施:

class GreedScore
  def initialize(dice)
    @values = dice.sort
  end

  def calculate
    @score = 0
    score_triples
    score_singles
    @score
  end

  private

  def score_triples
    (1..6).each do |match|
      if @values.count(match) >= 3
        @score += match * (match == 1 ? 1000 : 100)
        @values = @values.drop(3)
      end
    end
  end

  def score_singles
    @values.each do |value|
      @score += 100 if value == 1
      @score += 50 if value == 5
    end
  end
end

答案 3 :(得分:1)

这是我的方法。假设骰子的数量很大,我使用散列表示性能。另外,我喜欢尽可能使用inject

def score(dice)
  tally = 0

  return tally if dice.length == 0

  hash = dice.inject(Hash.new(0)) { |h,v| h[v] += 1; h }

  (1..6).collect do |roll|
    case roll
    when 5
      tally += (hash[roll] / 3) * 500 + (hash[roll] % 3) * 50
    when 1
      tally += (hash[roll] / 3) * 1000 + (hash[roll] % 3) * 100
    else
      tally += (hash[roll] / 3) * roll * 100
    end
  end

  ap "dice = #{dice}, " + "hash = #{hash}, " + "tally = #{tally}"

  tally
end