漢字プリント 数学プリント
問題文
次の定積分を求めよ。 $$\int_0^1 \left( x^2 + \frac{x}{\sqrt{1+x^2}} \right) \left( 1 + \frac{x}{(1+x^2)\sqrt{1+x^2}} \right) dx$$
(2019 東京大学 理系第1問)
$$\frac{\pi}{8}+\frac{5\sqrt{2}}{2}-\frac{35}{12}$$
※ この答えは学校側が公表したものではありません。個人が作成した非公式の答えです。
コード
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as ani
from matplotlib.colors import ListedColormap

#紙の準備よし
fig = plt.figure()
fig.canvas.draw()
fig.suptitle("2019東大数学 理系第1問",
             color="0.5",ha="right",x=0.95,y=0.95,zorder=-1)
width = 12
height = 4
ax = fig.add_subplot(111)
ax.set_xlim(0,width)
ax.set_ylim(0,height)
ax.set_aspect("equal")
ax.axis("off")

#フォントの準備よし
fdic={
"usetex" : True,
"clip_on" : True,
"animated" : True,
"fontsize"  : 18,
"fontfamily": "Meiryo",
"verticalalignment" : "baseline",
}
fdic_wc={
"ha" : "center",
"va" : "center",
"size" : 20,
"color" : "white",
"animated" : True,
"fontfamily": "Meiryo",
}
boxdic={
"facecolor" : "black",
"pad" : 300,
}

#台本
str_int0 = r"\int_0^1 \left( x^2 + \frac{x}{\sqrt{1+x^2}} \right) \left( 1 + \frac{x}{(1+x^2)\sqrt{1+x^2}} \right) dx"
str_int1 = r"\int_0^1 x^2 \, dx"
str_int2 = r"\int_0^1 \frac{x}{\sqrt{1+x^2}} \, dx"
str_int3 = r"\int_0^1 \frac{x^3}{(1+x^2)\sqrt{1+x^2}} \, dx"
str_int4 = r"\int_0^1 \frac{x^2}{(1+x^2)^2} \, dx"

lines1=[
r"=\left[ \, \frac{1}{3} x^3 \, \right]_0^1",
r"=\frac{1}{3}",
]
before2=[
"$t=1+x^2$ とおくと、$dt=2xdx$",
"$x:0\\longrightarrow1$ のとき、$t:1\\longrightarrow2$",
]
lines2=[
r"=\int_0^1 \frac{x}{(1+x^2)^\frac{1}{2}} \, dx",
r"=\int_0^1 \frac{1}{2(1+x^2)^\frac{1}{2}} \, 2xdx",
r"=\int_1^2 \frac{1}{2\,t^\frac{1}{2}} \, dt",
r"=\int_1^2 \frac{1}{2} \,t^{-\frac{1}{2}} \, dt",
r"=\left[ \, t^\frac{1}{2} \, \right]_1^2",
r"=\sqrt{2}-1",
]
lines3=[
r"=\int_0^1 \frac{x^3}{(1+x^2)^\frac{3}{2}} \, dx",
r"=\int_0^1 \frac{x^2}{2(1+x^2)^\frac{3}{2}} \, 2xdx",
r"=\int_1^2 \frac{t-1}{2\,t^\frac{3}{2}} \, dt",
r"=\int_1^2 ( \, \frac{1}{2}\,t^{-\frac{1}{2}} - \frac{1}{2}\,t^{-\frac{3}{2}} \, ) \, dt",
r"=\left[ \, t^\frac{1}{2} + t^{-\frac{1}{2}} \, \right]_1^2",
r"=(\sqrt{2}-1)+(\frac{1}{\sqrt{2}}-1)",
r"=\frac{3}{2}\sqrt{2}-2",
]
before4=[
"$x=\\tan\\theta$ とおくと、$dx=\\frac{1}{\\cos^2\\theta}\\,d\\theta$",
"$x:0\\longrightarrow1$ のとき、$\\theta:0\\longrightarrow^{\\pi}/_4$",
]
lines4=[
r"=\int_0^{\frac{\pi}{4}} \frac{\tan^2\theta}{(1+\tan^2\theta)^2} \cdot \frac{1}{\cos^2\theta} \, d\theta",
r"=\int_0^{\frac{\pi}{4}} \tan^2\theta \cdot \cos^4\theta \cdot \frac{1}{\cos^2\theta} \, d\theta",
r"=\int_0^{\frac{\pi}{4}} \tan^2\theta \cdot \cos^2\theta \, d\theta",
r"=\int_0^{\frac{\pi}{4}} \sin^2\theta \, d\theta",
r"=\int_0^{\frac{\pi}{4}} \frac{1-\cos2\theta}{2} \, d\theta",
r"=\left[ \, \frac{1}{2}\,\theta - \frac{1}{4}\sin2\theta\, \right]_0^{\frac{\pi}{4}}",
r"=\frac{\pi}{8} - \frac{1}{4}",
]
lines5=[
r"= \frac{1}{3} + (\sqrt{2}-1) + (\, \frac{3}{2}\sqrt{2}-2 \,) + (\, \frac{\pi}{8} - \frac{1}{4} \,)",
r"= \frac{\pi}{8} + \frac{5}{2}\sqrt{2} - \frac{35}{12}",
]

