Rebol3 Code Examplex
Heronian triangles
Find triangles with integer side lengths and integer area using Heron’s formula and number-theoretic constraints.
Rebol [
title: "Rosetta code: Heronian triangles"
file: %Heronian_triangles.r3
url: https://rosettacode.org/wiki/Heronian_triangles
]
heronian-triangles: function/with [
"Find all primitive Heronian triangles up to side length mx"
mx [integer!]
][
triangles: copy []
repeat c mx [ ; c is longest side
repeat b c [ ; b <= c
a: max 1 c - b + 1 ; triangle inequality lower bound for a
while [a <= b][ ; a <= b <= c (canonical order)
if all [
heronian? area: hero a b c ; integer area > 0
1 = gcd-list reduce [a b c] ; primitive: no common factor
][
repend/only triangles [ ; store as [a b c perimeter area]
a b c a + b + c to integer! area
]
]
++ a
]
]
]
triangles
][
hero: function [
;; Heron's formula: area of triangle from side lengths
a [integer!] b [integer!] c [integer!]
][
s: (a + b + c) / 2.0 ; semi-perimeter
sqrt s * (s - a) * (s - b) * (s - c)
]
heronian?: function [
;; True if x is a positive integer (i.e. area is whole number)
x [number!]
][
all [x > 0 x = round/ceiling x]
]
gcd-list: function [
;; Greatest common divisor of a list of integers
list [block!]
][
g: list/1
foreach x next list [g: gcd g x] ; fold gcd over list
g
]
]
print-table: function [title [string!] rows [block!]][
"Print triangles as a formatted table with header"
print as-yellow title
print-hline/with/width #"=" 50
printf [5 5 5 15 15]["A" "B" "C" "Perimeter" "Area"]
print-hline/with/width #"-" 50
foreach row rows [ printf [5 5 5 15 15] row ]
print ""
]
triangles: heronian-triangles 200
print ["Number of Heronian triangles:" length? triangles]
print ""
;; Sort by area, then perimeter, then shortest side
sort/compare triangles func [x y][
(x/5 * 10000 + (x/4 * 100) + x/1) < (y/5 * 10000 + (y/4 * 100) + y/1)
]
print-table "Ordered list of first ten Heronian triangles:"
copy/part triangles 10
;; Filter to area = 210, keeping copy so triangles block is not modified
print-table "Ordered list of Heronian triangles with area 210:"
remove-each row copy triangles [row/5 != 210]
Output:
Number of Heronian triangles: 517
Ordered list of first ten Heronian triangles:
==================================================
A B C Perimeter Area
--------------------------------------------------
3 4 5 12 6
5 5 6 16 12
5 5 8 18 12
4 13 15 32 24
5 12 13 30 30
9 10 17 36 36
3 25 26 54 36
7 15 20 42 42
10 13 13 36 60
8 15 17 40 60
Ordered list of Heronian triangles with area 210:
==================================================
A B C Perimeter Area
--------------------------------------------------
17 25 28 70 210
20 21 29 70 210
12 35 37 84 210
17 28 39 84 210
7 65 68 140 210
3 148 149 300 210