Rosetta Code

Heronian triangles

Search a small side-length range for Heronian triangles with integer area.

Medium View source
Source rosettacode/popular/heronian_triangles.vibe
# title: Heronian triangles
# source: https://rosettacode.org/wiki/Heronian_triangles
# category: Rosetta Code
# difficulty: Medium
# summary: Search a small side-length range for Heronian triangles with integer area.
# tags: popular, geometry, search, triangles
# vibe: 0.4

def isqrt(value)
  if value < 2
    return value
  end

  low = 1
  high = (value / 2) + 1
  answer = 1

  while low <= high
    middle = (low + high) / 2
    square = middle * middle

    if square == value
      return middle
    elsif square < value
      answer = middle
      low = middle + 1
    else
      high = middle - 1
    end
  end

  answer
end

def heronian_triangles(limit, count)
  values = []
  a = 1

  while a <= limit && values.length < count
    b = a
    while b <= limit && values.length < count
      c = b
      while c <= limit && values.length < count
        if a + b > c
          area_term = (a + b + c) * (-a + b + c) * (a - b + c) * (a + b - c)
          if area_term > 0
            root = isqrt(area_term)
            if root * root == area_term && root % 4 == 0
              values << { sides: [a, b, c], area: root / 4 }
            end
          end
        end
        c = c + 1
      end
      b = b + 1
    end
    a = a + 1
  end

  values
end

def heronian_area(a, b, c)
  area_term = (a + b + c) * (-a + b + c) * (a - b + c) * (a + b - c)
  root = isqrt(area_term)
  root / 4
end

def run
  [[3, 4, 5], [5, 5, 6], [5, 12, 13], [8, 15, 17]].map do |sides|
    { sides:, area: heronian_area(sides[0], sides[1], sides[2]) }
  end
end
Output
Press run to execute run from this example.