#定数のセッティング
base = height/5
delta = 0.1
colors = [(1,1,1,alpha) for alpha in np.arange(0,11)/10]
cmap = ListedColormap(colors)

#LATEXの数式に変換
def dmath(str_latex):
    return "$\\displaystyle " + str_latex + "$"

#与式を表示する関数
def Ltext(str_left):
    text = ax.text(0,base+height/2,dmath(str_left),
                   fontdict=fdic,zorder=10)
    bbox = text.get_window_extent().transformed(ax.transData.inverted())
    return text,bbox.x1+0.2

#余韻を残すための関数
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 = ax.pcolormesh(X,Y,C,cmap=cmap,zorder=10)
    return img
    
#問題の定積分を表示する関数
def integrals(col1,col2,col3,col4,col_others):
    
    text0 = ax.text(0,base+height,dmath(str_int0),
                    color=col_others,fontdict=fdic,clip_on=False)
    
    sign1 = ax.text(0,base+height/2,"$=$",
                    color=col_others,fontdict=fdic)
    bbox  = sign1.get_window_extent().transformed(ax.transData.inverted())
    text1 = ax.text(bbox.x1,base+height/2,dmath(str_int1),
                    color=col1,fontdict=fdic)
    bbox  = text1.get_window_extent().transformed(ax.transData.inverted())
    
    sign2 = ax.text(bbox.x1+0.2,base+height/2,"$+$",
                    color=col_others,fontdict=fdic)
    bbox  = sign2.get_window_extent().transformed(ax.transData.inverted())
    text2 = ax.text(bbox.x1,base+height/2,dmath(str_int2),
                    color=col2,fontdict=fdic)
    
    sign3 = ax.text(0.6,base,"$+$",
                    color=col_others,fontdict=fdic)
    bbox  = sign3.get_window_extent().transformed(ax.transData.inverted())
    text3 = ax.text(bbox.x1,base,dmath(str_int3),
                    color=col3,fontdict=fdic)
    bbox  = text3.get_window_extent().transformed(ax.transData.inverted())
    
    sign4 = ax.text(bbox.x1+0.2,base,"$+$",
                    color=col_others,fontdict=fdic)
    bbox  = sign4.get_window_extent().transformed(ax.transData.inverted())
    text4 = ax.text(bbox.x1,base,dmath(str_int4),
                    color=col4,fontdict=fdic)
    
    img = [text0]+[sign1]+[text1]+[sign2]+[text2]+[sign3]+[text3]+[sign4]+[text4]
    return img

