Подтвердить что ты не робот

Ruby Koan 151, делающий исключения

Я иду через рубиновые коаны, я на 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 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

Я вне растерянности - любая помощь вообще будет очень оценена!

EDIT: Чтобы завершить этот коан, мне нужно поместить что-то в класс TriangleError, но я понятия не имею, что

ОБНОВЛЕНИЕ: вот что говорит koan karma:

<TriangleError> exception expected but none was thrown.
4b9b3361

Ответ 1

  • Треугольник не должен иметь никаких сторон длины 0. Если это так, это либо отрезок линии, либо точка, в зависимости от того, сколько сторон равно 0.
  • Отрицательная длина не имеет смысла.
  • Любые две стороны треугольника должны содержать не более трех сторон.
  • См. 3, и сосредоточьтесь на "больше".

Вам не нужно менять код TriangleError, AFAICS. Похоже, ваш синтаксис просто немного дурацкий. Попробуйте изменить

raise new.TriangleError

к

raise TriangleError, "why the exception happened"

Кроме того, вы должны тестировать значения (и бросать исключения), прежде чем что-либо делать с ними. Переместите материал исключения в начало функции.

Ответ 2

Вы забыли случай, когда 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

Ответ 3

Закончено:

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

Спасибо комментаторам здесь:)

Ответ 4

Мне нравится ответ Кори. Но мне интересно, есть ли какие-либо причины или что-то, что можно получить, имея четыре теста, когда у вас может быть два:

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)

Ответ 5

Вам не нужно изменять Исключение. Что-то вроде этого должно работать;

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

Ответ 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

Ответ 7

Вы определенно не обновляете класс TriangleError - я сам застрял на себе. Я думаю, мне нужно использовать здесь теорему 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

Мне нужен метод, который анализировал все аргументы эффективно вместо того, чтобы полагаться на порядок, указанный в тестовых утверждениях.

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

Надеюсь, это поможет другим понять, что существует более одного способа кошки кошки.

Ответ 9

Попытайтесь понять, что я должен делать с 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

Ответ 10

Я не думаю, что я вижу это здесь.

Я считаю, что все незаконные условия треугольника подразумевают, что самая длинная сторона не может превышать половины общего числа. то есть:

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

Ответ 11

Я закончил с этим кодом:

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

Вы также можете попробовать исключить исключение с помощью:

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

Ответ 13

Действительно, в следующем коде условие a <= 0 избыточно. a + b всегда будет меньше c, если a < 0, и мы знаем, что b < с

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

Ответ 14

Вот что я написал, и все это работало нормально.

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

Ответ 15

Вы должны проверить, что новый созданный треугольник не нарушает "неравенство треугольника". Вы можете убедиться в этом по этой маленькой формуле.

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

Когда вы получите сообщение об ошибке:

<TriangleError> exception expected but none was thrown.

Ваш код, вероятно, бросает исключение, создавая правильный треугольник в этом файле. about_triangle_project.rb

Ответ 16

Для 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

Ответ 17

Это заняло некоторое время мозга. Но вот мое решение

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

Ответ 18

Вот моя версия...: -)

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

Ответ 19

Вот что я закончил. Это своего рода сочетание нескольких из приведенных выше примеров с моим собственным уникальным признаком исключения треугольника (оно также рассматривает вырожденный случай). Кажется, работает.

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

Ответ 20

Вот мой изящный ответ, с большой помощью от комментариев выше

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

Ответ 21

  #(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

Ответ 22

Не то, чтобы этот вопрос нуждался в другом ответе; однако, я думаю, что это самое простое и читаемое решение. Спасибо всем, кто передо мной.

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

Ответ 23

Леон выигрывает на элегантной элегантности, Бенджи за свои знания API Array. Вот мой грубый элегантный ответ:

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

Ответ 24

Нет необходимости изменять код 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

Ответ 25

В 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 

Ответ 26

ваш предыдущий метод треугольника должен появиться здесь

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

Ответ 27

Вот мое решение... честно говоря, я не могу придумать более краткий и понятный!

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

Ответ 28

Правила:

  • размер должен быть > 0

  • Всего двух сторон, должно быть больше, чем 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)

Ответ 29

Не нужно писать метод 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

Ответ 30

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