漢字プリント 数学プリント
問題文
半径 $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()
解説になっているのか?甚だギモンな動画
「高校数学のエアポケット」に戻る