Ruby Koan 151提出例外

我正在经历ruby,我在151,我只是碰到一堵砖墙。

这是公文:

# You need to write the triangle method in the file 'triangle.rb' require 'triangle.rb' class AboutTriangleProject2 < EdgeCase::Koan # The first assignment did not talk about how to handle errors. # Let's handle that part now. def test_illegal_triangles_throw_exceptions assert_raise(TriangleError) do triangle(0, 0, 0) end assert_raise(TriangleError) do triangle(3, 4, -5) end assert_raise(TriangleError) do triangle(1, 1, 3) end assert_raise(TriangleError) do triangle(2, 4, 2) end end end 

然后在triangle.rb中我们有:

 def triangle(a, b, c) # WRITE THIS CODE if a==b && a==c return :equilateral end if (a==b && a!=c) || (a==c && a!=b) || (b==c && b!=a) return :isosceles end if a!=b && a!=c && b!=c return :scalene end if a==0 && b==0 && c==0 raise new.TriangleError end end # Error class used in part 2. No need to change this code. class TriangleError < StandardError end 

我非常困惑 – 任何帮助都将不胜感激!

编辑:要完成这个公案,我需要把一些东西在TriangleError类 – 但我不知道是什么

更新:这是公牛业力事情说:

 <TriangleError> exception expected but none was thrown. 
  1. 一个三angular形不应该有任何长度为0的边。如果是的话,它可以是一个线段或一个点,取决于有多less个边是0。
  2. 消极长度没有意义。
  3. 三angular形的任何两边加起来应该比第三边多。
  4. 见3,关注“更多”。

您不应该需要更改TriangleError代码,AFAICS。 看起来你的语法只是有点古怪。 尝试改变

 raise new.TriangleError 

 raise TriangleError, "why the exception happened" 

另外,在你做任何事情之前,你应该testing这些值(并抛出exception)。 将exception的东西移动到函数的开头。

当a,b或c是负数时,你忘记了这个情况:

 def triangle(a, b, c) raise TriangleError if [a,b,c].min <= 0 x, y, z = [a,b,c].sort raise TriangleError if x + y <= z [:equilateral,:isosceles,:scalene].fetch([a,b,c].uniq.size - 1) end 

结束这样做:

 def triangle(a, b, c) a, b, c = [a, b, c].sort raise TriangleError if a <= 0 || a + b <= c [nil, :equilateral, :isosceles, :scalene][[a, b, c].uniq.size] end 

感谢这里的评论者:)

我喜欢Cory的答案。 但是,我想知道是否有任何理由或有任何获得四个testing,当你可以有两个:

 raise TriangleError, "Sides must by numbers greater than zero" if (a <= 0) || (b <= 0) || (c <= 0) raise TriangleError, "No two sides can add to be less than or equal to the other side" if (a+b <= c) || (a+c <= b) || (b+c <= a) 

您不需要修改例外。 像这样的东西应该工作;

 def triangle(*args) args.sort! raise TriangleError if args[0] + args[1] <= args[2] || args[0] <= 0 [nil, :equilateral, :isosceles, :scalene][args.uniq.length] end 
 def triangle(a, b, c) [a, b, c].permutation do |sides| raise TriangleError unless sides[0] + sides[1] > sides[2] end case [a,b,c].uniq.size when 3; :scalene when 2; :isosceles when 1; :equilateral end end 

你肯定不会更新TriangleError类 – 我自己被卡在了152上。 我想我需要在这里使用pythag定理。

 def triangle(a, b, c) # WRITE THIS CODE if a == 0 || b == 0 || c == 0 raise TriangleError end # The sum of two sides should be less than the other side if((a+b < c) || (a+c < b) || (b+c < a)) raise TriangleError end if a==b && b==c return :equilateral end if (a==b && a!=c) || (a==c && a!=b) || (b==c && b!=a) return :isosceles end if(a!=b && a!=c && b!=c) return :scalene end end # Error class used in part 2. No need to change this code. class TriangleError < StandardError end 

我想要一个能够有效地parsing所有参数的方法,而不是依赖testing断言中给出的顺序。

 def triangle(a, b, c) # WRITE THIS CODE [a,b,c].permutation { |p| if p[0] + p[1] <= p[2] raise TriangleError, "Two sides of a triangle must be greater than the remaining side." elsif p.count { |x| x <= 0} > 0 raise TriangleError, "A triangle cannot have sides of zero or less length." end } if [a,b,c].uniq.count == 1 return :equilateral elsif [a,b,c].uniq.count == 2 return :isosceles elsif [a,b,c].uniq.count == 3 return :scalene end end 

希望这有助于其他人意识到有一个以上的方式来剥皮猫。