#最初の1行目を表示する関数
def show_first_line_with_left(imgs,str_Ltext,lines,is_latex):
    text1,left = Ltext(str_Ltext)
    if is_latex:
        str2 = dmath(lines[0])
    else:
        str2 = lines[0]
    text2 = ax.text(left,base+height/2,str2,
                    fontdict=fdic,usetex=is_latex)
    bbox  = text2.get_window_extent().transformed(ax.transData.inverted())
    
    i = 0
    while True:
        img =  [text1]
        img += [text2]
        X,Y = np.mgrid[left-2:left+bbox.x1+2:delta,height/2:3*height/2:height/2]
        #img += ax.plot([bbox.x0, bbox.x0, bbox.x1, bbox.x1, bbox.x0], [bbox.y0, bbox.y1, bbox.y1, bbox.y0, bbox.y0])
        img += [appearing(i,X,Y)]
        imgs.append(img)
        i += 1
        if 2*i+20 > len(X)-1:
            break

#2行目を表示する関数
def show_second_line_with_left(imgs,str_Ltext,lines,k,is_latex):
    text1,left = Ltext(str_Ltext)
    if is_latex:
        str2 = dmath(lines[k])
        str3 = dmath(lines[k+1])
    else:
        str2 = lines[k]
        str3 = lines[k+1]
    text2 = ax.text(left,base+height/2,str2,
                    fontdict=fdic,usetex=is_latex)
    text3 = ax.text(left,base,str3,
                    fontdict=fdic,usetex=is_latex)
    bbox = text3.get_window_extent().transformed(ax.transData.inverted())
    
    i = 0
    while True:
        img =  [text1]
        img += [text2]
        img += [text3]
        X,Y = np.mgrid[left-2:left+bbox.x1+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_with_left(imgs,str_Ltext,lines,k,is_latex):
    text1,left = Ltext(str_Ltext)
    if is_latex:
        str2 = dmath(lines[k])
        str3 = dmath(lines[k+1])
    else:
        str2 = lines[k]
        str3 = lines[k+1]
    for i in range(21):
        img = [text1]
        alpha = max((10-i)/10,0)
        img += [ax.text(left,base+height/2+height*i/40,str2,
                        fontdict=fdic,usetex=is_latex,alpha=alpha)]
        img += [ax.text(left,base+height*i/40,str3,
                        fontdict=fdic,usetex=is_latex)]
        imgs.append(img)

#はじまりの部分の関数    
def load_integrals(imgs):
    for i in range(160):
        img = integrals("k","k","k","k","k")
        X,Y = np.mgrid[-2:32:delta,height/2:3*height/2:height/2]
        img += [appearing(i,X,Y)]
        X,Y = np.mgrid[-10:24:delta,0:height:height/2]
        img += [appearing(i,X,Y)]
        imgs.append(img)
        alpha = max(min((i-110)/20,1),0)
        img += [ax.text(width/2,base-height/2,"4つに分けて、バシバシ積分していきます!!",
                        fontdict=fdic,clip_on=False,usetex=False,ha="center",
                        color="r",alpha=alpha)]

#各パート、どこを積分するのか表示する関数
def load_intro(imgs,n,str_intro):
    cols = ["0.5","0.5","0.5","0.5","0.5"]
    cols[n] = "r"
    for i in range(31):
        img = integrals(cols[1],cols[2],cols[3],cols[4],cols[0])
        alpha = max((i-10)/20,0)
        img += [ax.text(10,3,str_intro,color="r",alpha=alpha,
                        fontdict=fdic,usetex=False,ha="center",va="center")]
        imgs.append(img)
    lingering(imgs,30)

#置換積分の前置きを表示する関数
def load_before(imgs,lines_before):
    for i in range(140):
        img =  [ax.text(width/2,base+height/2,lines_before[0],
                        fontdict=fdic,usetex=False,ha="center")]
        X,Y = np.mgrid[-2:28:delta,height/2:3*height/2:height/2]
        img += [appearing(i,X,Y)]
        
        img +=  [ax.text(width/2,base,lines_before[1],
                        fontdict=fdic,usetex=False,ha="center")]
        X,Y = np.mgrid[-14:16:delta,0:height:height/2]
        img += [appearing(i,X,Y)]
        imgs.append(img)

#計算の部分の関数
def load_lines_with_left(imgs,str_Ltext,lines,is_latex=True):
    
    show_first_line_with_left(imgs,str_Ltext,lines,is_latex)
    
    for k in range(len(lines)-2):
        show_second_line_with_left(imgs,str_Ltext,lines,k,is_latex)
        go_next_line_with_left(imgs,str_Ltext,lines,k,is_latex)
        
    show_second_line_with_left(imgs,str_Ltext,lines,len(lines)-2,is_latex)
    lingering(imgs,30)

#結びの部分の関数
def load_answers(imgs):
    for i in range(200):
        img = [ax.text(0,base+height,dmath(str_int0),
                       fontdict=fdic,clip_on=False)]
        img += [ax.text(0,base+height/2,dmath(lines5[0]),fontdict=fdic)]
        img += [ax.text(0,base,dmath(lines5[1]),fontdict=fdic)]
        X,Y = np.mgrid[-2:40:delta,height/2:3*height/2:height/2]
        img += [appearing(i,X,Y)]
        X,Y = np.mgrid[-14:28:delta,0:height:height/2]
        img += [appearing(i,X,Y)]
        imgs.append(img)
        alpha = max(min((i-100)/20,1),0)
        img += [ax.text(width/2,base-height/2,"おしまい! (*・ω・*)ゞ",
                        fontdict=fdic,clip_on=False,usetex=False,ha="center",
                        color="r",alpha=alpha)]

#コメントの部分の関数
def interlude(imgs,str_comment,frames,is_latex=False):
    if is_latex:
        str_comment = dmath(str_comment)
    for i in range(frames):
        interlude=ax.text(width/2,height/2,str_comment,
                          fontdict=fdic_wc,bbox=boxdic,usetex=is_latex)
        imgs.append([interlude])

#1文字ずつ出てくるコメント
def successive_interlude(imgs,str_comment):
    for i in range(len(str_comment)):
        interlude(imgs,str_comment[:i+1],2)
    lingering(imgs,10)
    
#震えるコメント   
def quivering_interlude(imgs,str_comment,frames):
    for i in range(frames):
        interlude=ax.text(width/2-0.1+0.2*(i%2),height/2,str_comment,
                          fontdict=fdic_wc,bbox=boxdic,usetex=False)
        imgs.append([interlude])

#上演   
imgs=[]
#はじまり
successive_interlude(imgs,"ツギノ")
successive_interlude(imgs,"テイセキブンヲ")
successive_interlude(imgs,"モトメヨ")
interlude(imgs,str_int0,40,is_latex=True)
quivering_interlude(imgs,"(((;゚Д゚))\n\nガクガクブルブル",40)
load_integrals(imgs)
#第1部
interlude(imgs,"I_1="+str_int1,20,is_latex=True)
load_intro(imgs,1,"これは\nカンタン")
load_lines_with_left(imgs,str_int1,lines1)
#第2部
interlude(imgs,"I_2="+str_int2,20,is_latex=True)
load_intro(imgs,2,"置換積分で\nいきます!")
load_before(imgs,before2)
load_lines_with_left(imgs,str_int2,lines2)
#第3部
interlude(imgs,"I_3="+str_int3,20,is_latex=True)
load_intro(imgs,3,"やれやれ\n置換積分か")
load_before(imgs,before2)
load_lines_with_left(imgs,str_int3,lines3)
#第4部
interlude(imgs,"I_4="+str_int4,20,is_latex=True)
load_intro(imgs,4,"置換積分は\nこりごりだ!")
load_before(imgs,before4)
load_lines_with_left(imgs,str_int4,lines4)
#結び
interlude(imgs,"まとめ",20)
load_answers(imgs)

mov=ani.ArtistAnimation(fig, imgs, 100)
plt.show()
解説になっているのか?甚だギモンな動画
「高校数学のエアポケット」に戻る