Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby Koans更优雅的解决方案';三角形.rb_Ruby - Fatal编程技术网

Ruby Koans更优雅的解决方案';三角形.rb

Ruby Koans更优雅的解决方案';三角形.rb,ruby,Ruby,我一直在研究Ruby Koans,并将其提交到about_triangle_project.rb,其中要求您为方法triangle编写代码 以下是这些项目的代码: 在triangle.rb中,我创建了以下方法: def triangle(a, b, c) if ((a == b) && (a == c) && (b == c)) return :equilateral elsif ((a == b) || (a == c) || (b == c

我一直在研究Ruby Koans,并将其提交到about_triangle_project.rb,其中要求您为方法triangle编写代码

以下是这些项目的代码:

在triangle.rb中,我创建了以下方法:

def triangle(a, b, c)
  if ((a == b) && (a == c) && (b == c))
    return :equilateral
  elsif ((a == b) || (a == c) || (b == c))
    return :isosceles
  else
    return :scalene
  end
end
通过阅读Chris Pine的《学会编程》我知道,做事的方法总是不止一种。尽管上面的代码可以工作,但我还是忍不住认为有一种更优雅的方法可以做到这一点。有没有人愿意就如何使这种方法更有效、更紧凑提出自己的想法


另一件我很好奇的事情是,为什么为了确定一个等边三角形,我不能创建(a==b==c)的条件。这是等边三角形的证明,但Ruby讨厌这种语法。有一个简单的解释来解释为什么会这样吗?

有一个简单的解释来解释为什么会这样:

def triangle(a, b, c)
  if a == b && a == c                # transitivity => only 2 checks are necessary
    :equilateral
  elsif a == b || a == c || b == c   # == operator has the highest priority
    :isosceles
  else
    :scalene                         # no need for return keyword
  end
end
Ruby中的
=
是一个运算符,它执行特定的函数。运算符具有确定其应用顺序的规则-例如,
a+2==3
在相等检查之前计算加法。但一次只计算一个运算符。将两个相等性检查放在一起是没有意义的,因为相等性检查的计算结果为
true
false
。有些语言允许这样做,但它仍然不能正常工作,因为如果
a
b
相等,那么您将计算
true==c
,这显然不是真的,即使a==b==c在数学术语中也是如此

至于更优雅的解决方案:

case [a,b,c].uniq.size
when 1 then :equilateral
when 2 then :isosceles
else        :scalene
end
def triangle(a, b, c)
  sides = [a, b, c].sort
  raise TriangleError, "Invalid side #{sides[0]}" unless sides[0] > 0
  raise TriangleError, "Impossible triangle" if sides[0] + sides[1] <= sides[2]
  return [:scalene, :isosceles, :equilateral][ 3 - sides.uniq.size ]
end
def triangle(a, b, c)
  return :equilateral if a == b and b == c
  return :isosceles if ( a == b or b == c or a == c )
  return :scalene
end
或者,更简短(但可读性较差):


我借用了Chuck很酷的uniq.size技术,并将其应用到oo解决方案中。最初我只是想将参数验证提取为一个保护子句,以维护单一责任原则,但由于这两种方法都在相同的数据上运行,我认为它们属于一个对象中的一部分

# for compatibility with the tests
def triangle(a, b, c)
  t = Triangle.new(a, b, c)
  return t.type
end

class Triangle
  def initialize(a, b, c)
    @sides = [a, b, c].sort
    guard_against_invalid_lengths
  end

  def type
    case @sides.uniq.size
    when 1 then :equilateral
    when 2 then :isosceles
    else :scalene
    end
  end

  private
  def guard_against_invalid_lengths
    if @sides.any? { |x| x <= 0 }
      raise TriangleError, "Sides must be greater than 0"
    end

    if @sides[0] + @sides[1] <= @sides[2]
      raise TriangleError, "Not valid triangle lengths"    
    end
  end
end
#与测试的兼容性
def三角板(a、b、c)
t=三角形。新的(a、b、c)
返回t.type
结束
阶级三角
def初始化(a、b、c)
@边=[a,b,c]。排序
防止无效长度
结束
def类型
case@sides.uniq.size
当1时,则为:等边
当2时,则为:等腰
其他:异丙苯
结束
结束
私有的
def防护装置防止长度无效
如果@sides.any?{| x | x另一种方法:

def triangle(a, b, c)
  a, b, c = [a, b, c].sort
  raise TriangleError if a <= 0 or a + b <= c
  return :equilateral if a == c
  return :isosceles if a == b or b == c
  return :scalene
end
def三角形(a、b、c)
a、 b,c=[a,b,c].排序

如果aHmm..我不知道uniq
-所以来自smalltalk(很久以前),我使用:

以下是我的解决方案:

case [a,b,c].uniq.size
when 1 then :equilateral
when 2 then :isosceles
else        :scalene
end
def triangle(a, b, c)
  sides = [a, b, c].sort
  raise TriangleError, "Invalid side #{sides[0]}" unless sides[0] > 0
  raise TriangleError, "Impossible triangle" if sides[0] + sides[1] <= sides[2]
  return [:scalene, :isosceles, :equilateral][ 3 - sides.uniq.size ]
end
def triangle(a, b, c)
  return :equilateral if a == b and b == c
  return :isosceles if ( a == b or b == c or a == c )
  return :scalene
end
def三角形(a、b、c)
边=[a,b,c]。排序
提升三角形错误,“无效边#{sides[0]}”,除非边[0]>0
提高三角形错误,如果边[0]+边[1]则为“不可能的三角形”:

case [a,b,c].uniq.size
when 1 then :equilateral
when 2 then :isosceles
else        :scalene
end
def triangle(a, b, c)
  sides = [a, b, c].sort
  raise TriangleError, "Invalid side #{sides[0]}" unless sides[0] > 0
  raise TriangleError, "Impossible triangle" if sides[0] + sides[1] <= sides[2]
  return [:scalene, :isosceles, :equilateral][ 3 - sides.uniq.size ]
end
def triangle(a, b, c)
  return :equilateral if a == b and b == c
  return :isosceles if ( a == b or b == c or a == c )
  return :scalene
end
class TriangleError
来自matlab世界,我习惯于数组函数“any”和“all”,并且很高兴在Ruby中找到它们。因此:

def triangle(a, b, c)
  eqs = [a==b, a==c, b==c]
  eqs.all?? :equilateral : eqs.any?? :isosceles : :scalene
end

不过,就可读性和计算时间而言,不知道这是否是最优的…(ruby noob)。

==
是一个接受值的运算符(如
*
/
)。它返回
true
false
。不引起混淆是非法的(例如,
1==1==1
将计算为
false
,因为它相当于
(1==1==1
)。您可以通过使用
:等边
:(a==b)和&(b==c)的可传递属性来节省一些代码。Python支持“a==b==c”语法(甚至“auniq.size
;这很优雅。有趣的是,你选择使用
fetch
,如
[…][…]uniq.size]
是有效的。@Phrogz:我一开始是这样写的,但它太难读了,就像人们经常取笑的那种Perl代码一样,所以我想
fetch
至少接近我想读的东西。我想出了这个代码:
[nil,:等边,:等腰,:scalene][[a,b,c].uniq.size]
但我认为你的更具可读性。很棒的东西,但请注意更简洁的解决方案中的两个打字错误(等腰和不等腰)。更改太少,无法编辑。谢谢你,glebm!(还有上面的答案。)这也是对about_triangle_项目_2.rb的测试部分的一个很好的回答。我复制了你的解决方案,它比我的机器代码版本优雅得多。+1巧妙地使用了排序,以避免不必要的比较。我必须将类TriangleError