在试图了解我必须要做什么与公主151,我得到了第一篇文章,并得到很多乐趣,检查每个人的解决scheme:) …这是我的:

 def triangle(a, b, c) array = [a, b, c].sort raise TriangleError if array.min <= 0 || array[0]+array[1] <= array[2] array.uniq! array.length == 1 ? :equilateral: array.length == 2 ? :isosceles : :scalene end 

Koan是学习Ruby的一个非常有趣的方式

我不认为我在这里看到这个。

我相信所有非法的三angular形条件都意味着最长的边不能超过总数的一半。 即:

 def triangle(a, b, c) fail TriangleError, "Illegal triangle: [#{a}, #{b}, #{c}]" if [a, b, c].max >= (a + b + c) / 2.0 return :equilateral if a == b and b == c return :isosceles if a == b or b == c or a == c return :scalene end 

我结束了这个代码:

 def triangle(a, b, c) raise TriangleError, "impossible triangle" if [a,b,c].min <= 0 x, y, z = [a,b,c].sort raise TriangleError, "no two sides can be < than the third" if x + y <= z if a == b && b == c # && a == c # XXX: last check implied by previous 2 :equilateral elsif a == b || b == c || c == a :isosceles else :scalene end end 

我不喜欢第二个条件/提高,但我不确定如何进一步改进。

您也可以尝试通过以下方式将exception实例化:

 raise TriangleError.new("All sides must be greater than 0") if a * b * c <= 0 

实际上在下面的代码中,条件a <= 0是多余的。 如果a <0,a + b将总是小于c,并且我们知道b <c

  raise TriangleError if a <= 0 || a + b <= c 

这是我写的,一切正常。

 def triangle(a, b, c) # WRITE THIS CODE raise TriangleError, "Sides have to be greater than zero" if (a == 0) | (b == 0) | (c == 0) raise TriangleError, "Sides have to be a postive number" if (a < 0) | (b < 0) | (c < 0) raise TriangleError, "Two sides can never be less than the sum of one side" if ((a + b) < c) | ((a + c) < b) | ((b + c) < a) raise TriangleError, "Two sides can never be equal one side" if ((a + b) == c) | ((a + c) == b) | ((b + c) == a) return :equilateral if (a == b) & (a == c) & (b == c) return :isosceles if (a == b) | (a == c) | (b == c) return :scalene end # Error class used in part 2. No need to change this code. class TriangleError < StandardError end 

你必须检查新创build的三angular形不会打破“三angular形不平等”。 你可以通过这个小公式来保证这一点。

 if !((ab).abs < c && c < a + b) raise TriangleError end 

当你得到错误:

 <TriangleError> exception expected but none was thrown. 

你的代码可能在这个文件中创build一个正则三angular形的时候抛出一个exception。 about_triangle_project.rb

对于Koan about_triangle_project_2.rb,不需要改变TriangleError类。 在三angular形algorithm之前插入此代码以通过所有testing:

 if ((a<=0 || b<=0 || c<=0)) raise TriangleError end if ((a+b<=c) || (b+c<=a) || (a+c<=b)) raise TriangleError end 

这一个确实花了一些时间。 但这是我的解决scheme

 def triangle(a, b, c) # WRITE THIS CODE raise TriangleError, "All sides must be positive number" if a <= 0 || b <= 0 || c <= 0 raise TriangleError, "Impossible triangle" if ( a + b + c - ( 2 * [a,b,c].max ) <= 0 ) if(a == b && a == c) :equilateral elsif (a == b || b == c || a == c) :isosceles else :scalene end end 

这是我的版本… 🙂

 def triangle(a, b, c) if a <= 0 || b <= 0 || c <= 0 raise TriangleError end if a + b <= c || a + c <= b || b + c <= a raise TriangleError end return :equilateral if a == b && b == c return :isosceles if a == b || a == c || b == c return :scalene if a != b && a != c && b != c end 

这是我结束了。 这是上述几个例子与我自己独特的三angular不平等例外的组合(它也考虑退化的情况)。 似乎工作。

 def triangle(a, b, c) raise TriangleError if [a,b,c].min <= 0 raise TriangleError if [a,b,c].sort.reverse.reduce(:-) >= 0 return :equilateral if a == b && b == c return :isosceles if a == b || a == c || b == c return :scalene end 

这是我的优雅的答案,从上面的意见有很多的帮助

 def triangle(a, b, c) test_tri = [a,b,c] if test_tri.min <=0 raise TriangleError end test_tri.sort! if test_tri[0]+ test_tri[1] <= test_tri[2] raise TriangleError end if a == b and b == c :equilateral elsif a != b and b != c and a != c :scalene else :isosceles end end 
  #(1)Any zero or -ve values if [a,b,c].any? { |side_length| side_length <= 0 } raise TriangleError end #(2)Any side of a triangle must be less than the sum of the other two sides # a < b+c, b < a+c and c < a+ba valid triangle # a >= b+c, b >= a+c and c >= a+b an invalid triangle total_of_side_lengths = [a,b,c].inject {|total,x| total += x} if [a,b,c].any? { |side_length| side_length >= (total_of_side_lengths - side_length)} raise TriangleError end 

