September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,86 +0,0 @@
#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';
}

View file

@ -1,23 +0,0 @@
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

View file

@ -1,57 +0,0 @@
import java.util.ArrayList;
public class Heron {
public static void main(String[] args) {
ArrayList<int[]> list = new ArrayList<int[]>();
for(int c = 1; c <= 200; c++){
for(int b = 1; b <= c; b++){
for(int a = 1; a <= b; a++){
if(gcd(gcd(a, b), c) == 1 && isHeron(heronArea(a, b, c)
list.add(new int[]{a, b, c, a + b + c, (int)heronArea(a, b, c)});
}
}
}
sort(list);
System.out.printf("Number of primitive Heronian triangles with sides up to 200: %d\n\nFirst ten when ordered by increasing area, then perimeter:\nSides Perimeter Area", list.size());
for(int i = 0; i < 10; i++){
System.out.printf("\n%d x %d x %d %d %d",list.get(i)[0], list.get(i)[1], list.get(i)[2], list.get(i)[3], list.get(i)[4]);
}
System.out.printf("\n\nArea = 210\nSides Perimeter Area");
for(int i = 0; i < list.size(); i++){
if(list.get(i)[4] == 210)
System.out.printf("\n%d x %d x %d %d %d",list.get(i)[0], list.get(i)[1], list.get(i)[2], list.get(i)[3], list.get(i)[4]);
}
}
public static double heronArea(int a, int b, int c){
double s = (a + b + c)/ 2f;
return Math.sqrt(s *(s -a)*(s - b)*(s - c));
}
public static boolean isHeron(double h){
return h % 1 == 0 && h > 0;
}
public static int gcd(int a, int b){
int leftover = 1, dividend = a > b ? a : b, divisor = a > b ? b : a;
while(leftover != 0){
leftover = dividend % divisor;
if(leftover > 0){
dividend = divisor;
divisor = leftover;
}
}
return divisor;
}
public static void sort(ArrayList<int[]> list){
boolean swapped = true;
int[] temp;
while(swapped){
swapped = false;
for(int i = 1; i < list.size(); i++){
if(list.get(i)[4] < list.get(i - 1)[4] || list.get(i)[4] == list.get(i - 1)[4] && list.get(i)[3] < list.get(i - 1)[3]){
temp = list.get(i);
list.set(i, list.get(i - 1));
list.set(i - 1, temp);
swapped = true;
}
}
}
}
}

View file

@ -1,23 +0,0 @@
Number of primitive Heronian triangles with sides up to 200: 517
First ten when ordered by increasing area, then perimeter:
Sides Perimeter Area
3 x 4 x 5 12 6
5 x 5 x 6 16 12
5 x 5 x 8 18 12
4 x 13 x 15 32 24
5 x 12 x 13 30 30
9 x 10 x 17 36 36
3 x 25 x 26 54 36
7 x 15 x 20 42 42
10 x 13 x 13 36 60
8 x 15 x 17 40 60
Area = 210
Sides Perimeter Area
17 x 25 x 28 70 210
20 x 21 x 29 70 210
12 x 35 x 37 84 210
17 x 28 x 39 84 210
7 x 65 x 68 140 210
3 x 148 x 149 300 210

View file

@ -1,82 +0,0 @@
(function (n) {
var chain = function (xs, f) { // Monadic bind/chain
return [].concat.apply([], xs.map(f));
},
hArea = function (x, y, z) {
var s = (x + y + z) / 2,
a = s * (s - x) * (s - y) * (s - z);
return a ? Math.sqrt(a) : 0;
},
gcd = function (m, n) { return n ? gcd(n, m % n) : m; },
rng = function (m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
},
sum = function (a, x) { return a + x; };
// DEFINING THE SORTED SUB-SET IN TERMS OF A LIST MONAD
var lstHeron = chain( rng(1, n), function (x) {
return chain( rng(x, n), function (y) {
return chain( rng(y, n), function (z) {
return (
(x + y > z) &&
gcd(gcd(x, y), z) === 1 && // Primitive.
(function () { // Heronian.
var a = hArea(x, y, z);
return a && (a === parseInt(a, 10))
})()
) ? [[x, y, z]] : []; // Monadic inject or fail
})})}).sort(function (a, b) {
var dArea = hArea.apply(null, a) - hArea.apply(null, b);
if (dArea) return dArea;
else {
var dPerim = a.reduce(sum, 0) - b.reduce(sum, 0);
return dPerim ? dPerim : (a[2] - b[2]);
}
});
// OUPUT FORMATTED AS TWO WIKITABLES
var lstColumns = ['Sides Perimeter Area'.split(' ')],
fnData = function (lst) {
return [JSON.stringify(lst), lst.reduce(sum, 0), hArea.apply(null, lst)];
},
wikiTable = function (lstRows, blnHeaderRow, strStyle) {
return '{| class="wikitable" ' + (
strStyle ? 'style="' + strStyle + '"' : ''
) + lstRows.map(function (lstRow, iRow) {
var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|');
return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) {
return typeof v === 'undefined' ? ' ' : v;
}).join(' ' + strDelim + strDelim + ' ');
}).join('') + '\n|}';
};
return 'Found: ' + lstHeron.length +
' primitive Heronian triangles with sides up to ' + n + '.\n\n' +
'(Showing first 10, sorted by increasing area, ' +
'perimeter, and longest side)\n\n' +
wikiTable(
lstColumns.concat(lstHeron.slice(0, 10).map(fnData)),
true
) + '\n\n' +
'All primitive Heronian triangles in this range where area = 210\n' +
'\n(also in order of increasing perimeter and longest side)\n\n' +
wikiTable(
lstColumns.concat(lstHeron.filter(function (x) {
return 210 === hArea.apply(null, x);
}).map(fnData)),
true
) + '\n\n';
})(200);

