新手问题 这段代码有几个小细节不太理解,寻求帮助

drine · 发布于 2014年12月28日 · 最后由 Alexander 回复于 2014年12月31日 · 1279 次阅读
6494

来自rubykoans, about_scoring_project.rb里的一个解法 (其中第8行 sum += 1000 | value -= 3 if value >= 3的逻辑稍微有点小错误)

说明部分

  • dice传入3个1,1000分
  • 3个一样的其他数字,返回100*其他数字(除了3个1)
  • 一个1值100分
  • 一个5值50分
  • 其他都算0分

  • A set of three ones is 1000 points

  • A set of three numbers (other than ones) is worth 100 times the number. (e.g. three fives is 500 points).

  • A one (that is not part of a set of three) is worth 100 points.-

  • A five (that is not part of a set of three) is worth 50 points.

  • Everything else is worth 0 points.

## 我的问题是

  1. 想了解下这段代码是怎么达到上面的要求的..(主要是对于if里面的理解)
  2. inject的block后面,分号后跟个result是什么意思啊?

* 还希望大神们能稍微详细的为小弟解决下这些问题。。做了一晚上的rubykoans了,都快昏了。。

def score(dice)
  return 0 if dice == []
  sum = 0
  rolls = dice.inject(Hash.new(0)) { |result, element| result[element] += 1; result; }
  rolls.each { |key, value| 
    # special condition for rolls of 1
    if key == 1  
      sum += 1000 | value -= 3 if value >= 3
      sum += 100*value
      next
    end
    sum += 100*key | value -= 3 if value >= 3
    sum += 50*value if key == 5 && value > 0
  }
  return sum
end

共收到 14 条回复
6494

已经意识模糊了。。google上搜到的代码又是如此模样,累觉不爱啊。。睡了明早再来看好了 = =

96

我也做过,我的答案是这个。好像是从哪里抄的了 http://www.51testing.com/index.php?uid-7844-action-viewspace-itemid-832538


def score(dice)
    s = 0
    dice.uniq.each do |x|
        array = dice.count(x).divmod(3)
        if 1 == x
            s += array[0] * 1000 + array[1] * 100
        elsif 5 == x
            s += array[0] * x * 100 + array[1] * 50
        else
            s += array[0] * x * 100
        end
    end
    s
end

6494

#2楼 @qqrrm 谢谢,但主要想了解下我贴的那段代码。 另外,记得以前C老师讲过, 1 == x比 x == 1要好..但原因是啥来着呢?想不起了..囧

E14fa6

@drine 1 == x 一來可以避免寫出 1 = x (不小心少了一個等號) 的問題外,再看看以下這個有點極端的例子:

class Demo
  def ==(other)
    true
  end
end

obj = Demo.new

p obj == false  # true
p false == obj  # false

雖然平常沒事不會這樣搞,不過上面這樣的寫法的確會造成交換過來寫會得到不同的結果 :)

14957

自己写, 让测试一条一条通过, 很简单的一道题, 你贴的代码过于炫技, 本来很简单的语句, 非要别别扭扭的写出来

6494

#4楼 @eddie 哦谢谢!

6494

#5楼 @cifery 是啊,too 炫酷 too 理解...。

14957

对于写 1 == x , 而不是x == 1, 原因是, 第一个写法没有副作用, 你知道你是在调用1.==() 这个方法, 如果你没有给fixnum做monkey patch, 那么当且仅当参数确实为1时, 函数返回true, 再没有其他情况, 如果写 x == 1, 你就要冒风险, 因为你不知道x这个类的==方法是怎么定义的, 极端一点就会有@eddle 提到的情况

14957

#7楼 @drine 安利给你一个qq群, 1043776, 新手挺友好的, 人也不多, 但是不缺高手

14206

#3楼 @drine 其实就是避免把==写成=,导致判断语句变成赋值语句后,1=x和x=1的区别就显而易见了,前者更安全。

1310
def score(dice)
  return 0 if dice == []
  sum = 0
  # 遍历 dice,使其变成一个 Hash,key 为 dice 里面的数值,value 为 出现的次数
  # result 只的是 block 返回的值
  rolls = dice.inject(Hash.new(0)) { |result, element| result[element] += 1; result; }
  rolls.each { |key, value| 
    # special condition for rolls of 1
    if key == 1
      # 下面这句可以等价为
      # if value >= 3
      #   sum += 1000
      #   value -= 3
      # end
      # 这里的 `|` 无意义,不想写 begin end
      sum += 1000 | value -= 3 if value >= 3
      sum += 100*value
      next
    end
    sum += 100*key | value -= 3 if value >= 3
    sum += 50*value if key == 5 && value > 0
  }
  return sum
end

btw:这段代码性能不错,可惜是错误的,如果有 6 个 1 的话,它只会计入 1300分。

12楼 已删除
6494

#11楼 @Alexander 好多解法用uniq,这个方法太耗时间了感觉

6494

#11楼 @Alexander 原题里没有要求处理6个1或者更多的情况,所以它那样写吧。不过还是有问题,在stackoverflow上有人帮忙修改了

1310

#14楼 @drine Sorry,我之前的理解错误,这里的 if 里面的 | 并非无意义,它的优先级比 += 要高,于是

sum += 1000 | value -= 3 if value >= 3

等价于

if value >= 3
  sum += (1000 | value -= 3)
end

| 操作符的意思是按位或,所以 sum 会得到一个不正确的值。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册