不是这个问题需要另一个答案; 不过,我认为这是最简单和最可读的解决scheme。 感谢所有那些在我之前。

 def triangle(a, b, c) a, b, c = [a, b, c].sort raise TriangleError, "all sides must > 0" unless [a, b, c].min > 0 raise TriangleError, "2 smaller sides together must the > 3rd side" unless a + b > c return :equilateral if a == b && a == c return :isosceles if a == b || a == c || b == c return :scalene end # Error class used in part 2. No need to change this code. class TriangleError < StandardError end 

莱昂赢得花哨的优雅,Benji为他的知识Array API。 这是我粗暴的优雅的答案:

 def triangle(a, b, c) [a, b, c].each { | side | raise TriangleError, "Sides must be positive" unless side > 0 } raise TriangleError, "Two sides can never be less than or equal to third side" if ((a + b) <= c) | ((a + c) <= b) | ((b + c) <= a) return :equilateral if (a == b) && (b == c) return :isosceles if (a == b) || (b == c) || (a == c) return :scalene end 

无需为任何挑战更改TriangleError代码。 你只需要检查无效的三angular形,如果三angular形不是三angular形就会引起错误。

 def triangle(a, b, c) if a==0 && b==0 && c==0 raise TriangleError, "This isn't a triangle" end if a <0 or b < 0 or c <0 raise TriangleError, "Negative length - thats not right" end if a + b <= c or a + c <= b or b + c <= a raise TriangleError, "One length can't be more (or the same as) than the other two added together. If it was the same, the whole thing would be a line. If more, it wouldn't reach. " end # WRITE THIS CODE if a == b and b == c return :equilateral end if (a==b or b == c or a == c) return :isosceles end :scalene end 

在StackOverflow上有一些非常出色的人…每当我访问时,都会想起我:D只是为了对话,这里是我提出的解决scheme:

 def triangle(a, b, c) raise TriangleError if [a,b,c].min <= 0 x,y,z = [a,b,c].sort raise TriangleError if x + y <= z equal_sides = 0 equal_sides +=1 if a == b equal_sides +=1 if a == c equal_sides +=1 if b == c # Note that equal_sides will never be 2. If it hits 2 # of the conditions, it will have to hit all 3 by the law # of associativity return [:scalene, :isosceles, nil, :equilateral][equal_sides] end 

你以前的三angular方法应该出现在这里

 class TriangleError < StandardError end def triangle(x,y,z) if(x>=y+z||y>=x+z||z>=x+y) raise TriangleError,"impossible triangle" elsif(x==0&&y==0&&z==0)||(x<0||y<0||z<0) raise TriangleError,"length cannot be zero or negative" elsif(x==y&&x==z) :equilateral elsif(x==y||y==z||x==z) :isosceles else :scalene end end 

这是我的解决scheme…老实说,我想不出一个更简洁和可读的!

 def triangle(a, b, c) raise TriangleError unless a > 0 && b > 0 && c > 0 raise TriangleError if a == b && a + b <= c raise TriangleError if a == c && a + c <= b return :equilateral if a == b && b == c return :isosceles if a == b || b == c || c == a :scalene end 

规则:

  1. 大小必须> 0

  2. 任何两面的总数,必须大于第三

码:

 raise TriangleError if ( [a,b,c].any? {|x| (x <= 0)} ) or ( ((a+b)<=c) or ((b+c)<=a) or ((a+c)<=b)) [:equilateral, :isosceles, :scalene].fetch([a,b,c].uniq.size - 1) 

无需编写TriangleError方法。 它说'不需要改变这个代码',所以我不会改变它。 我固执己见

4lines射击它,很干净。

  def triangle(a, b, c) if(a * b * c <= 0) || (( (a + c)<=b) || ((a + b)<=c)||((b + c)<=a) ) raise TriangleError else return ((a == b && b == c && a == c)? :equilateral:(((a == b)||(b == c)||(a == c))? :isosceles: :scalene)) end end # Error class used in part 2. No need to change this code. class TriangleError < StandardError end 
 def triangle(a, b, c) raise TriangleError if [a, b, c].min <= 0 raise TriangleError if [a, b, c].max * 2 >= [a, b, c].reduce(:+) if a == b && b == c :equilateral elsif a == b || b == c || c == a :isosceles else :scalene end end