View file

@ -1,4 +1,4 @@
import java.util.*
import java.util.ArrayList
object Heron {
private val n = 200
@ -19,7 +19,7 @@ object Heron {
sort(l)
print("\n\nFirst ten when ordered by increasing area, then perimeter:" + header)
for (i in 0..10 - 1) {
for (i in 0 until 10) {
print(format(l[i]))
}
val a = 210
@ -45,7 +45,7 @@ object Heron {
var swapped = true
while (swapped) {
swapped = false
for (i in 1..l.size - 1)
for (i in 1 until l.size)
if (l[i][4] < l[i - 1][4] || l[i][4] == l[i - 1][4] && l[i][3] < l[i - 1][3]) {
val temp = l[i]
l[i] = l[i - 1]
@ -55,7 +55,7 @@ object Heron {
}
}
private fun isHeron(h: Double) = h.mod(1) == 0.0 && h > 0
private fun isHeron(h: Double) = h.rem(1) == 0.0 && h > 0
private val header = "\nSides Perimeter Area"
private fun format(a: IntArray) = "\n%3d x %3d x %3d %5d %10d".format(a[0], a[1], a[2], a[3], a[4])

View file

@ -0,0 +1,138 @@
/*REXX pgm generates primitive Heronian triangles by side length & area.*/
Call time 'R'
Numeric Digits 12
Parse Arg mxs area list
If mxs ='' Then mxs =200
If area='' Then area=210
If list='' Then list=10
tx='primitive Heronian triangles'
Call heronian mxs /* invoke sub with max SIDES. */
Say nt tx 'found with side length up to' mxs "(inclusive)."
Call show '2'
Call show '3'
Say time('E') 'seconds elapsed'
Exit
heronian:
abc.=0 /* abc.ar.p.* contains 'a b c' for area ar and perimeter p */
nt=0 /* number of triangles found */
min.=''
max.=''
mem.=0
ln=length(mxs)
Do a=3 To mxs
Do b=a To mxs
ab=a+b
Do c=b To mxs
If hgcd(a,b,c)=1 Then Do /* GCD=1 */
ar=heron_area()
If pos('.',ar)=0 Then Do /* is an integer */
nt=nt+1 /* a primitive Heronian triangle.*/
Call minmax '0P',p
Call minmax '0A',a
per=ab+c
abc_ar=right(per,4) right(a,4) right(b,4) right(c,4),
right(ar,5)
Call mem abc_ar
End
End
End
End
End
/*
say 'min.p='min.0p
say 'max.p='max.0p
say 'min.a='min.0a
say 'max.a='max.0a
*/
Return nt
hgcd: Procedure
Parse Arg x
Do j=2 For 2
y=arg(j)
Do Until _==0
_=x//y
x=y
y=_
End
End
Return x
minmax:
Parse Arg which,x
If min.which='' Then Do
min.which=x
max.which=x
End
Else Do
min.which=min(min.which,x)
max.which=max(max.which,x)
End
--Say which min.which '-' max.which
Return
heron_area:
p=ab+c /* perimeter */
s=p/2
ar2=s*(s-a)*(s-b)*(s-c) /* area**2 */
If pos(right(ar2,1),'014569')=0 Then /* ar2 cannot be */
Return '.' /* square of an integer*/
If ar2>0 Then
ar=sqrt(ar2) /* area */
Else
ar='.'
Return ar
show: Parse Arg which
Say ''
Select
When which='2' Then Do
Say 'Listing of the first' list tx":"
Do i=1 To list
Call ot i,mem.i
End
End
When which='3' Then Do
Say 'Listing of the' tx "with area=210"
j=0
Do i=1 To mem.0
Parse Var mem.i per a b c area
If area=210 Then Do
j=j+1
Call ot j,mem.i
End
End
End
End
Return
ot: Parse Arg k,mem
Parse Var mem per a b c area
Say right(k,9)' area:'right(area,6)||,
' perimeter:'right(per,4)' sides:',
right(a,3) right(b,3) right(c,3)
Return
mem:
Parse Arg e
Do i=1 To mem.0
If mem.i>>e Then Leave
End
Do j=mem.0 to i By -1
j1=j+1
mem.j1=mem.j
End
mem.i=e
mem.0=mem.0+1
Return
/* for "Classic" REXX
sqrt: procedure; parse arg x;if x=0 then return 0;d=digits();numeric digits 11
numeric form; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'E'_%2
p=d+d%4+2; m.=11; do j=0 while p>9; m.j=p; p=p%2+1; end; do k=j+5 to 0 by -1
if m.k>11 then numeric digits m.k;g=.5*(g+x/g);end;numeric digits d;return g/1
*/
/* for ooRexx */
::requires rxmath library
::routine sqrt
Return rxCalcSqrt(arg(1),14)

View file

@ -1,29 +0,0 @@
size = 20
number = 0
see " a b c area perimeter" + nl
for i = 1 to size
for j = i + 1 to size
for k = j + 1 to size
perim = (i + j + k) / 2
heronian = sqrt(perim*(perim - i)*(perim - j)*(perim-k))
if heronian = floor(heronian)
if gcd(gcd(i, j),k) = 1
if i + j > k and i + k > j and j + k > i
number += 1
if number <= 20
if len(string(i)) = 1 stri = " " + string(i) else stri = string(i) ok
if len(string(j)) = 1 strj = " " + string(j) else strj = string(j) ok
if len(string(k)) = 1 strk = " " + string(k) else strk = string(k) ok
if len(string(heronian)) = 1 her = " " + string(heronian) else her = string(heronian) ok
see stri + " "+ strj + " "+ strk + " " + her + " " + perim*2 + nl ok ok ok ok
next
next
next
func gcd gcd, b
while b
c = gcd
gcd = b
b = c % b
end
return gcd

View file

@ -0,0 +1,33 @@
h,t = getem(200)
#.sort(h,4,5,1,2,3)
#.output("There are ",t," Heronian triangles")
#.output(" a b c area perimeter")
#.output("----- ----- ----- ------ ---------")
> i, 1..#.min(10,t)
print(h,i)
<
#.output(#.str("...",">34<"))
> i, 1..t
? h[4,i]=210, print(h,i)
<
print(h,i)=
#.output(#.str(h[1,i],">4>")," ",#.str(h[2,i],">4>")," ",#.str(h[3,i],">4>")," ",#.str(h[4,i],">5>")," ",#.str(h[5,i],">8>"))
.
getem(n)=
> a, 1..n
> b, #.upper((a+1)/2)..a
> c, a-b+1..b
x = ((a+b+c)*(a+b-c)*(a-b+c)*(b-a+c))^0.5
>> x%1 | #.gcd(a,b,c)>1
t += 1
h[1,t],h[2,t],h[3,t] = #.sort(a,b,c)
h[4,t],h[5,t] = heron(a,b,c)
<
<
<
<= h,t
.
heron(a,b,c)=
s = (a+b+c)/2
<= (s*(s-a)*(s-b)*(s-c))^0.5, s*2
.

View file

@ -0,0 +1,8 @@
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
}
fcn isHeronian(a,b,c){
A:=hero(a,b,c);
(A>0) and A.modf()[1].closeTo(0.0,1.0e-6) and A //--> area or False
}

View file

@ -0,0 +1,22 @@
const MAX_SIDE=200;
heros:=Sink(List);
foreach a,b,c in ([1..MAX_SIDE],[a..MAX_SIDE],[b..MAX_SIDE]){
if(a.gcd(b).gcd(c)==1 and (h:=isHeronian(a,b,c))) heros.write(T(h,a+b+c,a,b,c));
}
// sort by increasing area, perimeter, then sides
heros=heros.close().sort(fcn([(h1,p1,_,_,c1)],[(h2,p2,_,_,c2)]){
if(h1!=h2) return(h1<h2);
if(p1!=p2) return(p1<p2);
c1<c2;
});
println("Primitive Heronian triangles with sides up to %d: ".fmt(MAX_SIDE),heros.len());
println("First ten when ordered by increasing area, then perimeter,then maximum sides:");
println("Area Perimeter Sides");
heros[0,10].pump(fcn(phabc){ "%3s %8d %3dx%dx%d".fmt(phabc.xplode()).println() });
println("\nAll with area 210 subject to the previous ordering:");
println("Area Perimeter Sides");
heros.filter(fcn([(h,_)]){ h==210 })
.pump(fcn(phabc){ "%3s %8d %3dx%dx%d".fmt(phabc.xplode()).println() });