class Triangle(a, b, c) { has (sides, perimeter, area) method init { sides = [a, b, c].sort perimeter = [a, b, c].sum var s = (perimeter / 2) area = sqrt(s * (s - a) * (s - b) * (s - c)) } method is_valid(a,b,c) { var (short, middle, long) = [a, b, c].sort...; (short + middle) > long } method is_heronian { area == area.to_i } method <=>(other) { [area, perimeter, sides] <=> [other.area, other.perimeter, other.sides] } method to_s { "%-11s%6d%8.1f" % (sides.join('x'), perimeter, area) } } var (max, area) = (200, 210) var prim_triangles = [] for a in (1..max) { for b in (a..max) { for c in (b..max) { next if (Math.gcd(a, b, c) > 1) prim_triangles << Triangle(a, b, c) if Triangle.is_valid(a, b, c) } } } var sorted = prim_triangles.grep{.is_heronian}.sort say "Primitive heronian triangles with sides upto #{max}: #{sorted.size}" say "\nsides perim. area" say sorted.first(10).join("\n") say "\nTriangles with an area of: #{area}" sorted.each{|tr| say tr if (tr.area == area)}