How many Obtuse angled triangles are there?

Principal Topics

?. (roll) o. (circle functions) : (grade down) ~ (reflex), simulation, random numbers, random angles, accept-reject technique

In the world, that is. Lots, I know, but let me ask rather what proportion of all triangles in the world are obtuse-angled? Since any two of the angles, say a and b, of a triangle can be determined independently, the every possible triangle corresponds to a point within the large right-angled triangle in the diagram below

Acute-angled triangles must have a+b>90o and so their points all lie within the inner triangle, from which it follows that 75% of all triangles are obtuse-angled. Well let’s ask J and see what he/she/it says using statistical Monte-Carlo methods. Assume that a point is represented by a 2-list of numbers such as 4 7. The verb `py` calculates the square of the distance between two such points

```   py=.(+/@:*:@:-/)"2    NB. square of dist between 2 points
py 4 7,:1 3           NB. (3,4,5) triangle
25```

A triangle is a 3-list of 2-lists (points). To calculate the squares of the three sides, take the points in pairs and apply `py` :

```   sides =: 2 [\ 4&\$
]t=: 3 2\$_3 _2 _1 6 0 2
_3 _2
_1  6
0  2
<"2 sides t
┌─────┬────┬─────┐
│_3 _2│_1 6│ 0  2│
│_1  6│ 0 2│_3 _2│
└─────┴────┴─────┘```

A triangle is obtuse if the square of the largest side exceeds the sum of the squares of the other two, so define ifbigone which uses reflexive grade down to test whether the largest of a set of numbers is greater than the sum of all the others

```   ifbigone =: ({. > +/@}.)@\:~     NB. 1 if biggest > +/rest
ifbigone 49 43 100
1```

```   obtest =: ifbigone@:(py"2@sides)"2 NB. 1 if obtuse
obtest t
1```

randtri1 generates y random triangles with vertices in the unit square:

```   randtri1 =: 0 ?@\$~ ,&3 2

<"2 randtri1 3
┌─────────────────┬─────────────────┬─────────────────┐
│0.577101 0.430063│0.356508 0.879054│0.190733 0.629572│
│0.689446 0.610395│0.898293  0.11287│ 0.45149 0.964217│
│0.401262 0.267585│0.184275 0.444405│0.482228 0.170644│
└─────────────────┴─────────────────┴─────────────────┘
```

Everything is now in place to test a single random triangle with given resolution :

```   trial1=.obtest@:randtri1     NB. 1 if obtuse
trial1 8
0 0 1 1 1 0 0 1```

Of the triangles in this particular trial four of eight were obtuse-angled. Here are a thousand trials:

```   +/ trial1 1000
740
```

... and a few more :

```   +/ trial1 1000
739
+/ trial1 1000
708
+/ trial1 1000
736
```

By now you should be getting a feel for where the true value lies, somewhere between 72 and 75 per cent. Another way to conduct the simulation is to generate random angles rather than random sides. Start by writing a verb which generates a number of random values (angles) between 0 and 2π to use as angles from the origin to the vertex:

```   rnd =: ?@\$&0    NB. y rand uniform nos. in (0,1)
TAU =: 2p1             NB. tauday.com
randang =: TAU * rnd    NB. random angles in radians
randang 3
5.66985 3.78605 2.69206```

The sines and cosines of each angle generate a point within the unit circle, and so random angles can be transformed to random points within the unit circle by

```   cs =: 2 1 o.~/~ randang

cs 8
0.515802 _0.856708
0.19751 _0.980301
0.590711  0.806883
_0.659526 _0.751682
_0.451618 _0.892211
_0.956942  _0.29028
_0.980289 _0.197569
_0.4976  0.867407
```

and then to y random triangles in a unit circle by

```   randtri2 =: [: cs ,&3

<"2 randtri2 4
┌──────────────────┬──────────────────┬─────────────────────┬────────────────────┐
│_0.718971  0.69504│ 0.503937 _0.86374│0.0327604   _0.999463│_0.998892 _0.0470605│
│  0.96262 0.270857│_0.795225 0.606314│ _0.91815   _0.396232│_0.554286   0.832326│
│ 0.442591 0.896724│_0.401744 0.915752│ 0.999965 _0.00831741│ 0.727516  _0.686091│
└──────────────────┴──────────────────┴─────────────────────┴────────────────────┘```

