Heronian triangles: Difference between revisions

m
m (→‎using iSQRT: added whitespace, aligned the END with the DO loop.)
m (→‎{{header|Wren}}: Minor tidy)
 
(42 intermediate revisions by 21 users not shown)
Line 36:
<small>'''Note''': when generating triangles it may help to restrict</small> <math>a <= b <= c</math>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F gcd(=u, =v)
L v != 0
(u, v) = (v, u % v)
R abs(u)
 
F hero(a, b, c)
V s = (a + b + c) / 2
V a2 = s * (s - a) * (s - b) * (s - c)
R I a2 > 0 {sqrt(a2)} E 0
 
F is_heronian(a, b, c)
V x = hero(a, b, c)
R x > 0 & fract(x) == 0
 
F gcd3(x, y, z)
R gcd(gcd(x, y), z)
 
V MAXSIDE = 200
[(Int, Int, Int)] h
L(x) 1..MAXSIDE
L(y) x..MAXSIDE
L(z) y..MAXSIDE
I (x + y > z) & gcd3(x, y, z) == 1 & is_heronian(x, y, z)
h [+]= (x, y, z)
 
h = sorted(h, key' x -> (hero(x[0], x[1], x[2]), sum(x), (x[2], x[1], x[0])))
 
print(‘Primitive Heronian triangles with sides up to #.: #.’.format(MAXSIDE, h.len))
print("\nFirst ten when ordered by increasing area, then perimeter, then maximum sides:")
print(h[0.<10].map3((x, y, z) -> ‘ #14 perim: #3 area: #.’.format(String((x, y, z)), x + y + z, hero(x, y, z))).join("\n"))
print("\nAll with area 210 subject to the previous ordering:")
print(h.filter3((x, y, z) -> hero(x, y, z) == 210).map3((x, y, z) -> ‘ #14 perim: #3 area: #.’.format(String((x, y, z)), x + y + z, hero(x, y, z))).join("\n"))</syntaxhighlight>
 
{{out}}
<pre>
Primitive Heronian triangles with sides up to 200: 517
 
First ten when ordered by increasing area, then perimeter, then maximum sides:
(3, 4, 5) perim: 12 area: 6
(5, 5, 6) perim: 16 area: 12
(5, 5, 8) perim: 18 area: 12
(4, 13, 15) perim: 32 area: 24
(5, 12, 13) perim: 30 area: 30
(9, 10, 17) perim: 36 area: 36
(3, 25, 26) perim: 54 area: 36
(7, 15, 20) perim: 42 area: 42
(10, 13, 13) perim: 36 area: 60
(8, 15, 17) perim: 40 area: 60
 
All with area 210 subject to the previous ordering:
(17, 25, 28) perim: 70 area: 210
(20, 21, 29) perim: 70 area: 210
(12, 35, 37) perim: 84 area: 210
(17, 28, 39) perim: 84 area: 210
(7, 65, 68) perim: 140 area: 210
(3, 148, 149) perim: 300 area: 210
</pre>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Containers.Indefinite_Ordered_Sets;
with Ada.Finalization;
with Ada.Text_IO; use Ada.Text_IO;
procedure Heronian is
package Int_IO is new Ada.Text_IO.Integer_IO(Integer);
use Int_IO;
-- ----- Some math...
function GCD (A, B : in Natural) return Natural is (if B = 0 then A else GCD (B, A mod B));
function Int_Sqrt (N : in Natural) return Natural is
R1 : Natural := N;
R2 : Natural;
begin
if N <= 1 then
return N;
end if;
loop
R2 := (R1+N/R1)/2;
if R2 >= R1 then
return R1;
end if;
R1 := R2;
end loop;
end Int_Sqrt;
-- ----- Defines the triangle with sides as discriminants and a constructor which will
-- compute its other characteristics
type t_Triangle (A, B, C : Positive) is new Ada.Finalization.Controlled with record
Is_Heronian : Boolean;
Perimeter : Positive;
Area : Natural;
end record;
 
overriding procedure Initialize (Self : in out t_Triangle) is
-- Let's stick to integer computations, therefore a modified hero's formula
-- will be used : S*(S-a)*(S-b)*(S-c) = (a+b+c)*(-a+b+c)*(a-b+c)*(a+b-c)/16
-- This will require long integers because at max side size, the product
-- before /16 excesses 2^31
Long_Product : Long_Long_Integer;
Short_Product : Natural;
begin
Self.Perimeter := Self.A + Self.B + Self.C;
Long_Product := Long_Long_Integer(Self.Perimeter)
* Long_Long_Integer(- Self.A + Self.B + Self.C)
* Long_Long_Integer( Self.A - Self.B + Self.C)
* Long_Long_Integer( Self.A + Self.B - Self.C);
Short_Product := Natural(Long_Product / 16);
Self.Area := Int_Sqrt (Short_Product);
Self.Is_Heronian := (Long_Product mod 16 = 0) and (Self.Area * Self.Area = Short_Product);
end Initialize;
-- ----- Ordering triangles with criteria (Area,Perimeter,A,B,C)
function "<" (Left, Right : in t_Triangle) return Boolean is
(Left.Area < Right.Area or else (Left.Area = Right.Area and then
(Left.Perimeter < Right.Perimeter or else (Left.Perimeter = Right.Perimeter and then
(Left.A < Right.A or else (Left.A = Right.A and then
(Left.B < Right.B or else (Left.B = Right.B and then
Left.C < Right.C))))))));
package Triangle_Lists is new Ada.Containers.Indefinite_Ordered_Sets (t_Triangle);
use Triangle_Lists;
 
-- ----- Displaying triangle characteristics
Header : constant String := " A B C Per Area" & ASCII.LF & "---+---+---+---+-----";
procedure Put_Triangle (Position : Cursor) is
Triangle : constant t_Triangle := Element(Position);
begin
Put(Triangle.A, 3);
Put(Triangle.B, 4);
Put(Triangle.C, 4);
Put(Triangle.Perimeter, 4);
Put(Triangle.Area, 6);
New_Line;
end Put_Triangle;
 
-- ----- Global variables
Triangles : Set := Empty_Set;
-- Instead of constructing two sets, or browsing all the beginning of the set during
-- the second output, start/end cursors will be updated during the insertions.
First_201 : Cursor := No_Element;
Last_201 : Cursor := No_Element;
 
procedure Memorize_Triangle (A, B, C : in Positive) is
Candidate : t_Triangle(A, B, C);
Position : Cursor;
Dummy : Boolean;
begin
if Candidate.Is_Heronian then
Triangles.Insert (Candidate, Position, Dummy);
if Candidate.Area = 210 then
First_201 := (if First_201 = No_Element then Position
elsif Position < First_201 then Position
else First_201);
Last_201 := (if Last_201 = No_Element then Position
elsif Last_201 < Position then Position
else Last_201);
end if;
end if;
end Memorize_Triangle;
begin
-- Loops restrict to unique A,B,C (ensured by A <= B <= C) with sides < 200 and for
-- which a triangle is constructible : C is not greater than B+A (flat triangle)
for A in 1..200 loop
for B in A..200 loop
for C in B..Integer'Min(A+B-1,200) loop
-- Filter non-primitive triangles
if GCD(GCD(A,B),C) = 1 then
Memorize_Triangle (A, B, C);
end if;
end loop;
end loop;
end loop;
Put_Line (Triangles.Length'Img & " heronian triangles found :");
Put_Line (Header);
Triangles.Iterate (Process => Put_Triangle'Access);
New_Line;
Put_Line ("Heronian triangles with area = 201");
Put_Line (Header);
declare
Position : Cursor := First_201;
begin
loop
Put_Triangle (Position);
exit when Position = Last_201;
Position := Next(Position);
end loop;
end;
end Heronian;</syntaxhighlight>
{{out}}
<pre> 517 heronian triangles found :
A B C Per 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</pre>
...
<pre>
Heronian triangles with area = 201
A B C Per 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</pre>
 
=={{header|ALGOL 68}}==
{{Trans|Lua}}
<langsyntaxhighlight lang="algol68"># mode to hold details of a Heronian triangle #
MODE HERONIAN = STRUCT( INT a, b, c, area, perimeter );
# returns the details of the Heronian Triangle with sides a, b, c or nil if it isn't one #
Line 121 ⟶ 339:
OD
END
END</langsyntaxhighlight>
{{out}}
<pre>
Line 151 ⟶ 369:
=={{header|ALGOL W}}==
{{Trans|Lua}}
<langsyntaxhighlight lang="algolw">begin
% record to hold details of a Heronian triangle %
record Heronian ( integer a, b, c, area, perimeter );
Line 247 ⟶ 465:
end
end
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 274 ⟶ 492:
3 148 149 210 300
</pre>
 
 
=={{header|AppleScript}}==
Line 281 ⟶ 498:
 
{{Trans|JavaScript}}
<langsyntaxhighlight AppleScriptlang="applescript">use framework "Foundation"
 
-- HERONIAN TRIANGLES --------------------------------------------------------
Line 557 ⟶ 774:
((ca's NSString's stringWithString:(str))'s ¬
capitalizedStringWithLocale:(ca's NSLocale's currentLocale())) as text
end toTitle</langsyntaxhighlight>
{{Out}}
<pre>Number of triangles found (with sides <= 200): 517
Line 584 ⟶ 801:
(7, 65, 68) 140 210
(3, 148, 149) 300 210</pre>
 
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">printTable: function [title, rows][
print title ++ ":"
print repeat "=" 60
 
prints pad.center "A" 10
prints pad.center "B" 10
prints pad.center "C" 10
prints pad.center "Perimeter" 15
print pad.center "Area" 15
print repeat "-" 60
 
loop rows 'row [
prints pad.center to :string row\0 10
prints pad.center to :string row\1 10
prints pad.center to :string row\2 10
prints pad.center to :string row\3 15
print pad.center to :string row\4 15
]
print ""
]
 
hero: function [a,b,c][
s: (a + b + c) // 2
return sqrt(s * (s-a) * (s-b) * (s-c))
]
 
heronian?: function [x]->
and? -> x > 0
-> x = ceil x
 
lst: []
mx: 200
 
loop 1..mx 'c ->
loop 1..c 'b ->
loop 1..b 'a [
area: hero a b c
if and? [heronian? area] [one? gcd @[a b c]]->
'lst ++ @[
@[a, b, c, a + b + c, to :integer area]
]
]
 
print ["Number of Heronian triangles:" size lst]
print ""
 
lst: arrange lst 'item ->
(item\4 * 10000) + (item\3 * 100) + max first.n:3 item
 
printTable "Ordered list of first ten Heronian triangles" first.n: 10 lst
printTable "Ordered list of Heronian triangles with area 210" select lst 'x -> x\4 = 210</syntaxhighlight>
 
{{out}}
 
<pre>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</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">Primitive_Heronian_triangles(MaxSide){
obj :=[]
loop, % MaxSide {
Line 604 ⟶ 904:
x := StrSplit(x, "`t"), y := StrSplit(y, "`t")
return x.1 > y.1 ? 1 : x.1 < y.1 ? -1 : x.2 > y.2 ? 1 : x.2 < y.2 ? -1 : 0
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">res := Primitive_Heronian_triangles(200)
loop, parse, res, `n, `r
{
Line 620 ⟶ 920:
. "`nResults for Area = 210:"
. "`n" "Area`tPerimeter`tSides`n" res3
return</langsyntaxhighlight>
Outputs:<pre>517 results found
 
Line 650 ⟶ 950:
----
'''IMPORTANT''': This is a C99 compatible implementation. May result in errors on earlier compilers.
<syntaxhighlight lang="c">
<lang C>
#include<stdlib.h>
#include<stdio.h>
Line 771 ⟶ 1,071:
return 0;
}
</syntaxhighlight>
</lang>
Invocation and output :
<pre>
Line 799 ⟶ 1,099:
149 x 148 x 3 300 210
</pre>
 
=={{header|C++}}==
{{Works with|C++11}}
<lang cpp>#include <algorithm>
#include <cmath>
#include <iostream>
#include <tuple>
#include <vector>
 
int gcd(int a, int b)
{
int rem = 1, dividend, divisor;
std::tie(divisor, dividend) = std::minmax(a, b);
while (rem != 0) {
rem = dividend % divisor;
if (rem != 0) {
dividend = divisor;
divisor = rem;
}
}
return divisor;
}
 
struct Triangle
{
int a;
int b;
int c;
};
 
int perimeter(const Triangle& triangle)
{
return triangle.a + triangle.b + triangle.c;
}
 
double area(const Triangle& t)
{
double p_2 = perimeter(t) / 2.;
double area_sq = p_2 * ( p_2 - t.a ) * ( p_2 - t.b ) * ( p_2 - t.c );
return sqrt(area_sq);
}
 
std::vector<Triangle> generate_triangles(int side_limit = 200)
{
std::vector<Triangle> result;
for(int a = 1; a <= side_limit; ++a)
for(int b = 1; b <= a; ++b)
for(int c = a+1-b; c <= b; ++c) // skip too-small values of c, which will violate triangle inequality
{
Triangle t{a, b, c};
double t_area = area(t);
if(t_area == 0) continue;
if( std::floor(t_area) == std::ceil(t_area) && gcd(a, gcd(b, c)) == 1)
result.push_back(t);
}
return result;
}
 
bool compare(const Triangle& lhs, const Triangle& rhs)
{
return std::make_tuple(area(lhs), perimeter(lhs), std::max(lhs.a, std::max(lhs.b, lhs.c))) <
std::make_tuple(area(rhs), perimeter(rhs), std::max(rhs.a, std::max(rhs.b, rhs.c)));
}
 
struct area_compare
{
bool operator()(const Triangle& t, int i) { return area(t) < i; }
bool operator()(int i, const Triangle& t) { return i < area(t); }
};
 
int main()
{
auto tri = generate_triangles();
std::cout << "There are " << tri.size() << " primitive Heronian triangles with sides up to 200\n\n";
 
std::cout << "First ten when ordered by increasing area, then perimeter, then maximum sides:\n";
std::sort(tri.begin(), tri.end(), compare);
std::cout << "area\tperimeter\tsides\n";
for(int i = 0; i < 10; ++i)
std::cout << area(tri[i]) << '\t' << perimeter(tri[i]) << "\t\t" <<
tri[i].a << 'x' << tri[i].b << 'x' << tri[i].c << '\n';
 
std::cout << "\nAll with area 210 subject to the previous ordering:\n";
auto range = std::equal_range(tri.begin(), tri.end(), 210, area_compare());
std::cout << "area\tperimeter\tsides\n";
for(auto it = range.first; it != range.second; ++it)
std::cout << area(*it) << '\t' << perimeter(*it) << "\t\t" <<
it->a << 'x' << it->b << 'x' << it->c << '\n';
}</lang>
{{out}}
<pre>There are 517 primitive Heronian triangles with sides up to 200
 
First ten when ordered by increasing area, then perimeter, then maximum sides:
area perimeter sides
6 12 5x4x3
12 16 6x5x5
12 18 8x5x5
24 32 15x13x4
30 30 13x12x5
36 36 17x10x9
36 54 26x25x3
42 42 20x15x7
60 36 13x13x10
60 40 17x15x8
 
All with area 210 subject to the previous ordering:
area perimeter sides
210 70 28x25x17
210 70 29x21x20
210 84 37x35x12
210 84 39x28x17
210 140 68x65x7
210 300 149x148x3</pre>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight Csharplang="csharp">using System;
using System.Collections.Generic;
 
Line 971 ⟶ 1,158:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Number of primitive Heronian triangles with sides up to 200: 517
Line 996 ⟶ 1,183:
7 65 68 140 210
3 148 149 300 210</pre>
 
=={{header|C++}}==
{{Works with|C++17}}
<syntaxhighlight lang="cpp">#include <tuple>
#include <vector>
#include <numeric>
#include <iostream>
#include <algorithm>
 
#include <cmath>
 
struct Triangle {
int a{};
int b{};
int c{};
 
[[nodiscard]] constexpr auto perimeter() const noexcept { return a + b + c; }
 
[[nodiscard]] constexpr auto area() const noexcept {
const auto p_2 = static_cast<double>(perimeter()) / 2;
const auto area_sq = p_2 * (p_2 - a) * (p_2 - b) * (p_2 - c);
return std::sqrt(area_sq);
}
};
 
 
auto generate_triangles(int side_limit = 200) {
std::vector<Triangle> result;
for(int a = 1; a <= side_limit; ++a)
for(int b = 1; b <= a; ++b)
for(int c = a + 1 - b; c <= b; ++c) // skip too-small values of c, which will violate triangle inequality
{
Triangle t{ a, b, c };
const auto t_area = t.area();
if (t_area == 0) continue;
if (std::floor(t_area) == std::ceil(t_area) && std::gcd(a, std::gcd(b, c)) == 1)
result.push_back(t);
}
return result;
}
 
bool compare(const Triangle& lhs, const Triangle& rhs) noexcept {
return std::make_tuple(lhs.area(), lhs.perimeter(), std::max(lhs.a, std::max(lhs.b, lhs.c))) <
std::make_tuple(rhs.area(), rhs.perimeter(), std::max(rhs.a, std::max(rhs.b, rhs.c)));
}
 
struct area_compare {
[[nodiscard]] constexpr bool operator()(const Triangle& t, int i) const noexcept { return t.area() < i; }
[[nodiscard]] constexpr bool operator()(int i, const Triangle& t) const noexcept { return i < t.area(); }
};
 
int main() {
auto tri = generate_triangles();
std::cout << "There are " << tri.size() << " primitive Heronian triangles with sides up to 200\n\n";
 
std::cout << "First ten when ordered by increasing area, then perimeter, then maximum sides:\n";
std::sort(tri.begin(), tri.end(), compare);
std::cout << "area\tperimeter\tsides\n";
for(int i = 0; i < 10; ++i)
std::cout << tri[i].area() << '\t' << tri[i].perimeter() << "\t\t" <<
tri[i].a << 'x' << tri[i].b << 'x' << tri[i].c << '\n';
 
std::cout << "\nAll with area 210 subject to the previous ordering:\n";
auto range = std::equal_range(tri.begin(), tri.end(), 210, area_compare());
std::cout << "area\tperimeter\tsides\n";
for(auto it = range.first; it != range.second; ++it)
std::cout << (*it).area() << '\t' << (*it).perimeter() << "\t\t" <<
it->a << 'x' << it->b << 'x' << it->c << '\n';
}</syntaxhighlight>
{{out}}
<pre>There are 517 primitive Heronian triangles with sides up to 200
 
First ten when ordered by increasing area, then perimeter, then maximum sides:
area perimeter sides
6 12 5x4x3
12 16 6x5x5
12 18 8x5x5
24 32 15x13x4
30 30 13x12x5
36 36 17x10x9
36 54 26x25x3
42 42 20x15x7
60 36 13x13x10
60 40 17x15x8
 
All with area 210 subject to the previous ordering:
area perimeter sides
210 70 28x25x17
210 70 29x21x20
210 84 37x35x12
210 84 39x28x17
210 140 68x65x7
210 300 149x148x3</pre>
 
=={{header|CoffeeScript}}==
{{trans|JavaScript}}
<langsyntaxhighlight lang="coffeescript">heronArea = (a, b, c) ->
s = (a + b + c) / 2
Math.sqrt s * (s - a) * (s - b) * (s - c)
Line 1,045 ⟶ 1,325:
for i in list
if i[4] == 210
console.log i[0..2].join(' x ') + ', p = ' + i[3]</langsyntaxhighlight>
{{out}}
<pre>primitive Heronian triangles with sides up to 200: 517
Line 1,070 ⟶ 1,350:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.math, std.range, std.algorithm, std.numeric, std.traits, std.typecons;
 
double hero(in uint a, in uint b, in uint c) pure nothrow @safe @nogc {
Line 1,114 ⟶ 1,394:
"\nAll with area 210 subject to the previous ordering:".writeln;
showTriangles(h.filter!(t => t[].hero == 210));
}</langsyntaxhighlight>
{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517
Line 1,139 ⟶ 1,419:
210 140 7x65x68
210 300 3x148x149</pre>
=={{header|Delphi}}==
See [https://rosettacode.org/wiki/Heronian_triangles#Pascal Pascal].
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
;; returns quintuple (A s a b c)
;; or #f if not hero
Line 1,167 ⟶ 1,449:
(define (print-laurels H)
(writeln '🌿🌿 (length H) 'heroes '🌿🌿))
</syntaxhighlight>
</lang>
{{out}}
<pre>(define H (heroes))
Line 1,197 ⟶ 1,479:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">defmodule Heronian do
def triangle?(a,b,c) when a+b <= c, do: false
def triangle?(a,b,c) do
Line 1,232 ⟶ 1,514:
|> Enum.each(fn {a, b, c} ->
IO.puts "#{a}\t#{b}\t#{c}\t#{a+b+c}\t#{area_size}"
end)</langsyntaxhighlight>
 
{{out}}
Line 1,257 ⟶ 1,539:
 
=={{header|ERRE}}==
<syntaxhighlight lang="erre">
<lang ERRE>
PROGRAM HERON
 
Line 1,325 ⟶ 1,607:
END FOR
END PROGRAM
</syntaxhighlight>
</lang>
<pre>Number of triangles: 517
3 4 5 12 6
Line 1,346 ⟶ 1,628:
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: accessors assocs backtrack combinators.extras
combinators.short-circuit formatting io kernel locals math
math.functions math.order math.parser math.ranges mirrors qw
Line 1,407 ⟶ 1,689:
[ first10 nl ] [ area210= ] bi ;
MAIN: main</langsyntaxhighlight>
{{out}}
<pre>
Line 1,439 ⟶ 1,721:
=={{header|Fortran}}==
Earlier Fortran doesn't offer special functions such as SUM, PRODUCT and MAXVAL of arrays, nor the ability to create compound data aggregates such as STASH to store a triangle's details. Simple code would have to be used in the absence of such conveniences, and multiple ordinary arrays rather than an array of a compound data entity. Rather than attempt to create the candidate triangles in the desired order, the simple approach is to sort a list of triangles, and using an XNDX array evades tossing compound items about. Rather than create a procedure to do the sorting, a comb sort is not too much trouble to place in-line once. Further, since the ordering is based on a compound key, having only one comparison to code is a boon. The three-way-if statement is central to the expedient evaluation of a compound sort key, but this facility is deprecated by the modernists, with no alternative offered that avoids re-comparison of parts.
<syntaxhighlight lang="fortran">
<lang Fortran>
MODULE GREEK MATHEMATICIANS !Two millenia back and more.
CONTAINS
Line 1,547 ⟶ 1,829:
END DO !Just thump through the lot.
END
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,572 ⟶ 1,854:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' version 02-05-2016
' compile with: fbc -s console
 
Line 1,718 ⟶ 2,000:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>There are 517 Heronian triangles with sides <= 200
Line 1,750 ⟶ 2,032:
 
=={{header|FutureBasic}}==
<langsyntaxhighlight lang="futurebasic">
text,,,,,70// Set width of tabs
include "ConsoleWindow"
 
// Set width of tabs
def tab 10
 
local fn gcd( a as long, b as long )
dim as long result
 
if ( b != 0 )
result = fn gcd( b, a mod b)
else
result = abs(a)
end if
end fn = result
 
Line 1,771 ⟶ 2,050:
 
local fn CalculateHeronianTriangles( numberToCheck as long ) as long
dim as long c, b, a, result, count : count = 0
dim as double s, area
 
for c = 1 to numberToCheck
for b = 1 to c
for a = 1 to b
s = ( a + b + c ) / 2
area = s * ( s - a ) * ( s - b ) * ( s - c )
if area > 0
area = sqr( area )
if area = int( area )
result = fn gcd( b, c )
result = fn gcd( a, result )
if result == 1
count++
triangleInfo( count, 0 ) = a
triangleInfo( count, 1 ) = b
triangleInfo( count, 2 ) = c
triangleInfo( count, 3 ) = 2 * s
triangleInfo( count, 4 ) = area
end if
end if
end if
next
next
next
end fn = count
 
Line 1,808 ⟶ 2,087:
print "---------------------------------------------"
print "Side A", "Side B", "Side C", "Perimeter", "Area"
print "---------------------------------------------"
 
// Sort array
dim as Boolean flips : flips = _true
while ( flips = _true )
flips = _false
for i = 1 to count - 1
if triangleInfo( i, 4 ) > triangleInfo( i + 1, 4 )
for k = 0 to 4
swap triangleInfo( i, k ), triangleInfo( i + 1, k )
next
flips = _true
end if
next
wend
 
// Find first 10 heronian triangles
for i = 1 to 10
print triangleInfo( i, 0 ), triangleInfo( i, 1 ), triangleInfo( i, 2 ), triangleInfo( i, 3 ), triangleInfo( i, 4 )
next
print
Line 1,833 ⟶ 2,112:
// Search for triangle with area of 210
for i = 1 to count
if triangleInfo( i, 4 ) == 210
print triangleInfo( i, 0 ), triangleInfo( i, 1 ), triangleInfo( i, 2 ), triangleInfo( i, 3 ), triangleInfo( i, 4 )
end if
next
 
</lang>
HandleEvents
</syntaxhighlight>
 
Output:
Line 1,868 ⟶ 2,149:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,937 ⟶ 2,218:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Number of primitive Heronian triangles with sides up to 200: 517
Line 1,964 ⟶ 2,245:
 
=={{header|Haskell}}==
<langsyntaxhighlight Haskelllang="haskell">import qualified Data.List as L
import Data.Maybe
import Data.Ord
Line 2,026 ⟶ 2,307:
mapM_ printTri $ take 10 tris
putStrLn ""
mapM_ printTri $ filter ((== 210) . fifth) tris</langsyntaxhighlight>
{{out}}
<pre>Heronian triangles found: 517
Line 2,053 ⟶ 2,334:
'''Hero's formula Implementation'''
 
<langsyntaxhighlight Jlang="j">a=: 0&{"1
b=: 1&{"1
c=: 2&{"1
Line 2,059 ⟶ 2,340:
area=: 2 %: s*(s-a)*(s-b)*(s-c) NB. Hero's formula
perim=: +/"1
isPrimHero=: (0&~: * (= <.@:+))@area * 1 = a +. b +. c</langsyntaxhighlight>
 
We exclude triangles with zero area, triangles with complex area, non-integer area, and triangles whose sides share a common integer multiple.
Line 2,067 ⟶ 2,348:
The implementation above uses the symbols as given in the formula at the top of the page, making it easier to follow along as well as spot any errors. That formula distinguishes between the individual sides of the triangles but J could easily treat these sides as a single entity or array. The implementation below uses this "typical J" approach:
 
<langsyntaxhighlight Jlang="j">perim=: +/"1
s=: -:@:perim
area=: [: %: s * [: */"1 s - ] NB. Hero's formula
isNonZeroInt=: 0&~: *. (= <.@:+)
isPrimHero=: isNonZeroInt@area *. 1 = +./&.|:</langsyntaxhighlight>
 
'''Required examples'''
 
<langsyntaxhighlight Jlang="j"> Tri=:(1-i.3)+"1]3 comb 202 NB. distinct triangles with sides <= 200
HeroTri=: (#~ isPrimHero) Tri NB. all primitive Heronian triangles with sides <= 200
 
Line 2,101 ⟶ 2,382:
17 28 39 _ 84 210
7 65 68 _ 140 210
3 148 149 _ 300 210</langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.ArrayList;
 
public class Heron {
Line 2,180 ⟶ 2,461:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Number of primitive Heronian triangles with sides up to 200: 517
Line 2,210 ⟶ 2,491:
===Imperative===
 
<syntaxhighlight lang="javascript">
<lang JavaScript>
window.onload = function(){
var list = [];
Line 2,261 ⟶ 2,542:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517
Line 2,298 ⟶ 2,579:
ES6 JavaScript introduces syntactic sugar for list comprehensions, but the list monad pattern can already be used in ES5 – indeed in any language which supports the use of higher-order functions.
 
<langsyntaxhighlight JavaScriptlang="javascript">(function (n) {
var chain = function (xs, f) { // Monadic bind/chain
Line 2,379 ⟶ 2,660:
) + '\n\n';
})(200);</langsyntaxhighlight>
 
{{out}}
Line 2,434 ⟶ 2,715:
=={{header|jq}}==
{{works with|jq|1.4}}
<langsyntaxhighlight lang="jq"># input should be an array of the lengths of the sides
def hero:
(add/2) as $s
Line 2,473 ⟶ 2,754:
( .[] | select( hero == 210 ) | "\(rjust(11)) \(add|rjust(3)) \(hero|rjust(4))" ) ;
 
task(200)</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ time jq -n -r -f heronian.jq
The number of primitive Heronian triangles with sides up to 200: 517
The first ten when ordered by increasing area, then perimeter, then maximum sides:
Line 2,496 ⟶ 2,777:
[17,28,39] 84 210
[7,65,68] 140 210
[3,148,149] 300 210</langsyntaxhighlight>
 
=={{header|Julia}}==
Line 2,502 ⟶ 2,783:
 
'''Types and Functions'''
<syntaxhighlight lang="julia">
<lang Julia>
type IntegerTriangle{T<:Integer}
a::T
Line 2,529 ⟶ 2,810:
σ^2 == t
end
</syntaxhighlight>
</lang>
 
'''Main'''
<syntaxhighlight lang="julia">
<lang Julia>
slim = 200
 
Line 2,566 ⟶ 2,847:
println(@sprintf "%6d %3d %3d %4d %4d" t.a t.b t.c t.σ t.p)
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,595 ⟶ 2,876:
=={{header|Kotlin}}==
{{trans|Scala}}
<langsyntaxhighlight lang="scala">import java.util.ArrayList
 
object Heron {
Line 2,658 ⟶ 2,939:
}
 
fun main(args: Array<String>) = Heron.run()</langsyntaxhighlight>
{{out}}
<pre>Number of primitive Heronian triangles with sides up to 200: 517
Line 2,683 ⟶ 2,964:
7 x 65 x 68 140 210
3 x 148 x 149 300 210</pre>
 
=={{header|Logtalk}}==
 
Implemented as a parametric object, the solution to making primitive Heronian triangles would look something like this:
 
<syntaxhighlight lang="logtalk">
% In this example we assume that A<=B<=C.
% Non-pedagogical code would verify and force this.
:- object(triangle(_A_, _B_, _C_)).
 
:- public([a/1, b/1, c/1, area/1, perimeter/1, primitive/0]).
 
a(_A_). b(_B_). c(_C_).
 
area(A) :-
AB is _A_ + _B_,
AB @> _C_, % you can't make a triangle if one side is half or longer the perimeter
s(S),
A is sqrt(S * (S - _A_) * (S - _B_) * (S - _C_)).
 
perimeter(P) :-
P is _A_ + _B_ + _C_.
 
primitive :- heronian, gcd(1).
 
% helper predicates
 
heronian :-
integer(_A_),
integer(_B_),
integer(_C_),
area(A),
A > 0.0,
0.0 is float_fractional_part(A).
 
gcd(G) :- G is gcd(_A_, gcd(_B_, _C_)).
 
s(S) :- perimeter(P), S is P / 2.
 
:- end_object.
</syntaxhighlight>
 
A quickly hacked-together test that produces the output for the task assignment would look something like this:
 
<syntaxhighlight lang="logtalk">
:- object(test_triangle).
 
:- uses(integer, [between/3]).
:- uses(list, [length/2, member/2, sort/3, take/3]).
:- uses(logtalk, [print_message(information, heronian, Message) as print(Message)]).
 
:- public(start/0).
 
start :-
 
gather_primitive_heronians(Primitives),
length(Primitives, L),
print('There are ~w primitive Heronian triangles with sides under 200.~n'+[L]),
 
sort(order_by(area), Primitives, AreaSorted),
take(10, AreaSorted, Area10),
print(@'The first ten found, ordered by area, are:\n'),
display_each_element(Area10),
 
sort(order_by(perimeter), Primitives, PerimeterSorted),
take(10, PerimeterSorted, Perimeter10),
print(@'The first ten found, ordered by perimeter, are:\n'),
display_each_element(Perimeter10),
 
findall(
t(A, B, C, 210.0, Perimeter),
member(t(A, B, C, 210.0, Perimeter), Primitives),
Area210
),
print(@'The list of those with an area of 210 is:\n'),
display_each_element(Area210).
 
% localized helper predicates
 
% display a single element in the provided format
display_single_element(t(A,B,C,Area,Perimeter)) :-
format(F),
print(F+[A, B, C, Area, Perimeter]).
 
% display each element in a list of elements, printing a header first
display_each_element(L) :-
print(@' A B C Area Perimeter'),
print(@'=== === === ======= ========='),
forall(member(T, L), display_single_element(T)),
print(@'\n').
 
format('~|~` t~w~3+~` t~w~4+~` t~w~4+~` t~w~8+~` t~w~7+').
 
% collect all the primitive heronian triangles within the boundaries of the provided task
gather_primitive_heronians(Primitives) :-
findall(
t(A, B, C, Area, Perimeter),
(
between(3, 200, A),
between(A, 200, B),
between(B, 200, C),
triangle(A, B, C)::primitive,
triangle(A, B, C)::area(Area),
triangle(A, B, C)::perimeter(Perimeter)
),
Primitives
).
 
order_by(_, =, T, T) :- !.
order_by(area, <, t(_,_,_,Area1,_), t(_,_,_,Area2,_)) :- Area1 < Area2, !.
order_by(area, >, t(_,_,_,Area1,_), t(_,_,_,Area2,_)) :- Area1 > Area2, !.
order_by(perimeter, <, t(_,_,_,_,Perimeter1), t(_,_,_,_,Perimeter2)) :- Perimeter1 < Perimeter2, !.
order_by(perimeter, >, t(_,_,_,_,Perimeter1), t(_,_,_,_,Perimeter2)) :- Perimeter1 > Perimeter2, !.
order_by(_, <, t(A1,_,_,_,_), t(A2,_,_,_,_)) :- A1 < A2, !.
order_by(_, <, t(_,B1,_,_,_), t(_,B2,_,_,_)) :- B1 < B2, !.
order_by(_, <, t(_,_,C1,_,_), t(_,_,C2,_,_)) :- C1 < C2, !.
order_by(_, >, _, _).
 
:- end_object.
</syntaxhighlight>
 
{{Out}}
 
<pre>
?- test_triangle::start.
% There are 517 primitive Heronian triangles with sides under 200.
 
% The first ten found, ordered by area, are:
 
% A B C Area Perimeter
% === === === ======= =========
% 3 4 5 6.0 12
% 5 5 6 12.0 16
% 5 5 8 12.0 18
% 4 13 15 24.0 32
% 5 12 13 30.0 30
% 3 25 26 36.0 54
% 9 10 17 36.0 36
% 7 15 20 42.0 42
% 6 25 29 60.0 60
% 8 15 17 60.0 40
%
 
% The first ten found, ordered by perimeter, are:
 
% A B C Area Perimeter
% === === === ======= =========
% 3 4 5 6.0 12
% 5 5 6 12.0 16
% 5 5 8 12.0 18
% 5 12 13 30.0 30
% 4 13 15 24.0 32
% 9 10 17 36.0 36
% 10 13 13 60.0 36
% 8 15 17 60.0 40
% 7 15 20 42.0 42
% 13 14 15 84.0 42
%
 
% The list of those with an area of 210 is:
 
% A B C Area Perimeter
% === === === ======= =========
% 3 148 149 210.0 300
% 7 65 68 210.0 140
% 12 35 37 210.0 84
% 17 25 28 210.0 70
% 17 28 39 210.0 84
% 20 21 29 210.0 70
%
 
true.
</pre>
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">-- Returns the details of the Heronian Triangle with sides a, b, c or nil if it isn't one
local function tryHt( a, b, c )
local result
Line 2,745 ⟶ 3,199:
local t = ht[ htPos ];
if t.area == 210 then htPrint( t ) end
end</langsyntaxhighlight>
{{out}}
<pre>
Line 2,773 ⟶ 3,227:
</pre>
 
=={{header|NimMathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[Heron]
<lang nim>import math, algorithm, strfmt, sequtils
Heron[a_, b_, c_] := With[{s = (a + b + c)/2}, Sqrt[s (s - a) (s - b) (s - c)]]
PrintTemporary[Dynamic[{a, b, c}]];
results = Reap[
Do[
If[a < b + c \[And] b < c + a \[And] c < a + b,
If[GCD[a, b, c] == 1,
If[IntegerQ[Heron[a, b, c]],
Sow[<|"Sides" -> {a, b, c}, "Area" -> Heron[a, b, c],
"Perimeter" -> a + b + c, "MaximumSide" -> Max[a, b, c]|>]
]
]
]
,
{a, 1, 200},
{b, a, 200},
{c, b, 200}
]
][[2, 1]];
results = SortBy[results, {#["Area"] &, #["Perimeter"] &, #["MaximumSide"] &}];
results // Length
Take[results, 10] // Dataset
Select[results, #["Area"] == 210 &] // Dataset</syntaxhighlight>
{{out}}
<pre>517
 
Sides Area Perimeter MaximumSide
type
{3,4,5} 6 12 5
HeronianTriangle = tuple
{5,5,6} 12 16 6
a: int
{5,5,8} 12 18 8
b: int
{4,13,15} 24 32 15
c: int
{5,12,13} 30 30 13
s: float
{9,10,17} 36 36 17
A: int
{3,25,26} 36 54 26
{7,15,20} 42 42 20
{10,13,13} 60 36 13
{8,15,17} 60 40 17
 
Sides Area Perimeter MaximumSide
proc `$` (t: HeronianTriangle): string =
{17,25,28} 210 70 28
fmt("{:3d}, {:3d}, {:3d}\t{:7.3f}\t{:3d}", t.a, t.b, t.c, t.s, t.A)
{20,21,29} 210 70 29
{12,35,37} 210 84 37
proc hero(a:int, b:int, c:int): tuple[s, A: float] =
{17,28,39} 210 84 39
let s: float = (a + b + c) / 2
{7,65,68} 210 140 68
result = (s, sqrt( s * (s - float(a)) * (s - float(b)) * (s - float(c)) ))
{3,148,149} 210 300 149</pre>
proc isHeronianTriangle(x: float): bool = ceil(x) == x and x.toInt > 0
 
=={{header|Nim}}==
proc gcd(x: int, y: int): int =
<syntaxhighlight lang="nim">import std/[math, algorithm, lenientops, strformat, sequtils]
var
(dividend, divisor) = if x > y: (x, y) else: (y, x)
remainder = dividend mod divisor
while remainder != 0:
dividend = divisor
divisor = remainder
remainder = dividend mod divisor
result = divisor
var list = newSeq[HeronianTriangle]()
const max = 200
 
type HeronianTriangle = tuple[a, b, c: int; p: int; area: int]
for c in 1..max:
for b in 1..c:
for a in 1..b:
let (s, A) = hero(a, b, c)
if isHeronianTriangle(A) and gcd(a, gcd(b, c)) == 1:
let t:HeronianTriangle = (a, b, c, s, A.toInt)
list.add(t)
 
# Functions with three operands.
echo "Numbers of Heronian Triangle : ", list.len
func max(a, b, c: int): int = max(a, max(b, c))
func gcd(a, b, c: int): int = gcd(a, gcd(b, c))
 
list.sort dofunc cmp(x, y: HeronianTriangle): ->int int:=
## Compare two Heronian triangles.
result = cmp(x.A, y.A)
result = cmp(x.area, y.area)
if result == 0:
result = cmp(x.sp, y.sp)
if result == 0:
result = cmp(max(x.a, x.b, x.c), max(y.a, y.b, y.c))
 
func `$`(t: HeronianTriangle): string =
echo "Ten first Heronian triangle ordered : "
## Return the representation of a Heronian triangle.
echo "Sides Perimeter Area"
fmt"{t.a:3d}, {t.b:3d}, {t.c:3d} {t.p:7d} {t.area:8d}"
for t in list[0 .. <10]:
echo t
 
 
echo "Heronian triangle ordered with Area 210 : "
func hero(a, b, c: int): float =
echo "Sides Perimeter Area"
## Return the area of a triangle using Hero's formula.
for t in list.filter(proc (x: HeronianTriangle): bool = x.A == 210):
let s = (a + b + c) / 2
echo t</lang>
result = sqrt(s * (s - a) * (s - b) * (s - c))
 
func isHeronianTriangle(x: float): bool = x > 0 and ceil(x) == x
 
const Header = " Sides Perimeter Area\n------------- --------- ----"
 
var list: seq[HeronianTriangle]
const Max = 200
 
for c in 1..Max:
for b in 1..c:
for a in 1..b:
let area = hero(a, b, c)
if area.isHeronianTriangle and gcd(a, b, c) == 1:
let t: HeronianTriangle = (a, b, c, a + b + c, area.toInt)
list.add t
 
list.sort(cmp)
echo "Number of Heronian triangles: ", list.len
 
echo "\nOrdered list of first ten Heronian triangles:"
echo Header
for t in list[0 ..< 10]: echo t
 
echo "\nOrdered list of Heronian triangles with area 210:"
echo Header
for t in list.filterIt(it.area == 210): echo t
</syntaxhighlight>
{{out}}
<pre>NumbersNumber of Heronian Triangle triangles: 517
 
Ten first Heronian triangle ordered :
Ordered list of first ten Heronian triangles:
Sides Perimeter Area
3, Sides 4, 5 6.000 Perimeter 6Area
------------- --------- ----
5, 5, 6 8.000 12
53, 54, 8 5 9.000 12 6
45, 13 5, 15 6 16.000 24 12
5, 12 5, 13 15.000 8 30 18 12
94, 1013, 17 15 18.000 36 32 24
35, 2512, 26 13 27.000 36 30 30
79, 1510, 20 17 21.000 42 36 36
10 3, 1325, 13 26 54 18.000 6036
87, 15, 17 20.000 60 42 42
10, 13, 13 36 60
Heronian triangle ordered with Area 210 :
Sides 8, 15, 17 Perimeter Area 40 60
 
17, 25, 28 35.000 210
Ordered list of Heronian triangles with area 210:
20, 21, 29 35.000 210
Sides Perimeter Area
12, 35, 37 42.000 210
------------- --------- ----
17, 28, 39 42.000 210
17, 725, 65,28 68 70.000 210
20, 21, 29 70 210
3, 148, 149 150.000 210</pre>
12, 35, 37 84 210
17, 28, 39 84 210
7, 65, 68 140 210
3, 148, 149 300 210</pre>
 
=={{header|ooRexx}}==
Derived from REXX with some changes
<langsyntaxhighlight lang="rexx">/*REXX pgm generates primitive Heronian triangles by side length & area.*/
Call time 'R'
Numeric Digits 12
Line 2,996 ⟶ 3,493:
::requires rxmath library
::routine sqrt
Return rxCalcSqrt(arg(1),14)</langsyntaxhighlight>
{{out}}
<pre>517 primitive Heronian triangles found with side length up to 200 (inclusive).
Line 3,023 ⟶ 3,520:
=={{header|PARI/GP}}==
 
<langsyntaxhighlight lang="parigp">Heron(v)=my([a,b,c]=v); (a+b+c)*(-a+b+c)*(a-b+c)*(a+b-c) \\ returns 16 times the squared area
is(a,b,c)=(a+b+c)%2==0 && gcd(a,gcd(b,c))==1 && issquare(Heron([a,b,c]))
v=List(); for(a=1,200,for(b=a+1,200,for(c=b+1,200, if(is(a,b,c),listput(v, [a,b,c])))));
Line 3,033 ⟶ 3,530:
vecsort(u, (a,b)->Heron(a)-Heron(b))
vecsort(u, (a,b)->vecsum(a)-vecsum(b))
vecsort(u, 3) \\ shortcut: order by third component</langsyntaxhighlight>
{{out}}
<pre>%1 = [[1, 2, 3], [1, 3, 4], [1, 4, 5], [1, 5, 6], [1, 6, 7], [1, 7, 8], [1, 8, 9], [1, 9, 10], [1, 10, 11], [1, 11, 12]]
Line 3,044 ⟶ 3,541:
=={{header|Pascal}}==
{{Trans|Lua}}
<langsyntaxhighlight lang="pascal">program heronianTriangles ( input, output );
type
(* record to hold details of a Heronian triangle *)
Line 3,144 ⟶ 3,641:
if t^.area = 210 then htPrint( t )
end
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 3,173 ⟶ 3,670:
 
=={{header|Perl}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use List::Util qw(max);
Line 3,236 ⟶ 3,733:
}
 
&main();</langsyntaxhighlight>
{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517
Line 3,259 ⟶ 3,756:
210 140 7×65×68
210 300 3×148×149</pre>
 
=={{header|Perl 6}}==
{{works with|Rakudo|2018.09}}
<lang perl6>sub hero($a, $b, $c) {
my $s = ($a + $b + $c) / 2;
($s * ($s - $a) * ($s - $b) * ($s - $c)).sqrt;
}
sub heronian-area($a, $b, $c) {
$_ when Int given hero($a, $b, $c).narrow;
}
 
sub primitive-heronian-area($a, $b, $c) {
heronian-area $a, $b, $c
if 1 == [gcd] $a, $b, $c;
}
 
sub show(@measures) {
say " Area Perimeter Sides";
for @measures -> [$area, $perim, $c, $b, $a] {
printf "%6d %6d %12s\n", $area, $perim, "$a×$b×$c";
}
}
sub MAIN ($maxside = 200, $first = 10, $witharea = 210) {
my @h;
(1 .. $maxside).race.map: -> $c {
for 1 .. $c -> $b {
for $c - $b + 1 .. $b -> $a {
if primitive-heronian-area($a,$b,$c) -> $area {
@h.push: [$area, $a+$b+$c, $c, $b, $a];
}
}
}
}
@h = @h.sort;
say "Primitive Heronian triangles with sides up to $maxside: ", +@h;
 
say "\nFirst $first:";
show @h[^$first];
 
say "\nArea $witharea:";
show @h.grep: *[0] == $witharea;
}</lang>
{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517
 
First 10:
Area Perimeter Sides
6 12 3×4×5
12 16 5×5×6
12 18 5×5×8
24 32 4×13×15
30 30 5×12×13
36 36 9×10×17
36 54 3×25×26
42 42 7×15×20
60 36 10×13×13
60 40 8×15×17
 
Area 210:
Area Perimeter Sides
210 70 17×25×28
210 70 20×21×29
210 84 12×35×37
210 84 17×28×39
210 140 7×65×68
210 300 3×148×149</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">-->
<lang Phix>function heroArea(integer a, b, c)
<span style="color: #008080;">function</span> <span style="color: #000000;">heroArea</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
atom s = (a+b+c)/2
<span style="color: #004080;">atom</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span>
return sqrt(s*(s-a)*(s-b)*(s-c))
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">-</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)*(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">-</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)*(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">-</span><span style="color: #000000;">c</span><span style="color: #0000FF;">),</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
function hero(atom h)
<span style="color: #008080;">function</span> <span style="color: #000000;">hero</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">)</span>
return remainder(h,1)=0 and h>0
<span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
sequence list = {}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">list</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
integer tries = 0
<span style="color: #004080;">integer</span> <span style="color: #000000;">tries</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
for a=1 to 200 do
<span style="color: #008080;">for</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">200</span> <span style="color: #008080;">do</span>
for b=1 to a do
<span style="color: #008080;">for</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">a</span> <span style="color: #008080;">do</span>
for c=1 to b do
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">b</span> <span style="color: #008080;">do</span>
tries += 1
<span style="color: #000000;">tries</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if gcd({a,b,c})=1 then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">gcd</span><span style="color: #0000FF;">({</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">})=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
atom hArea = heroArea(a,b,c)
<span style="color: #004080;">atom</span> <span style="color: #000000;">hArea</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">heroArea</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
if hero(hArea) then
<span style="color: #008080;">if</span> <span style="color: #000000;">hero</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hArea</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
list = append(list,{hArea,a+b+c,a,b,c})
<span style="color: #000000;">list</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">hArea</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">})</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
list = sort(list)
<span style="color: #000000;">list</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">)</span>
printf(1,"Primitive Heronian triangles with sides up to 200: %d (of %,d tested)\n\n",{length(list),tries})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Primitive Heronian triangles with sides up to 200: %d (of %,d tested)\n\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">),</span><span style="color: #000000;">tries</span><span style="color: #0000FF;">})</span>
printf(1,"First 10 ordered by area/perimeter/sides:\n")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"First 10 ordered by area/perimeter/sides:\n"</span><span style="color: #0000FF;">)</span>
printf(1,"area perimeter sides")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"area perimeter sides\n"</span><span style="color: #0000FF;">)</span>
for i=1 to 10 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
printf(1,"\n%4d %3d %dx%dx%d",list[i])
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%4d %3d %dx%dx%d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">list</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"\n\narea = 210:\n")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\narea = 210:\n"</span><span style="color: #0000FF;">)</span>
printf(1,"area perimeter sides")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"area perimeter sides\n"</span><span style="color: #0000FF;">)</span>
for i=1 to length(list) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if list[i][1]=210 then
<span style="color: #008080;">if</span> <span style="color: #000000;">list</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">210</span> <span style="color: #008080;">then</span>
printf(1,"\n%4d %3d %dx%dx%d",list[i])
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%4d %3d %dx%dx%d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">list</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 3,395 ⟶ 3,826:
 
=={{header|PowerShell}}==
<langsyntaxhighlight lang="powershell">
function Get-Gcd($a, $b){
if($a -ge $b){
Line 3,443 ⟶ 3,874:
}
}
</syntaxhighlight>
</lang>
{{out}}
<syntaxhighlight lang="text">
Primitive Heronian triangles with sides up to 200: 517
 
Line 3,469 ⟶ 3,900:
7 65 68 140 210
3 148 149 300 210
</syntaxhighlight>
</lang>
 
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">from __future__ import division, print_function
from math import gcd, sqrt
from fractions import gcd
from itertools import product
 
 
def hero(a, b, c):
s = (a + b + c) / 2
a2 = s * (s - a) * (s - b) * (s - c)
return sqrt(a2) if a2 > 0 else 0
 
 
def is_heronian(a, b, c):
a = hero(a, b, c)
return a > 0 and a.is_integer()
 
 
def gcd3(x, y, z):
def gcd3(x, y, z):
return gcd(gcd(x, y), z)
 
 
if __name__ == '__main__':
maxsideMAXSIDE = 200
 
h = [(a, b, c) for a,b,c in product(range(1, maxside + 1), repeat=3)
N = 1 + MAXSIDE
if a <= b <= c and a + b > c and gcd3(a, b, c) == 1 and is_heronian(a, b, c)]
h = [(x, y, z)
h.sort(key = lambda x: (hero(*x), sum(x), x[::-1])) # By increasing area, perimeter, then sides
for x in range(1, N)
print('Primitive Heronian triangles with sides up to %i:' % maxside, len(h))
for y in range(x, N)
print('\nFirst ten when ordered by increasing area, then perimeter,then maximum sides:')
for z in range(y, N) if (x + y > z) and
print('\n'.join(' %14r perim: %3i area: %i'
1 == gcd3(x, y, z) and
is_heronian(x, y, z)]
 
# By increasing area, perimeter, then sides
h.sort(key=lambda x: (hero(*x), sum(x), x[::-1]))
 
print(
'Primitive Heronian triangles with sides up to %i:' % MAXSIDE, len(h)
)
print('\nFirst ten when ordered by increasing area, then perimeter,',
'then maximum sides:')
print('\n'.join(' %14r perim: %3i area: %i'
% (sides, sum(sides), hero(*sides)) for sides in h[:10]))
print('\nAll with area 210 subject to the previous ordering:')
print('\n'.join(' %14r perim: %3i area: %i'
% (sides, sum(sides), hero(*sides)) for sides in h
if hero(*sides) == 210))</lang>
</syntaxhighlight>
 
{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517
Line 3,535 ⟶ 3,976:
Mostly adopted from Python implementation:
 
<syntaxhighlight lang="r">
<lang R>
area <- function(a, b, c) {
s = (a + b + c) / 2
Line 3,572 ⟶ 4,013:
cat("Showing the first ten ordered first by perimeter, then by area:\n")
print(head(r[order(x=r[,"perimeter"],y=r[,"area"]),],n=10))
</syntaxhighlight>
</lang>
 
{{out}}
 
<syntaxhighlight lang="text">There are 517 Heronian triangles up to a maximal side length of 200.
Showing the first ten ordered first by perimeter, then by area:
a b c perimeter area
Line 3,588 ⟶ 4,029:
[8,] 8 15 17 40 60
[9,] 7 15 20 42 42
[10,] 13 14 15 42 84</langsyntaxhighlight>
 
=={{header|Racket}}==
 
<syntaxhighlight lang="text">#lang at-exp racket
(require data/order scribble/html)
 
Line 3,636 ⟶ 4,077:
@; Show a similar ordered table for those triangles with area = 210
@(triangles->table (tri-sort (filter (λ(t) (eq? 210 (car t))) ts)))
}))</langsyntaxhighlight>
 
This program generates HTML, so the output is inline with the page, not in a <code>&lt;pre></code> block.
Line 3,665 ⟶ 4,106:
 
<br><br>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.09}}
<syntaxhighlight lang="raku" line>sub hero($a, $b, $c) {
my $s = ($a + $b + $c) / 2;
($s * ($s - $a) * ($s - $b) * ($s - $c)).sqrt;
}
sub heronian-area($a, $b, $c) {
$_ when Int given hero($a, $b, $c).narrow;
}
 
sub primitive-heronian-area($a, $b, $c) {
heronian-area $a, $b, $c
if 1 == [gcd] $a, $b, $c;
}
 
sub show(@measures) {
say " Area Perimeter Sides";
for @measures -> [$area, $perim, $c, $b, $a] {
printf "%6d %6d %12s\n", $area, $perim, "$a×$b×$c";
}
}
sub MAIN ($maxside = 200, $first = 10, $witharea = 210) {
my @hh[1000];
my atomicint $i;
(1 .. $maxside).race(:12batch).map: -> $c {
for 1 .. $c -> $b {
for $c - $b + 1 .. $b -> $a {
if primitive-heronian-area($a,$b,$c) -> $area {
@hh[$i⚛++] = [$area, $a+$b+$c, $c, $b, $a];
}
}
}
}
 
my @h = (@hh.grep: so *).sort;
say "Primitive Heronian triangles with sides up to $maxside: ", +@h;
 
say "\nFirst $first:";
show @h[^$first];
 
say "\nArea $witharea:";
show @h.grep: *[0] == $witharea;
}</syntaxhighlight>
{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517
 
First 10:
Area Perimeter Sides
6 12 3×4×5
12 16 5×5×6
12 18 5×5×8
24 32 4×13×15
30 30 5×12×13
36 36 9×10×17
36 54 3×25×26
42 42 7×15×20
60 36 10×13×13
60 40 8×15×17
 
Area 210:
Area Perimeter Sides
210 70 17×25×28
210 70 20×21×29
210 84 12×35×37
210 84 17×28×39
210 140 7×65×68
210 300 3×148×149</pre>
 
=={{header|REXX}}==
=== using iSQRT ===
Line 3,695 ⟶ 4,208:
This REXX version doesn't need to explicitly sort the triangles as they are listed in the proper order.
<langsyntaxhighlight lang="rexx">/*REXX program generates & displays primitive Heronian triangles by side length and area*/
parse arg N first area . /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 200 /*Not specified? Then use the default.*/
Line 3,747 ⟶ 4,260:
end /*k*/
end /*j*/ /* [↑] use the known perimeters. */
end /*i*/; return /* [↑] show any found triangles. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 3,782 ⟶ 4,295:
 
It is about eight times faster than the 1<sup>st</sup> REXX version.
<langsyntaxhighlight lang="rexx">/*REXX program generates & displays primitive Heronian triangles by side length and area*/
parse arg N first area . /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 200 /*Not specified? Then use the default.*/
Line 3,827 ⟶ 4,340:
end /*k*/
end /*j*/ /* [↑] use the known perimeters. */
end /*i*/; return /* [↑] show any found triangles. */</langsyntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}} <br><br>
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Heronian triangles
 
Line 3,872 ⟶ 4,385:
end
return gcd
</syntaxhighlight>
</lang>
Output:
<pre>
Line 3,897 ⟶ 4,410:
{17, 28, 39} 84 210
{20, 21, 29} 70 210
</pre>
 
=={{header|RPL}}==
We use here the <code>→V3</code> and<code>SORT</code> instructions, available for HP-48G or newer models only. <code>GCD </code> is not a built-in instruction, but it is a question of a few words:
≪ WHILE DUP REPEAT SWAP OVER MOD END DROP ABS ≫ ''''GCD'''' STO
{{trans|FreeBASIC}}
{{works with|Halcyon Calc|4.2.8}}
{| class="wikitable"
! RPL code
! Comment
|-
|
3 DUPN + + 2 / → a b c s
≪ s DUP a - * s b - * s c - *
≫ ≫ ‘'''SURF2'''’ STO
IF '''SURF2''' DUP 0 > THEN √ FP NOT ELSE DROP 0 END
≫ ‘'''HERO?'''’ STO
≪ → n
≪ { } 1 n FOR x
x n FOR y
y x 2 MOD + x y + 1 - n MIN FOR z
IF x y z '''GCD GCD''' THEN
IF x y z '''HERO?''' THEN x y z →V3 +
END END
2 STEP NEXT NEXT
≫ ≫ ‘'''TASK2'''’ RCL
|
'''SURF2''' ''( a b c → A² ) ''
s = (a+b+c)/2
A² = s(s-a)(s-b)(s-c)
return A²
'''HERO?''' ''( a b c → boolean ) ''
return true if A > 0 and √A is an integer
'''TASK2''' ''( n → { [Heronians] ) ''
for x = 1 to n
for y = x to n
for z = y+u to min(x+y-1,n) // u ensures x+y+z is even
if gcd(x,y,z) == 1
if x y z is Heronian then append to list
z += 2 to keep x+y+z even
|}
The rest of the code, which is devoted to printing the requested tables, is boring and the result is awful: native RPL works on machines with a 22-character screen.
{{in}}
<pre>
≪ → a b c
≪ c →STR WHILE DUP SIZE 4 < REPEAT " " SWAP + END
a b c + + →STR SWAP + WHILE DUP SIZE 8 < REPEAT " " SWAP + END
a b c SURF √ →STR SWAP + WHILE DUP SIZE 12 < REPEAT " " SWAP + END
" (" + a →STR + " " + b →STR + " " + c →STR + ")" +
≫ ≫ 'PRTRI' STO
200 TASK2 'H' STO
≪ { } 1 H SIZE FOR j H j GET ARRY→ DROP PRTRI + NEXT SORT 'H2' STO ≫ EVAL
"Area P. LS (triangle)"
1 10 H2 SUB
≪ { } 1 H2 SIZE FOR j H2 j GET IF DUP 1 4 SUB " 210" == THEN + END NEXT ≫ EVAL
</pre>
{{out}}
<pre style="height:40ex;overflow:scroll;">
4: 517
3: "Area P. LS (triangle)"
2: { " 6 12 5 (3 4 5)"
" 12 16 6 (5 5 6)"
" 12 18 8 (5 5 8)"
" 24 32 15 (4 13 15)"
" 30 30 13 (5 12 13)"
" 36 36 17 (9 10 17)"
" 36 54 26 (3 25 26)"
" 42 42 20 (7 15 20)"
" 60 36 13 (10 13 13)"
" 60 40 17 (8 15 17)" }
1: { " 210 70 28 (17 25 28)"
" 210 70 29 (20 21 29)"
" 210 84 37 (12 35 37)"
" 210 84 39 (17 28 39)"
" 210 140 68 (7 65 68)"
" 210 300 149 (3 148 149)" }
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class Triangle
def self.valid?(a,b,c) # class method
short, middle, long = [a, b, c].sort
Line 3,945 ⟶ 4,543:
puts sorted.first(10).map(&:to_s)
puts "\nTriangles with an area of: #{area}"
sorted.each{|tr| puts tr if tr.area == area}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,969 ⟶ 4,567:
7x65x68 140 210.0
3x148x149 300 210.0
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">
use num_integer::Integer;
use std::{f64, usize};
 
const MAXSIZE: usize = 200;
 
#[derive(Debug)]
struct HerionanTriangle {
a: usize,
b: usize,
c: usize,
area: usize,
perimeter: usize,
}
 
fn get_area(a: &usize, b: &usize, c: &usize) -> f64 {
let s = (a + b + c) as f64 / 2.;
(s * (s - *a as f64) * (s - *b as f64) * (s - *c as f64)).sqrt()
}
 
fn is_heronian(a: &usize, b: &usize, c: &usize) -> bool {
let area = get_area(a, b, c);
// Heronian if the area is an integer number
area != 0. && area.fract() == 0.
}
 
fn main() {
let mut heronians: Vec<HerionanTriangle> = vec![];
 
(1..=MAXSIZE).into_iter().for_each(|a| {
(a..=MAXSIZE).into_iter().for_each(|b| {
(b..=MAXSIZE).into_iter().for_each(|c| {
if a + b > c && a.gcd(&b).gcd(&c) == 1 && is_heronian(&a, &b, &c) {
heronians.push(HerionanTriangle {
a,
b,
c,
perimeter: a + b + c,
area: get_area(&a, &b, &c) as usize,
})
}
})
})
});
 
// sort by area then by perimeter, then by maximum side
heronians.sort_unstable_by(|x, y| {
x.area
.cmp(&y.area)
.then(x.perimeter.cmp(&y.perimeter))
.then((x.a.max(x.b).max(x.c)).cmp(&y.a.max(y.b).max(y.c)))
});
 
println!(
"Primitive Heronian triangles with sides up to 200: {}",
heronians.len()
);
 
println!("\nFirst ten when ordered by increasing area, then perimeter,then maximum sides:");
heronians.iter().take(10).for_each(|h| println!("{:?}", h));
 
println!("\nAll with area 210 subject to the previous ordering:");
heronians
.iter()
.filter(|h| h.area == 210)
.for_each(|h| println!("{:?}", h));
}
 
</syntaxhighlight>
{{out}}
<pre>
Primitive Heronian triangles with sides up to 200: 517
 
First ten when ordered by increasing area, then perimeter,then maximum sides:
HerionanTriangle { a: 3, b: 4, c: 5, area: 6, perimeter: 12 }
HerionanTriangle { a: 5, b: 5, c: 6, area: 12, perimeter: 16 }
HerionanTriangle { a: 5, b: 5, c: 8, area: 12, perimeter: 18 }
HerionanTriangle { a: 4, b: 13, c: 15, area: 24, perimeter: 32 }
HerionanTriangle { a: 5, b: 12, c: 13, area: 30, perimeter: 30 }
HerionanTriangle { a: 9, b: 10, c: 17, area: 36, perimeter: 36 }
HerionanTriangle { a: 3, b: 25, c: 26, area: 36, perimeter: 54 }
HerionanTriangle { a: 7, b: 15, c: 20, area: 42, perimeter: 42 }
HerionanTriangle { a: 10, b: 13, c: 13, area: 60, perimeter: 36 }
HerionanTriangle { a: 8, b: 15, c: 17, area: 60, perimeter: 40 }
 
All with area 210 subject to the previous ordering:
HerionanTriangle { a: 17, b: 25, c: 28, area: 210, perimeter: 70 }
HerionanTriangle { a: 20, b: 21, c: 29, area: 210, perimeter: 70 }
HerionanTriangle { a: 12, b: 35, c: 37, area: 210, perimeter: 84 }
HerionanTriangle { a: 17, b: 28, c: 39, area: 210, perimeter: 84 }
HerionanTriangle { a: 7, b: 65, c: 68, area: 210, perimeter: 140 }
HerionanTriangle { a: 3, b: 148, c: 149, area: 210, perimeter: 300 }
</pre>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">object Heron extends scala.collection.mutable.MutableList[Seq[Int]] with App {
private final val n = 200
for (c <- 1 to n; b <- 1 to c; a <- 1 to b if gcd(gcd(a, b), c) == 1) {
Line 4,006 ⟶ 4,699:
private final val header = "\nSides Perimeter Area"
private def format: Seq[Int] => String = "\n%3d x %3d x %3d %5d %10d".format
}</langsyntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="ruby">class Triangle(a, b, c) {
 
has (sides, perimeter, area)
Line 4,057 ⟶ 4,750:
say sorted.first(10).join("\n")
say "\nTriangles with an area of: #{area}"
sorted.each{|tr| say tr if (tr.area == area)}</langsyntaxhighlight>
{{out}}
<pre>
Line 4,081 ⟶ 4,774:
7x65x68 140 210.0
3x148x149 300 210.0
</pre>
 
=={{header|Smalltalk}}==
Works with Squeak 5.x
<syntaxhighlight lang="smalltalk">perimeter := [:triangle | triangle reduce: #+].
 
squaredArea := [:triangle |
| s |
s := (perimeter value: triangle) / 2.
triangle inject: s into: [:a2 :edge | s - edge * a2]].
 
isPrimitive := [:triangle | (triangle reduce: #gcd:) = 1].
 
isHeronian := [:triangle | (squaredArea value: triangle) sqrt isInteger].
 
heroGenerator := Generator on: [:generator |
1 to: 200 do: [:a |
a to: 200 do: [:b |
b to: (a+b-1 min: 200) do: [:c |
| triangle |
triangle := {a. b. c.}.
((isPrimitive value: triangle) and: [isHeronian value: triangle])
ifTrue: [generator nextPut: triangle]]]]].
 
heronians := heroGenerator contents.
sorter := squaredArea ascending , perimeter ascending , #third ascending , #second ascending , #first ascending.
sorted := heronians sorted: sorter.
area210 := sorted select: [:triangle | (squaredArea value: triangle) = 210 squared].
 
header := [:title |
Transcript cr; cr; nextPutAll: title; cr.
#(peri area a b c) do: [:s | Transcript nextPutAll: s; tab]].
tabulate := [:t |
Transcript cr.
Transcript print: (perimeter value: t); tab.
Transcript print: (squaredArea value: t) sqrt.
t do: [:edge | Transcript tab; print: edge].].
 
Transcript cr; print: heronians size; nextPutAll: ' heronians triangles of side <= 200 where found'.
header value: 'first 10 sorted by area, then perimeter, the largest side'.
(sorted first: 10) do: tabulate.
header value: 'heronians of area 210'.
area210 do: tabulate.
 
Transcript flush.</syntaxhighlight>
{{out}}
<pre>
517 heronians triangles of side <= 200 where found
 
first 10 sorted by area, then perimeter, the largest side
peri area a b c
12 6 3 4 5
16 12 5 5 6
18 12 5 5 8
32 24 4 13 15
30 30 5 12 13
36 36 9 10 17
54 36 3 25 26
42 42 7 15 20
36 60 10 13 13
40 60 8 15 17
 
heronians of area 210
peri area a b c
70 210 17 25 28
70 210 20 21 29
84 210 12 35 37
84 210 17 28 39
140 210 7 65 68
300 210 3 148 149
</pre>
 
=={{header|SPL}}==
<langsyntaxhighlight lang="spl">h,t = getem(200)
#.sort(h,4,5,1,2,3)
#.output("There are ",t," Heronian triangles")
Line 4,116 ⟶ 4,879:
s = (a+b+c)/2
<= (s*(s-a)*(s-b)*(s-c))^0.5, s*2
.</langsyntaxhighlight>
{{out}}
<pre>
Line 4,143 ⟶ 4,906:
=={{header|Swift}}==
Works with Swift 1.2
<langsyntaxhighlight Swiftlang="swift">import Foundation
 
typealias PrimitiveHeronianTriangle = (s1:Int, s2:Int, s3:Int, p:Int, a:Int)
Line 4,196 ⟶ 4,959:
for t in triangles[0...9] {
println("\(t.s1)\t\(t.s2)\t\(t.s3)\t\t\(t.p)\t\t\(t.a)")
}</langsyntaxhighlight>
 
{{out}}
Line 4,219 ⟶ 4,982:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">
if {[info commands let] eq ""} {
 
Line 4,311 ⟶ 5,074:
sqlite3 db :memory:
main db
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,337 ⟶ 5,100:
(3, 148, 149) perimiter = 300; area = 210
</pre>
 
=={{header|VBA}}==
{{trans|Phix}}<syntaxhighlight lang="vb">Function heroArea(a As Integer, b As Integer, c As Integer) As Double
s = (a + b + c) / 2
On Error GoTo Err
heroArea = Sqr(s * (s - a) * (s - b) * (s - c))
Exit Function
Err:
heroArea = -1
End Function
Function hero(h As Double) As Boolean
hero = (h - Int(h) = 0) And h > 0
End Function
Public Sub main()
Dim list() As Variant, items As Integer
Dim a As Integer, b As Integer, c As Integer
Dim hArea As Double
Dim tries As Long
For a = 1 To 200
For b = 1 To a
For c = 1 To b
tries = tries + 1
If gcd(gcd(a, b), c) = 1 Then
hArea = heroArea(a, b, c)
If hero(hArea) Then
ReDim Preserve list(items)
list(items) = Array(CStr(hArea), CStr(a + b + c), CStr(a), CStr(b), CStr(c))
items = items + 1
End If
End If
Next c
Next b
Next a
list = sort(list)
Debug.Print "Primitive Heronian triangles with sides up to 200:"; UBound(list) + 1; "(of"; tries; "tested)"
Debug.Print
Debug.Print "First 10 ordered by area/perimeter/sides:"
Debug.Print "area perimeter sides"
For i = 0 To 9
Debug.Print Format(list(i)(0), "@@@"), Format(list(i)(1), "@@@"),
Debug.Print list(i)(2); "x"; list(i)(3); "x"; list(i)(4)
Next i
Debug.Print
Debug.Print "area = 210:"
Debug.Print "area perimeter sides"
For i = 0 To UBound(list)
If Val(list(i)(0)) = 210 Then
Debug.Print Format(list(i)(0), "@@@"), Format(list(i)(1), "@@@"),
Debug.Print list(i)(2); "x"; list(i)(3); "x"; list(i)(4)
End If
Next i
End Sub</syntaxhighlight>{{out}}
<pre>Primitive Heronian triangles with sides up to 200: 517 (of 1353400 tested)
 
First 10 ordered by area/perimeter/sides:
area perimeter sides
6 12 5x4x3
12 16 6x5x5
12 18 8x5x5
24 32 15x13x4
30 30 13x12x5
36 36 17x10x9
36 54 26x25x3
42 42 20x15x7
60 36 13x13x10
60 40 17x15x8
 
area = 210:
area perimeter sides
210 70 28x25x17
210 70 29x21x20
210 84 37x35x12
210 84 39x28x17
210 140 68x65x7
210 300 149x148x3</pre>
 
=={{header|Wren}}==
{{libheader|Wren-math}}
{{libheader|Wren-sort}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./math" for Int, Nums
import "./sort" for Sort
import "./fmt" for Fmt
 
var isInteger = Fn.new { |n| n is Num && n.isInteger }
 
var primHeronian = Fn.new { |a, b, c|
if (!(isInteger.call(a) && isInteger.call(b) && isInteger.call(c))) return [false, 0, 0]
if (Int.gcd(Int.gcd(a, b), c) != 1) return [false, 0, 0]
var p = a + b + c
var s = p / 2
var A = (s * (s - a) * (s - b) * (s - c)).sqrt
if (A > 0 && isInteger.call(A)) return [true, A, p]
return [false, 0, 0]
}
 
var ph = []
for (a in 1..200) {
for (b in a..200) {
for (c in b..200) {
var res = primHeronian.call(a, b, c)
if (res[0]) {
var sides = [a, b, c]
ph.add([sides, res[1], res[2], Nums.max(sides)])
}
}
}
}
System.print("There are %(ph.count) primitive Heronian trangles with sides <= 200.")
 
var cmp = Fn.new { |e1, e2|
if (e1[1] != e2[1]) return (e1[1] - e2[1]).sign
if (e1[2] != e2[2]) return (e1[2] - e2[2]).sign
return (e1[3] - e2[3]).sign
}
Sort.quick(ph, 0, ph.count-1, cmp)
System.print("\nThe first 10 such triangles in sorted order are:")
System.print(" Sides Area Perimeter Max Side")
for (t in ph.take(10)) {
var sides = Fmt.swrite("$2d x $2d x $2d", t[0][0], t[0][1], t[0][2])
Fmt.print("$-14s $2d $2d $2d", sides, t[1], t[2], t[3])
}
 
System.print("\nThe triangles in the previously sorted order with an area of 210 are:")
System.print(" Sides Area Perimeter Max Side")
for (t in ph.where { |e| e[1] == 210 }) {
var sides = Fmt.swrite("$2d x $3d x $3d", t[0][0], t[0][1], t[0][2])
Fmt.print("$-14s $3d $3d $3d", sides, t[1], t[2], t[3])
}</syntaxhighlight>
 
{{out}}
<pre>
There are 517 primitive Heronian trangles with sides <= 200.
 
The first 10 such triangles in sorted order are:
Sides Area Perimeter Max Side
3 x 4 x 5 6 12 5
5 x 5 x 6 12 16 6
5 x 5 x 8 12 18 8
4 x 13 x 15 24 32 15
5 x 12 x 13 30 30 13
9 x 10 x 17 36 36 17
3 x 25 x 26 36 54 26
7 x 15 x 20 42 42 20
10 x 13 x 13 60 36 13
8 x 15 x 17 60 40 17
 
The triangles in the previously sorted order with an area of 210 are:
Sides Area Perimeter Max Side
17 x 25 x 28 210 70 28
20 x 21 x 29 210 70 29
12 x 35 x 37 210 84 37
17 x 28 x 39 210 84 39
7 x 65 x 68 210 140 68
3 x 148 x 149 210 300 149
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">include xpllib; \for Min, GCD, StrSort, StrNCmp, and Print
 
func Hero(A, B, C); \Return area squared of triangle with sides A, B, C
int A, B, C, S;
[S:= (A+B+C)/2;
if rem(0) = 1 then return 0; \return 0 if area is not an integer
return S*(S-A)*(S-B)*(S-C);
];
 
func Heronian(A, B, C); \Return area of triangle if sides and area are integers
int A, B, C, Area2, Area;
[Area2:= Hero(A, B, C);
Area:= sqrt(Area2);
return if Area*Area = Area2 then Area else 0;
];
 
def MaxSide = 200;
int A, B, C, Area, Count, I, J, K;
char Array(1000, 5*5);
[Format(5, 0);
Count:= 0;
for A:= 1 to MaxSide do
for B:= A to MaxSide do
for C:= B to Min(A+B-1, MaxSide) do
if GCD(GCD(B,C), A) = 1 then
[Area:= Heronian(A, B, C);
if Area > 0 then
[OpenO(8);
RlOut(8, float(Area));
RlOut(8, float(A+B+C));
RlOut(8, float(C));
RlOut(8, float(B));
RlOut(8, float(A));
OpenI(8);
for I:= 0 to 25-1 do Array(Count,I):= ChIn(8);
Count:= Count+1;
];
];
Print("Count = %d\n", Count);
StrSort(Array, Count);
Print(" A B C Perim Area\n");
for I:= 0 to 10-1 do
[for J:= 4 downto 0 do
Print("%5.5s", @Array(I, J*5+K));
Print("\n");
];
Print("\n");
for I:= 0 to Count-1 do
if StrNCmp(" 210", @Array(I,0), 5) = 0 then
[for J:= 4 downto 0 do
Print("%5.5s", @Array(I, J*5+K));
Print("\n");
];
]</syntaxhighlight>
{{out}}
<pre>
Count = 517
A B C Perim 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
 
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
</pre>
 
=={{header|zkl}}==
{{trans|Python}}
<langsyntaxhighlight lang="zkl">fcn hero(a,b,c){ //--> area (float)
s,a2:=(a + b + c).toFloat()/2, s*(s - a)*(s - b)*(s - c);
(a2 > 0) and a2.sqrt() or 0.0
Line 4,346 ⟶ 5,347:
A:=hero(a,b,c);
(A>0) and A.modf()[1].closeTo(0.0,1.0e-6) and A //--> area or False
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">const MAX_SIDE=200;
heros:=Sink(List);
foreach a,b,c in ([1..MAX_SIDE],[a..MAX_SIDE],[b..MAX_SIDE]){
Line 4,368 ⟶ 5,369:
println("Area Perimeter Sides");
heros.filter(fcn([(h,_)]){ h==210 })
.pump(fcn(phabc){ "%3s %8d %3dx%dx%d".fmt(phabc.xplode()).println() });</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits