Ruby Koan 151提出异常

时间:2010-09-30 19:39:48

标签: ruby geometry

我正在浏览红宝石公案,我在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类中添加一些东西 - 但我不知道是什么

更新:这是koan karma所说的:

<TriangleError> exception expected but none was thrown.

37 个答案:

答案 0 :(得分:48)

  1. 三角形的长度不应为0.如果是,则为线段或点,具体取决于边数为0。
  2. 负长度没有意义。
  3. 三角形的任何两边应该加起来超过第三边。
  4. 请参阅3,并关注“更多”。
  5. 您不需要更改TriangleError代码AFAICS。看起来你的语法有点古怪。尝试更改

    raise new.TriangleError
    

    raise TriangleError, "why the exception happened"
    

    此外,您应该在对它们执行任何操作之前测试值(并抛出异常)。将异常内容移动到函数的开头。

答案 1 :(得分:30)

你忘了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

答案 2 :(得分:11)

结束这样做:

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

感谢评论者:)

答案 3 :(得分:9)

我喜欢Cory的回答。但是我想知道,如果你有两个测试,有什么理由可以获得任何理由或什么:

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)

答案 4 :(得分:7)

您无需修改​​例外。这样的事情应该有效;

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

答案 5 :(得分:6)

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

答案 6 :(得分:4)

在尝试了解我必须用koan 151做什么之后,我在第一篇文章中得到了它,并且检查每个人的解决方案得到很多乐趣:) ...这是我的:

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的一种非常有趣的方式

答案 7 :(得分:3)

你绝对不会更新Triangle Error类 - 我自己被困在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

答案 8 :(得分:3)

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

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

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

答案 9 :(得分:3)

我想要一个有效解析所有参数的方法,而不是依赖于测试断言中给出的顺序。

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

希望这有助于其他人意识到有一种方法可以给猫皮肤。

答案 10 :(得分:2)

您还可以尝试使用以下命令来实例:

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

答案 11 :(得分:2)

我最终得到了这段代码:

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 

我不喜欢第二个条件/加注,但我不确定如何进一步改善它。

答案 12 :(得分:2)

实际上在以下代码中,条件a&lt; = 0是多余的。如果a&lt; a + b将始终小于c。 0,我们知道b&lt; ç

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

答案 13 :(得分:1)

这是我写的内容,一切正常。

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

答案 14 :(得分:1)

def triangle(a, b, c)

  sides = a, b, c # Assigns variable signs (array) to all arguments.
  begin

  raise TriangleError if sides.inject(:+) <= 0 # Raise an error if all sides added together are less than or equal to 0. (the triangle would be invalid).
  raise TriangleError if sides.any?(&:negative?) #Raise an error if there are any negative sides.
  sides.each {|side| (side < (sides.inject(:+) - side) ? nil : (raise TriangleError))} # For the final check, Raise an error if any single side is greater than the other two sides added together. It can be broken down like this if side is less than (remaining sides - side we're comparing) raise an error, else, nil. 

  return :equilateral if sides.uniq.length == 1
  return :isosceles   if sides.uniq.length == 2
  return :scalene     if sides.uniq.length == 3

  resuce TriangleError
  end
end

答案 15 :(得分:1)

不是这个问题需要另一个答案;但是,我认为这是最简单,最易读的解决方案。感谢我之前的所有人。

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

答案 16 :(得分:1)

  #(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+b  a  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

答案 17 :(得分:1)

您必须检查新创建的三角形是否不会破坏“三角形不等式”。你可以通过这个小公式确保这一点。

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

当您收到错误:

<TriangleError> exception expected but none was thrown.

在此文件中创建常规三角形时,您的代码可能会抛出异常。 about_triangle_project.rb

答案 18 :(得分:1)

这是我优雅的答案,在上面的评论中提供了很多帮助

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

答案 19 :(得分:1)

对于Koan about_triangle_project_2.rb,无需更改TriangleError类。在三角形算法之前插入此代码以传递所有测试:

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

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

答案 20 :(得分:1)

这是我的版本......: - )

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

答案 21 :(得分:1)

这个确实占用了一些大脑时间。但这是我的解决方案

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

答案 22 :(得分:1)

这就是我最终的结果。它有点是上面几个例子的组合,我对三角不等式异常有独特的看法(它也考虑了退化情况)。似乎工作。

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

答案 23 :(得分:0)

