問題文
半径 $1$ の球に内接する正四面体の一辺の長さを求めよ。(2005 北海道大学 理系第5問 文系第1問)
$$\frac{2\sqrt{6}}{3}$$
※ この答えは学校側が公表したものではありません。個人が作成した非公式の答えです。
コード
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import matplotlib.gridspec as gridspec
from matplotlib.colors import ListedColormap
#紙の準備
fig = plt.figure()
fig.canvas.draw()
fig.suptitle("2005北海道大数学 理系第5問 文系第1問",
color="0.5",ha="right",x=0.95,y=0.95,zorder=-1)
fig.subplots_adjust(left=0.05,right=0.95)
gs = gridspec.GridSpec(1,3)
ax1 = fig.add_subplot(gs[0,0],projection="3d")
ax1.set_box_aspect((1,1,1))
ax1.view_init(30,-105)
ax1.set_xlim(-0.6,0.6)
ax1.set_ylim(-0.6,0.6)
ax1.set_zlim(-0.6,0.6)
ax1.axis("off")
ax2 = fig.add_subplot(gs[0,1:])
width = 12
height = 4
ax2.set_xlim(0,width)
ax2.set_ylim(0,height)
ax2.set_aspect("equal")
ax2.axis("off")
#立体図形の描画
u = np.linspace(0,2*np.pi,100)
v = np.linspace(0, np.pi,100)
x = np.outer(np.cos(u),np.sin(v))
y = np.outer(np.sin(u),np.sin(v))
z = np.outer(np.ones(np.size(u)),np.cos(v))
ax1.plot_surface(x,y,z,cmap="binary",alpha=0.2)
theta = np.linspace(0,2*np.pi,4)
x = 2*np.sqrt(2)/3*np.cos(theta)
y = 2*np.sqrt(2)/3*np.sin(theta)
z = -1/3*np.ones(4)
ax1.plot(x[:2],y[:2],z[:2],color="k",linestyle="dashed",zorder=10)
ax1.plot(x[1:],y[1:],z[1:],color="k",linestyle="solid",zorder=10)
ax1.plot_trisurf(x,y,z,color="0.8")
ax1.quiver(np.zeros(3),np.zeros(3),np.ones(3),
x[:3],y[:3],z[:3]-1,
color="k",linestyle="solid",arrow_length_ratio=0.1)
ax1.quiver(0,0,1,0,0,-1,
color="k",linestyle="dashed",arrow_length_ratio=0.1)
ax1.text(0,0,1.15,"$O$",ha="center",va="center")
ax1.text(1.15*x[0],1.15*y[0],z[0],"$A$",ha="center",va="center")
ax1.text(1.20*x[1],1.20*y[1],z[1],"$B$",ha="center",va="center")
ax1.text(1.25*x[2],1.25*y[2],z[2],"$C$",ha="center",va="center")
ax1.text(0,0,-0.20,"$P$",ha="center",va="center",zorder=10)
#台本
comment1="""\
半径 1 の球に内接する
正四面体の一辺の長さとは?
"""
comment2="""\
鬼
"""
comment3="""\
そう、対称性の鬼になるのだ。
"""
script1={
r"正四面体の中心を $$\mathrm{P}$$ とすると、":0,
r"$$\overrightarrow{\mathstrut\mathrm{OP}}=\frac{1}{4}\,(\,\overrightarrow{\mathstrut\mathrm{OO}}+\overrightarrow{\mathstrut\mathrm{OA}}+\overrightarrow{\mathstrut\mathrm{OB}}+\overrightarrow{\mathstrut\mathrm{OC}}\,)$$":1,
r"$$\overrightarrow{\mathstrut\mathrm{OA}}=\overrightarrow{\mathstrut a},\,\overrightarrow{\mathstrut\mathrm{OB}}=\overrightarrow{\mathstrut b},\,\overrightarrow{\mathstrut\mathrm{OC}}=\overrightarrow{\mathstrut c}$$とすると、":0,
r"$$\overrightarrow{\mathstrut\mathrm{OP}}=\frac{1}{4}\,(\,\overrightarrow{\mathstrut 0}+\overrightarrow{\mathstrut a}+\overrightarrow{\mathstrut b}+\overrightarrow{\mathstrut c}\,)$$":1,
}
script2={
r"$$|\overrightarrow{\mathstrut\mathrm{OP}}|^2=\frac{1}{16}\,|\overrightarrow{\mathstrut a}+\overrightarrow{\mathstrut b}+\overrightarrow{\mathstrut c}|^2$$":0,
r"$$=\frac{1}{16}\,(\,|\overrightarrow{\mathstrut a}|^2+|\overrightarrow{\mathstrut b}|^2+|\overrightarrow{\mathstrut c}|^2$$":1.8,
r"$$+2\overrightarrow{\mathstrut a}\!\cdot\!\overrightarrow{\mathstrut b}+2\overrightarrow{\mathstrut b}\!\cdot\!\overrightarrow{\mathstrut c}+2\overrightarrow{\mathstrut c}\!\cdot\!\overrightarrow{\mathstrut a})$$":3.4,
}
script3={
r"正四面体の一辺の長さを $$a$$ とすると、":0,
r"$$|\overrightarrow{\mathstrut a}|=|\overrightarrow{\mathstrut b}|=|\overrightarrow{\mathstrut c}|=a$$":1,
r"$$\overrightarrow{\mathstrut a}\cdot\overrightarrow{\mathstrut b}=\overrightarrow{\mathstrut b}\cdot\overrightarrow{\mathstrut c}=\overrightarrow{\mathstrut c}\cdot\overrightarrow{\mathstrut a}$$":1,
r"$$=|\overrightarrow{\mathstrut a}||\overrightarrow{\mathstrut b}|\cos60^{\circ}=a^2\cos60^{\circ}=\frac{1}{2}\,a^2$$":1,
}
script4={
r"$$|\overrightarrow{\mathstrut\mathrm{OP}}|^2=\frac{1}{16}\,(\,3\,a^2+3\cdot2\cdot\frac{1}{2}\,a^2\,)$$":0,
r"$$=\frac{1}{16}\times 6\,a^2=\frac{3}{8}\,a^2$$":1.8,
r"球の半径は $$1$$ なので、":0,
r"$$|\overrightarrow{\mathstrut\mathrm{OP}}|^2=\frac{3}{8}\,a^2=1$$":2,
r"したがって、 $$a^2=\frac{8}{3}$$":1.2,
r"$$a>0$$ より、 $$a=\frac{2\sqrt{2}}{\sqrt{3}}=\frac{2\sqrt{6}}{3}":1,
}
comment4="""\
(答) $\\frac{2\sqrt{6}}{3}$
"""
comment5="""\
END
"""
#定数の準備
base = height/5
delta = 0.1
colors = [(1,1,1,alpha) for alpha in np.arange(0,11)/10]
cmap = ListedColormap(colors)
#数式の部分だけLATEX変換
def show_line(x,y,line,alpha=1.0):
img = []
left = x
pieces = line.split("$$")
for i,piece in enumerate(pieces):
if i%2==0:
fdic={
"usetex" : False,
"clip_on" : True,
"animated" : True,
"fontsize" : 12,
"fontfamily": "Meiryo",
"verticalalignment" : "baseline",
}
else:
fdic={
"usetex" : True,
"clip_on" : True,
"animated" : True,
"fontsize" : 16,
"verticalalignment" : "baseline",
}
piece = "$\\displaystyle " + piece + "$"
text = ax2.text(left,y,piece,alpha=alpha,fontdict=fdic)
img += [text]
bbox = text.get_window_extent().transformed(ax2.transData.inverted())
right = bbox.x1
left = right
return img,right
#余韻を残すための関数
def lingering(imgs,frames):
img = imgs[-1]
for i in range(frames):
imgs.append(img)
#数式が徐々に現れる関数
def appearing(i,X,Y):
C = np.zeros(len(X)-1)
C[2*i+1:2*i+20] = np.arange(0.05,1.00,0.05)
C[2*i+20:] = 1
C = np.reshape(C,(len(X)-1,1))
img = ax2.pcolormesh(X,Y,C,cmap=cmap,zorder=10)
return img
#最初の1行目を表示する関数
def show_first_line(imgs,line,left):
i = 0
while True:
img,right = show_line(left,base+height/2,line)
X,Y = np.mgrid[left-2:right+2:delta,height/2:3*height/2:height/2]
img += [appearing(i,X,Y)]
imgs.append(img)
i += 1
if 2*i+20 > len(X)-1:
break
#2行目を表示する関数
def show_second_line(imgs,line1,line2,left1,left2):
i = 0
while True:
img1,right1 = show_line(left1,base+height/2,line1)
img2,right2 = show_line(left2,base,line2)
img = img1 + img2
X,Y = np.mgrid[left2-2:right2+2:delta,0:height:height/2]
img += [appearing(i,X,Y)]
imgs.append(img)
i += 1
if 2*i+20 > len(X)-1:
break
#次の数式へと進む関数
def go_next_line(imgs,line1,line2,left1,left2):
for i in range(21):
alpha = max((10-i)/10,0)
img1,right1 = show_line(left1,base+height/2+height*i/40,line1,alpha)
img2,right2 = show_line(left2,base+height*i/40,line2)
img = img1 + img2
imgs.append(img)
#数式の解説を読み込む関数
def load_script(imgs,script):
N = len(script)
lines = list(script.keys())
lefts = list(script.values())
show_first_line(imgs,lines[0],lefts[0])
for k in range(N-2):
show_second_line(imgs,lines[k],lines[k+1],lefts[k],lefts[k+1])
go_next_line(imgs,lines[k],lines[k+1],lefts[k],lefts[k+1])
show_second_line(imgs,lines[N-2],lines[N-1],lefts[N-2],lefts[N-1])
lingering(imgs,30)
#コメントの部分の関数
def interlude(imgs,str_comment,frames):
fdic_wc={
"ha" : "center",
"va" : "center",
"size" : 20,
"color" : "white",
"animated" : True,
"fontfamily": "Meiryo",
}
boxdic={
"facecolor" : "black",
"pad" : 300,
}
for i in range(frames):
interlude=ax2.text(width/4,height/2,str_comment,
fontdict=fdic_wc,bbox=boxdic)
imgs.append([interlude])
#上演
imgs=[]
interlude(imgs,comment1,60)
interlude(imgs,comment2,10)
interlude(imgs,comment3,30)
load_script(imgs,script1)
load_script(imgs,script2)
load_script(imgs,script3)
load_script(imgs,script4)
interlude(imgs,comment4,30)
interlude(imgs,comment5,30)
mov=ani.ArtistAnimation(fig, imgs, 100)
plt.show()