How to BUILD precise angles with LEGO
The foto shows a construction that makes an
angle of 9 degrees with an error of only
0.01 degrees. (I need this construction to
make a precise cut for another project...
this is not the topic here).
The second foto shows that the angle is
given by five small natural numbers
x1=1 y1=6 x2=2 y2=5 d=4
corresponding to the 10th line of output
of my quick&dirty computer program below.
The third foto shows, how tiny the construction
becomes, if you half the scale by using
jumper plates.
Consider the 5-dimensional space of natural
numbers. If you restrict the numbers to be
not greater than 10, there are 100'000
possible combinations. Though each combination
has a horizontally mirrored combination
giving the same angle. Makes still 50'000.
Only very few of those give the same angle
(I assume if and only if one 5-vector is
the scalar multiple of another).
In other words: You can build any given
angle in good precision (with an average
error around 0.004 degrees or smaller if
you allow larger numbers than 10).
Instead of simply scanning a complete
subspace (e.g. numbers not greater than 10)
my program uses the CANTOR diagonal method
to generate ALL combinations in the order
of increasing sum of components. This way
small solutions will be found first, and
solutions with larger numbers will be
output only if they improve the result.
CANTOR used this method to prove that there
are as many rational numbers as integers.
Here we have more than two dimensions
(numerator and denominator), and I used
recursion to define the scanning.
The program is written in Lua, to make it
run on my iPod (free TouchLua). I personally
prefer LISP for programming. Compared to
other languages, LISP is like LEGO compared
to other toys. Lua is more like LEGO Duplo.
If k is the maximum number of studs to be
considered, the running time of the algorithm
is O(k^5). You could improve this to O(k^4),
if you e.g. compute d' as floating point from
given integers x1,y1,x2,y2 and the target angle.
Then try only the two adjacent integers to d'
for d. But taking the cross-over-point of
those two algorithms and the programming
effort in account, it does not make very
much sense.
target angle/degrees = 9
x1 y1 x2 y2 d alfa error
0 1 0 1 0 0.0000 9.0000
0 1 1 1 1 0.0000 9.0000
1 1 2 1 3 0.0000 9.0000
0 4 0 4 1 14.3615 5.3615
0 5 0 5 1 11.4783 2.4783
0 4 1 3 2 11.1498 2.1498
1 3 1 1 3 6.9676 2.0324
0 6 0 6 1 9.5604 0.5604
0 5 1 4 2 8.7974 0.2026
1 6 2 5 4 8.9889 0.0111
1 5 5 3 7 8.9936 0.0064
6 5 0 2 7 8.9986 0.0014
6 14 0 9 9 9.0010 0.0010
8 7 8 6 17 9.0010 0.0010
13 6 5 1 19 8.9995 0.0005
5 12 7 3 16 9.0004 0.0004
6 13 7 13 15 8.9997 0.0003
6 11 14 6 22 8.9997 0.0003
7 15 7 6 18 8.9998 0.0002
3 13 16 12 21 9.0001 0.0001
7 13 20 10 29 9.0000 0.0000
16 14 15 12 33 9.0000 0.0000
5 21 11 1 27 9.0000 0.0000
22 8 32 3 55 9.0000 0.0000
n=5
v={}
function deg(r)
return r*180/math.pi
end
function rad(d)
return d*math.pi/180
end
function try(x1, y1, x2, y2, d)
local s1, a1, s2, a2, omega, alfa
s1=x1*x1+y1*y1
a1=math.atan(x1/y1)
s2=x2*x2+y2*y2
a2=math.atan(x2/y2)
omega=math.acos((s1+s2-d*d)/2/math.sqrt(s1*s2))
alfa=deg(omega-a1-a2)
error=math.abs(alfa-target)
if error= y2 > 0 and d >= x1+x2
else
for take=0, remaining do
v[i]=take
scan(i+1, remaining-take)
end
end
end
io.write("target angle/degrees = ")
target=io.read("*n")
io.write(" x1 y1 x2 y2 d alfa error\n")
sum=0
besterror=360
repeat
scan(1, sum)
sum=sum+1
until false