最简单的解决方案!

  def triangle(a, b, c)
  #This would check for if the numbers are negative or 0.
  if a <= 0 || b <= 0 || c <= 0 
    raise TriangleError
  end
  #This would check if the two sides of a triangle are greater than the remaining side.
  if a + b <= c  || a + c <= b ||  b + c <= a
    raise TriangleError
  end 

  if a == b && b = c
    :equilateral
  elsif a == b || a == c || b == c 
    :isosceles
  else 
    :scalene
  end
end

感谢所有美丽的人的回答,我已经检查了他们,我会说不需要更改 TriangleError 代码。我们需要检查无效的三角形,如果三角形不是,则引发错误。

答案 24 :(得分:0)

StackOverflow上有一些非常出色的人......我每次访问时都会想到这一点:D 只是为了对话,这是我提出的解决方案:

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 

答案 25 :(得分:0)

我的解决方案,我认为这是更易读的解决方案之一:

def triangle(a, b, c)
  a, b, c = [a, b, c].sort
  if a <= 0 or c >= a + b
    raise TriangleError
  end
  case [a, b, c].uniq.length
  when 1
    :equilateral
  when 2
    :isosceles
  when 3
    :scalene
  end
end

答案 26 :(得分:0)

您可以使用此公式并验证所有案例:

  • a + b&gt; ç
  • a + c&gt; B'/ LI>
  • b + c&gt;一个

你的代码如下:

def triangle(a, b, c)
  # Validate the triangle
 raise TriangleError, "The triangle is not valid" unless (a + b) > c && (a + c) > b && (b + c) > a

 if a === b && b === c
  :equilateral
 elsif a === b || a === c || b === c
  :isosceles
 else
  :scalene
 end
end

答案 27 :(得分:0)

这是我的解决方案: -

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

希望它有所帮助。

答案 28 :(得分:0)

错误检查试图达到三角形的标准:

if (a <= 0 || b <= 0 || c <= 0)
    raise TriangleError,"All lengths must be positive"
end 

args=[a,b,c].sort #this lets us get at the longest side of the triangle

unless ( args[0]+args[1] > args[2] )
    raise TriangleError,"Longest length may not be greater than the sum of the other lengths"
end 

if (args[0]-args[1] > args[2])
    raise TriangleError,"Longest length must be greater than the difference of the other two lengths"
end 

有更优雅和简洁的方法来执行此错误检查,但我认为应该明确如何检查4个主要标准。 我实际上将2个标准卷入了一个检查。例如。没有边可能是负面的,没有边可能是0。

使用splat运算符作为参数是一种很好的方法来确保你有一个数组而没有明确地形成一个,但我不喜欢它,因为这意味着你还应该添加一个检查以确保有3个参数,这是隐含的。

答案 29 :(得分:0)

我能提出的最小解决方案。

这将通过测试,但是,如果阵列比它应该更长,它将不会抱怨。容易测试但似乎并不完全需要。

  1. def(sides*) splat(将输入转换为数组)
  2. raise TriangleError if ... or ...如果两者都为真,则提出错误
  3. sides.sort!对列表进行排序。这很重要,因为两个语句依赖于正在排序的列表,这意味着它只执行一次。
  4. sides.sort![0] <=0获取最小元素,如果大于0,则所有其他元素都将为。
  5. sides.reverse.reduce(:-) >=0最大元素减去较小的两个,如果超过0那么最大的一方比另外两个大。
  6. sides.uniq.size-1获取唯一边数(减1)
  7. [:e,:i,:s].fetch(sides.uniq.size-1)从数组中获取相应的元素(并返回)。

    def triangle(*sides)
      raise TriangleError if sides.sort![0] <=0 or sides.reverse.reduce(:-) >=0
      [:equilateral, :isosceles, :scalene].fetch(sides.uniq.size - 1)
    end
    

答案 30 :(得分:0)

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

答案 31 :(得分:0)

无需编写TriangleError方法。它说'不需要改变这个代码',所以我根本不会改变它。像我一样顽固。

4行拍摄它,很好干净。

    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

答案 32 :(得分:0)

规则:

  1. 尺寸必须> 0

  2. 任何2个方面的总数,必须大于第3个

  3. 代码:

    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)
    

答案 33 :(得分:0)

这是我的解决方案......老实说,我想不出更简洁,更易读的一个!

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

答案 34 :(得分:0)

Leon以优雅的姿态赢得了胜利,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

答案 35 :(得分:0)

您之前的三角形方法应该出现在这里

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

答案 36 :(得分:0)

无需更改任何挑战的TriangleError代码。您只需检查无效三角形,如果三角形不是,则引发错误。

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