算額(その853)
十七 岩手県平泉町 中尊寺金色堂(現存しない) 文政8年(1825)
山村善夫:現存 岩手の算額,昭和52年1月30日,熊谷印刷,盛岡市. http://www.wasan.jp/yamamura/yamamura.html
直角三角形(鈎股弦)内に隔斜を 2 本引き,区画された領域に等円を 2 個入れる。鈎,股,弦は,「5(鈎 + 股 + 弦) - 37(股 - 鈎) = 1」という条件式が成り立つとき(「鈎^2 + 股^2 = 弦^2」は当然),等円の直径はいかほどか。
鈎股弦内に隔斜 2 本と等円 2 個を入れるという問は他にもある。算額(その139),算額(その280)
この算額では,鈎股弦の条件の出し方が独特である。
もし大学入試の数学の問題だと整数方程式を如何に効率的に解くかということになるかもしれないが,プログラムで全探索するほうが手っ取り早い。
念の為, 鈎,股 が 10000 まで探索すると,解は 28, 45, 53 の一組しかない。
include("julia-source.txt");
#=
mx = 10000
for 鈎 = 1:mx, 股 = 鈎 + 1:mx
弦 = sqrt(鈎^2 + 股^2)
if 5(鈎 + 股 + 弦) - 37(股 - 鈎) == 1
@printf("%g; %g; %g\n", 鈎, 股, 弦)
end
end
=#
鈎 = 28, 股 = 45 円の半径を r,それぞれの中心座標を (r, y), (x, r) とおき,直線までの距離に関する方程式を立て,解く。
SymPy の solve() では能力不足で解けないので,nlsolve() で数値解を求めるのが簡単であるが,変数を手動で消去していって r を求める手順を示してみよう。
まずは,式を簡単にするために,円の中心から隔斜までの距離の式を通覧する。
using SymPy
dist2(x1, y1, x2, y2, x3, y3, r) = numerator(apart(dist(x1, y1, x2, y2, x3, y3) - r^2, d))
@syms 鈎::positive, 股::positive, 弦::positive,
r::positive, x::positive, y::positive, x0::positive, y0::positive,
d;
eq1 = dist2(0, 鈎, x0, y0, r, y, r) # 円1の中心から BD への距離
eq2 = dist2(0, 鈎, x0, y0, x, r, r) # 円2の中心から BD への距離
eq3 = dist2(0, 鈎, 股, 0, x, r, r) # 円2の中心から AB への距離
eq4 = dist2(0, 0, x0, y0, r, y, r) # 円1の中心から OC への距離
eq5 = dist2(0, 0, x0, y0, x, r, r); # 円2の中心から OC への距離
println(eq1, ", # eq1")
println(eq2, ", # eq2")
println(eq3, ", # eq3")
println(eq4, ", # eq4")
println(eq5, ", # eq5")
-r^2*x0^2 - 2*r*x0*y*y0 + 2*r*x0*y*鈎 + 2*r*x0*y0*鈎 - 2*r*x0*鈎^2 + x0^2*y^2 - 2*x0^2*y*鈎 + x0^2*鈎^2, # eq1
-r^2*y0^2 + 2*r^2*y0*鈎 - r^2*鈎^2 - 2*r*x*x0*y0 + 2*r*x*x0*鈎 - 2*r*x0^2*鈎 + x^2*y0^2 - 2*x^2*y0*鈎 + x^2*鈎^2 + 2*x*x0*y0*鈎 - 2*x*x0*鈎^2 + x0^2*鈎^2, # eq2
-r^2*鈎^2 + 2*r*x*股*鈎 - 2*r*股^2*鈎 + x^2*鈎^2 - 2*x*股*鈎^2 + 股^2*鈎^2, # eq3
-r^2*x0^2 - 2*r*x0*y*y0 + x0^2*y^2, # eq4
-r^2*y0^2 - 2*r*x*x0*y0 + x^2*y0^2, # eq5
最初に,eq5 を x について解く。
res1 = solve(eq5, x0)[1]
res1 |> println
y0*(-r^2 + x^2)/(2*r*x)
eq1 〜 eq4 に x0 = y0*(-r^2 + x^2)/(2*r*x) を代入する。結果の方程式は eq11 〜 eq14
eq11 = numerator(apart(eq1(x0 => res1), d))/y0/(x - r)/(x + r) |> factor;
eq12 = numerator(apart(eq2(x0 => res1), d))/鈎/(x - r)/(x + r) |> factor;
eq13 = numerator(apart(eq3(x0 => res1), d))/鈎 |> factor;
eq14 = numerator(apart(eq4(x0 => res1), d))/y0^2/(x - r)/(x + r) |> factor;
次に eq14 を x について解く。
res2 = solve(eq14, x)[1]
res2 |> println
r*(r + y)/(-r + y)
eq11 〜 eq14 に x = r*(r + y)/(-r + y) を代入する。
eq21 = numerator(apart(eq11(x => res2), d))/(4r^3*鈎) |> factor;
eq22 = numerator(apart(eq12(x => res2), d))/(4r^3) |> factor;
eq23 = numerator(apart(eq13(x => res2), d)) |> factor;
次に eq21 を y0 について解く。
res3 = solve(eq21, y0)[1]
res3 |> println
(-r^2*y + r^2*鈎 + y^3 - y^2*鈎)/(r^2 + y^2 - y*鈎)
eq21 〜 eq23 に y0 = (-r^2*y + r^2*鈎 + y^3 - y^2*鈎)/(r^2 + y^2 - y*鈎) を代入する。
eq32 = numerator(apart(eq22(y0 => res3), d))/(y*(r + y)^2) |> factor
eq32 |> println
(-r^2 - 2*r*y + 2*r*鈎 + y^2 - y*鈎)*(-r^3 + r^2*y - r^2*鈎 - r*y^2 + r*鈎^2 + y^3 - y^2*鈎)
eq33 = numerator(apart(eq23(y0 => res3), d)) |> factor;
eq32 は 式1*式2 の形で,-r^2 - 2*r*y + 2*r*鈎 + y^2 - y*鈎 = 0 を解けばよい。
eq32_1 = (-r^2 - 2*r*y + 2*r*鈎 + y^2 - y*鈎);
eq32_1 を y について解く。
res4 = solve(eq32_1, y)[1]
res4 |> println
r + 鈎/2 - sqrt(8*r^2 - 4*r*鈎 + 鈎^2)/2
eq33 に y = r + 鈎/2 - sqrt(8*r^2 - 4*r*鈎 + 鈎^2)/2 を代入する。
eq42 = eq33(y => res4) |> simplify
eq42 |> factor |> println
(2*r*股 + 2*r*鈎 - 股*鈎)*(4*r^3 - 4*r^2*股 + 2*r^2*鈎 - 2*r^2*sqrt(8*r^2 - 4*r*鈎 + 鈎^2) + 2*r*股*鈎 - 股*鈎^2 + 股*鈎*sqrt(8*r^2 - 4*r*鈎 + 鈎^2))/2
sqrt(8*r^2 - 4*r*鈎 + 鈎^2) でまとめ,二乗してルートを外す。
using SymPy
@syms 鈎::positive, 股::positive, 弦::positive,
r::positive, x::positive, y::positive, x0::positive, y0::positive
eq01 = (4*r^3 - 4*r^2*股 + 2*r^2*鈎 + 2*r*股*鈎 - 股*鈎^2)^2 - (股*鈎 - 2*r^2)^2*(8*r^2 - 4*r*鈎 + 鈎^2) |> factor
eq01 |> println
-4*r^2*(4*r^4 + 8*r^3*股 - 8*r^3*鈎 - 4*r^2*股^2 - 8*r^2*股*鈎 + 4*r*股^2*鈎 + 4*r*股*鈎^2 - 股^2*鈎^2)
eq02 = eq01/(-4r^2)
eq02 |> println
4*r^4 + 8*r^3*股 - 8*r^3*鈎 - 4*r^2*股^2 - 8*r^2*股*鈎 + 4*r*股^2*鈎 + 4*r*股*鈎^2 - 股^2*鈎^2
鈎,股に具体値を代入してプロットしてみる。
eq03 = eq02(鈎 => Sym(28), 股 => Sym(45))
4*r^4 + 8*r^3*股 - 8*r^3*鈎 - 4*r^2*股^2 - 8*r^2*股*鈎 + 4*r*股^2*鈎 + 4*r*股*鈎^2 - 股^2*鈎^2
using Plots
pyplot(size=(400, 200), grid=false, aspectratio=:none, label="", fontfamily="IPAMincho");
plot(eq03, xlims=(4, 32))
hline!([0])
3 個の実数解が得られるが r = 6 が適解である。
solve(eq03, r)
3-element Vector{Sym{PyCall.PyObject}}:
6
30
-35 + 7⋅√70
あとは,交代代入を繰り返し,ここまでで変数消去されていた変数の値を確定していけばよい。
(鈎, 股) = (28, 45)
r = 6
y = r + 鈎/2 - sqrt(8*r^2 - 4*r*鈎 + 鈎^2)/2
y0 = (-r^2*y + r^2*鈎 + y^3 - y^2*鈎)/(r^2 + y^2 - y*鈎)
x = r*(r + y)/(-r + y)
x0 = y0*(-r^2 + x^2)/(2*r*x)
(r, y, y0, x, x0)
(6, 10.0, 8.0, 24.0, 15.0)
NLsolve() で数値解を求めるほうが,簡単である。
using NLsolve
function nls(func, params...; ini = [0.0])
if typeof(ini) <: Number</span>
r = nlsolve((vout, vin) -> vout[1] = func(vin[1], params..., [ini]), ftol=big"1e-40")
v = r.zero[1]
else
r = nlsolve((vout, vin)->vout .= func(vin, params...), ini, ftol=big"1e-40")
v = r.zero
end
return Float64.(v), r.f_converged
end;
function H(u)
(r, x, y, x0, y0) = u
return [
-r^2*x0^2 - 2*r*x0*y*y0 + 2*r*x0*y*鈎 + 2*r*x0*y0*鈎 - 2*r*x0*鈎^2 + x0^2*y^2 - 2*x0^2*y*鈎 + x0^2*鈎^2, # eq1
-r^2*y0^2 + 2*r^2*y0*鈎 - r^2*鈎^2 - 2*r*x*x0*y0 + 2*r*x*x0*鈎 - 2*r*x0^2*鈎 + x^2*y0^2 - 2*x^2*y0*鈎 + x^2*鈎^2 + 2*x*x0*y0*鈎 - 2*x*x0*鈎^2 + x0^2*鈎^2, # eq2
-r^2*鈎^2 + 2*r*x*股*鈎 - 2*r*股^2*鈎 + x^2*鈎^2 - 2*x*股*鈎^2 + 股^2*鈎^2, # eq3
-r^2*x0^2 - 2*r*x0*y*y0 + x0^2*y^2, # eq4
-r^2*y0^2 - 2*r*x*x0*y0 + x^2*y0^2, # eq5
]
end;
(鈎, 股, 弦) = (28, 45, 53)
iniv = BigFloat[5.0, 20, 11, 12, 10]
res = nls(H, ini=iniv)
([6.0, 24.0, 10.0, 15.0, 8.0], true)
function draw(more=false)
pyplot(size=(500, 500), grid=false, aspectratio=1, label="", fontfamily="IPAMincho")
(鈎, 股, 弦) = (28, 45, 53)
(r, x, y, x0, y0) = res[1]
plot([0, 股, 0, 0], [0, 0, 鈎, 0], color=:blue, lw=0.5)
circle(r, y, r)
circle(x, r, r)
(X1, Y1) = intersection(0, 0, x0, y0, 0, 鈎, 股, 0)
segment(0, 0, X1, Y1, :green)
(X2, Y2) = intersection(0, 鈎, x0, y0, 0, 0, 股, 0)
segment(0, 鈎, X2, Y2, :green)
if more
delta = (fontheight = (ylims()[2]- ylims()[1]) / 500 * 10 * 2) /3 # size[2] * fontsize * 2
hline!([0], color=:gray80, lw=0.5)
vline!([0], color=:gray80, lw=0.5)
point(x, r, "等円:r,(x,r)", :red, :center, delta=-delta/2)
point(r, y, "等円:r,(r,y)", :red, :center, delta=-delta/2)
point(x0, y0, "(x0,y0)", :green, :left, :bottom, delta=4delta, deltax=-4delta)
point(股, 0, " 股", :blue, :left, :bottom, delta=delta/2)
point(0, 鈎, " 鈎", :blue, :left, :bottom, delta=delta/2)
end
end;