問題文
次の定積分を求めよ。 $$\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()