All is in place for determining whether these triangles are obtuse or not, and for doing some more experiments

```   ([: +/ trial2)@:(1000"_) ^:(>: i. 4) ''
763 710 754 736
```

A little bit higher than our previous estimate, but close to the theoretical 75%. Maybe sampling from a square frame includes disproportionately ‘skinny’ acute-angled triangles which have one vertex tucked into one of the far corners. To test this conjecture, sample the coordinates within a square, but filter only those triangles all of whose points lie inside the unit circle. The polynomial transforms the triangle vertices to have absolute value <: 1 . All of these must have length <: 1.

```   ssq =: +/@:*:    NB. sum of squares
randtri3 =: (#~ ([: (*./"1) 1 >: ssq"1))@:(_1 2 p. randtri1)

NB. graphics shows the remaining points are within the unit circle
require 'plot'
'point'plot _2 j./\ , randtri3 999
```

As before everything is in place for the next experiment. Since randtri3 generates fewer triangles than requested, include the average :

```      (+/ % #) trial3 10000
0.729905```

Not much different from `trial1` – ah well, that’s one conjecture gone for a bang!

Another accept-reject technique for random triangles consists of generating the values of three random sides in order, and rejecting the result if the sides fail to form a triangle because one of them is bigger than the sum of the other two :

```   randtri4 =: (#~ (>./ < +/ - >./)"1)@:([: rnd ,&3)

randtri4 9
0.482861 0.631554 0.575322
0.790549  0.74182 0.983299
0.21859 0.814304 0.746637
0.758181 0.448893 0.836001
```

Since randtri4 returns lengths of sides the obtuseness test is applied to the squares of the sides :

```   trial4 =: ifbigone"1@:*:@randtri4

(+/ % #) trial4 99999
0.57199```

Seems I’ve mislaid nearly 20% of the world’s obtuse-angled triangles (careless of me!) Another possibility based on sides is to choose two sides at random, say these were 6 and 10. The range of acceptable values for a third side is then from 10-6 to 10+6, or more generally from m-n to m+n where m and n are the lengths of the sides in decreasing order. The third side can then be taken as (m-n) plus a number drawn at random from 0 to 2n:

```   avg =: +/ % #
rnd =: ?@\$&0
third =: , (>./ + <./ * _1 2 p. ?@:0:)
rantri5 =: [: third"1 [: rnd ,&2
trial5 =: ifbigone"1@:*:@rantri5
avg trial5 100000
0.73331```

Let’s get back to the original question . How many obtuse-angled triangles did I say there were? ...

Code Summary

```trial1=: obtest@randtri1                NB. first random trial
obtest =: ifbigone@:(py"2@sides)"2      NB. 1 if obtuse
ifbigone =: ({. > +/@}.)@\:~            NB. 1 if biggest > +/rest
py =: (+/@:*:@:-/)"2                    NB. sq of dist between 2 pts
sides =: 2 [\ 4&\$                       NB. sides from coords
randtri1 =: 0 ?@\$~ ,&3 2                NB. generate y triangles in unit square

trial2 =: obtest@randtri2               NB. second random trial
randtri2 =: [: cs ,&3
cs =: 2 1 o.~/~ randang                 NB. cos/sin of rand angle
TAU =: 2p1
randang =: TAU * rnd                    NB. random angles in radians
rnd =: ?@\$&0                            NB. random values on (0,1) with shape y

trial3 =: obtest@randtri3               NB. third random trial

randtri3 =: (#~ ([: (*./"1) 1 >: ssq"1))@:(_1 2 p. randtri1)
NB. generate at most y triangles in unit square,
NB. discarding those outside the inscribed circle.

ssq =: +/@:*:                           NB. sum of squares

trial4 =: ifbigone@:*:@randtri4         NB. fourth random trial
randtri4 =: (#~ (>./ < +/ - >./)"1)@:([: rnd ,&3)
NB. generate at most y triangles by random length sides
NB. discarding triples which can not form triangles.

trial5 =: ifbigone@:*:@rantri5          NB. fifth random trial
rantri5 =: [: third"1 [: rnd ,&2        NB. choose 2 sides, 3rd side randomly chosen as plausible
third =: , (>./ + <./ * _1 2 p. ?@:0:)  NB. join feasible third side
```