Ruby Koan 151 soulevant des exceptions

Je traverse les rbuy koans, je suis sur 151 et je viens de bash un mur de briques.

Voici le koan:

# You need to write the sortingangle method in the file 'sortingangle.rb' require 'sortingangle.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 

Puis en sortingangle.rb nous avons:

 def sortingangle(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 

Je suis plus confus – toute aide serait très appréciée!

EDIT: Pour compléter ce koan, je dois mettre quelque chose dans la classe TriangleError – mais je n’ai aucune idée de ce que

MISE À JOUR: Voici ce que dit le koan karma:

  exception expected but none was thrown. 

  1. Un sortingangle ne doit pas avoir de côté de longueur 0. Si c’est le cas, c’est soit un segment de ligne, soit un point, selon le nombre de côtés 0.
  2. La longueur négative n’a pas de sens.
  3. Tous les deux côtés d’un sortingangle doivent représenter plus que le troisième côté.
  4. Voir 3 et se concentrer sur le “plus”.

Vous ne devriez pas avoir besoin de changer le code TriangleError, AFAICS. On dirait que votre syntaxe est un peu farfelue. Essayez de changer

 raise new.TriangleError 

à

 raise TriangleError, "why the exception happened" 

En outre, vous devriez tester les valeurs (et lancer des exceptions) avant de les utiliser. Déplace les éléments d’exception au début de la fonction.

Vous avez oublié le cas où a, b ou c sont négatifs:

 def sortingangle(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 

Terminé en faisant ceci:

 def sortingangle(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 

Merci aux commentateurs ici 🙂

J’aime la réponse de Cory. Mais je me demande s’il y a une raison ou quoi que ce soit à gagner en ayant quatre tests, alors que vous pourriez en avoir deux:

 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) 

Vous n’avez pas besoin de modifier l’exception. Quelque chose comme ça devrait fonctionner;

 def sortingangle(*args) args.sort! raise TriangleError if args[0] + args[1] <= args[2] || args[0] <= 0 [nil, :equilateral, :isosceles, :scalene][args.uniq.length] end 
 def sortingangle(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 

Vous n’avez certainement pas mis à jour la classe TriangleError – je suis bloqué sur 152 moi-même. Je pense que je dois utiliser le théorème de pythag ici.

 def sortingangle(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 

Je voulais une méthode qui analysait efficacement tous les arguments au lieu de s’appuyer sur l’ordre donné dans les assertions de test.

 def sortingangle(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 sortingangle 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 

Espérons que cela aide d’autres personnes à réaliser qu’il y a plus d’une façon de peler un chat.

Après avoir essayé de comprendre ce que je dois faire avec Koan 151, je l’ai eu avec les premiers messages, et je me suis bien amusé à vérifier la solution de tout le monde 🙂 … voici la mine:

 def sortingangle(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 est une manière très intéressante d'apprendre le Ruby

Je ne pense pas que je vois celui-ci ici, pour le moment.

Je crois que toutes les conditions de sortingangle illégales impliquent que le plus long côté ne peut pas représenter plus de la moitié du total. c’est à dire:

 def sortingangle(a, b, c) fail TriangleError, "Illegal sortingangle: [#{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 

J’ai fini avec ce code:

 def sortingangle(a, b, c) raise TriangleError, "impossible sortingangle" 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 

Je n'aime pas la deuxième condition / relance, mais je ne sais pas comment l'améliorer davantage.

Vous pouvez également essayer d’injecter l’exception avec:

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

En fait, dans le code suivant, la condition a <= 0 est redondante. a + b sera toujours inférieur à c si a <0 et on sait que b

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

Voici ce que j’ai écrit et tout a bien fonctionné.

 def sortingangle(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 

Vous devez vérifier que le nouveau sortingangle créé ne rompt pas “l’inégalité de sortingangle”. Vous pouvez assurer cela par cette petite formule.

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

Lorsque vous obtenez l'erreur:

  exception expected but none was thrown. 

Votre code génère probablement une exception lors de la création d'un sortingangle régulier dans ce fichier. about_sortingangle_project.rb

Pour Koan about_sortingangle_project_2.rb, il n’est pas nécessaire de modifier la classe TriangleError. Insérez ce code avant votre algorithme de sortingangle pour réussir tous les tests:

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

Celui-ci a pris du temps de cerveau. Mais voici ma solution

 def sortingangle(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 

Voici ma version … 🙂

 def sortingangle(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 

C’est ce que j’ai fini avec. C’est en quelque sorte une combinaison de quelques-uns des exemples ci-dessus avec mon approche unique de l’exception de l’inégalité du sortingangle (elle considère également le cas dégénéré). Semble travailler.

 def sortingangle(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 

Voici ma réponse élégante, avec beaucoup d’aide des commentaires ci-dessus

 def sortingangle(a, b, c) test_sorting = [a,b,c] if test_sorting.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 sortingangle 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 

Non que cette question ait besoin d’une autre réponse; Cependant, je pense que c’est la solution la plus simple et la plus lisible. Merci à tous ceux qui m’ont précédé.

 def sortingangle(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 
 def sortingangle(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 

Leon gagne à l’élégance de fantaisie, Benji pour sa connaissance de l’API Array. Voici ma réponse élégante brute:

 def sortingangle(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 

Pas besoin de changer le code TriangleError pour l’un ou l’autre défi. Il suffit de vérifier les sortingangles non valides et de relever l’erreur si le sortingangle ne l’est pas.

 def sortingangle(a, b, c) if a==0 && b==0 && c==0 raise TriangleError, "This isn't a sortingangle" 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 

Il y a des gens absolument shinys sur StackOverflow … Cela me rappelle chaque fois que je visite: D Juste pour consortingbuer à la conversation, voici la solution que j’ai trouvée:

 def sortingangle(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 

Voici ma solution … honnêtement, je ne peux pas penser à une version plus concise et lisible!

 def sortingangle(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 

Règles:

  1. la taille doit être> 0

  2. Total des 2 côtés, doit être plus grand que le 3ème

Code:

 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) 

Pas besoin d’écrire la méthode TriangleError. Il dit “Pas besoin de changer ce code”, donc je ne le changerai pas du tout. Têtu comme je suis.

4lines a tiré, gentil et propre.

  def sortingangle(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 sortingangle(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