漢字プリント 数学プリント
問題文
  1. $0 \lt x \lt a$ を満たす実数 $x,a$ に対し、次を示せ。 $$\frac{2x}{a} \lt \int_{a-x}^{a+x}\frac{1}{t}\,dt \lt x\left(\frac{1}{a+x}+\frac{1}{a-x}\right)$$
  2. (1) を利用して、次を示せ。 $$0.68 \lt \log2 \lt 0.71$$ ただし、 $\log2$ は $2$ の自然対数とする。
(2007 東京大学 理系第6問)
コード
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import matplotlib.patches as patches
import matplotlib.gridspec as gridspec
from matplotlib.colors import ListedColormap

#色の準備
col_L = "dodgerblue"
col_R = "coral"

#紙の準備
fig = plt.figure()
fig.suptitle("2007東大数学 理系第6問",
             color="0.5",ha="right",x=0.96,y=0.96)
fig.subplots_adjust(left=0.0,right=1.0,bottom=0.05,top=1.0)
gs = gridspec.GridSpec(4,30,height_ratios=[5,1,1,1],wspace=0.0,hspace=0.0)
ax1d = fig.add_subplot(gs[2:, 1:10])
ax2d = fig.add_subplot(gs[1:,12:17])
ax3d = fig.add_subplot(gs[2:,19:30])
ax2u = fig.add_subplot(gs[:1, 2:10])
ax4u = fig.add_subplot(gs[:1,11:19])
ax6u = fig.add_subplot(gs[:1,20:28])

#数式スペースの準備
for ax,width,height in zip([ax1d,ax2d,ax3d],[9,5,11],[4,6,4]):
    ax.set_xlim(0,width)
    ax.set_ylim(-height,0)
    ax.axis("off")

#グラフスペースの準備
areadic = dict(fc="none",ec="0.4",hatch="....")
memoridic = dict(color="0.3",size=8,ha="center",va="center")
wbgs = []
for ax in [ax2u,ax4u,ax6u]:
    ax.set_xlim(0.75,2.25)
    ax.set_ylim(-0.4,1.2)
    ax.set_aspect("equal")
    ax.axes.xaxis.set_visible(False)
    ax.axes.yaxis.set_visible(False)
    ax.spines["top"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["bottom"].set_color("0.5")
    ax.spines["bottom"].set_linewidth(0.7)
    ax.spines["bottom"].set_position(("data",0))
    ax.plot(1,0,">",color="0.5",markersize=4,transform=ax.get_yaxis_transform(),clip_on=False)
    xw = np.linspace(0.75,2.25)
    ax.plot(xw,1/xw,color="0.5",lw=0.7)
    xs = np.linspace(1,2)
    ax.text(1,-0.1,"$1$",**memoridic)
    ax.text(2,-0.1,"$2$",**memoridic)
    if ax == ax4u:
        area = ax.fill_between(xs,1/xs,0,**areadic,zorder=100,alpha=0)
        ax.text(1.4,0.8,"$y=\\dfrac{1}{x}$",color="0.3")
    else:
        ax.fill_between(xs,1/xs,0,**areadic)
        ax.text(1.5,-0.1,"$\\frac{3}{2}$",**memoridic)
        ax.set_visible(False)
    wbg = patches.Rectangle((0.5,-3),2.2,4.3,fc="w",clip_on=False,zorder=90,alpha=0)
    wbgs.append(wbg)
    ax.add_patch(wbg)

#動かせる図形たちを描きます
wakudic = dict(fc="none",hatch="////",linewidth=1.5,zorder=100,alpha=0)
kagedic = dict(clip_on=False,alpha=0)
vL1  = [(1,0),(1.5,0),(1.5,4/5-4/25),(1,4/5+4/25)]
vL2  = [(1.5,0),(2,0),(2,4/7-4/49),(1.5,4/7+4/49)]
vL1a = [(1,0),(1.5,0),(1.5,4/5-4/25),(1.25,4/5),(1,4/5)]
vL1b = [(1.25,4/5),(1,4/5),(1,4/5+4/25)]
vL2a = [(1.5,0),(2,0),(2,4/7-4/49),(1.75,4/7),(1.5,4/7)]
vL2b = [(1.75,4/7),(1.5,4/7),(1.5,4/7+4/49)]
L1w = patches.Polygon(vL1,**wakudic)
L2w = patches.Polygon(vL2,**wakudic)
L1a = patches.Polygon(vL1a,**kagedic)
L1b = patches.Polygon(vL1b,**kagedic)
L2a = patches.Polygon(vL2a,**kagedic)
L2b = patches.Polygon(vL2b,**kagedic)
for L in [L1w,L2w]:
    L.set_edgecolor(col_L)
    ax2u.add_patch(L)
for L in [L1a,L1b,L2a,L2b]:
    L.set_facecolor(col_L)
    ax2u.add_patch(L)
vR1 = [(1,0),(1.5,0),(1.5,2/3),(1,1)]
vR2 = [(1.5,0),(2,0),(2,1/2),(1.5,2/3)]
R1w = patches.Polygon(vR1,**wakudic)
R2w = patches.Polygon(vR2,**wakudic)
R1k = patches.Polygon(vR1,**kagedic)
R2k = patches.Polygon(vR2,**kagedic)
for R in [R1w,R2w]:
    R.set_edgecolor(col_R)
    ax6u.add_patch(R)
for R in [R1k,R2k]:
    R.set_facecolor(col_R)
    ax6u.add_patch(R)

#長さ表記を準備
pdic = dict(color="0.6",linewidth=1,zorder=-10,clip_on=False,alpha=0)
tdic = dict(color="0.3",ha="center",va="center",alpha=0)
Rdic = dict(fc="w",clip_on=False,visible=False,zorder=-10)
class Length:
    def __init__(self,ax):
        self.ax = ax
        self.objs = []
        self.boxs = []
        
    def hlen(self,edge1,edge2,position,latex):
        x = np.linspace(edge1,edge2)
        y = 2*(x-edge1)*(x-edge2)+position
        p,= self.ax.plot(x,y,**pdic)
        txt = self.ax.text((edge1+edge2)/2,position-0.12,"$"+latex+"$",**tdic)
        self.objs += [p,txt]
        pad = patches.Rectangle((((edge1+edge2)/2)-0.07,position-0.21),0.15,0.2,**Rdic)
        self.ax.add_patch(pad)
        self.boxs += [pad]
        
    def vlen(self,edge1,edge2,position,latex,LR):
        x = np.linspace(edge1,edge2)
        y = -LR*0.48*(x-edge1)*(x-edge2)/(edge2-edge1)**2+position
        p,= self.ax.plot(y,x,**pdic)
        txt = self.ax.text(position+LR*0.12,(edge1+edge2)/2,"$"+latex+"$",**tdic)
        self.objs += [p,txt]
        pad = patches.Rectangle((position+LR*0.12-0.08,(edge1+edge2)/2-0.12),0.16,0.24,**Rdic)
        self.ax.add_patch(pad)
        self.boxs += [pad]

#長さ表記を埋め込んでいきます
Llen = Length(ax2u)
Llen.hlen(0.8,1.3,-1.1,"\\frac{1}{2}")
Llen.hlen(1.7,2.2,-1.1,"\\frac{1}{2}")
Llen.vlen(-1.1,4/5-1.1,1.05,"\\frac{4}{5}",-1)
Llen.vlen(-1.1,4/7-1.1,1.95,"\\frac{4}{7}",-1)
Llen.objs += ax2u.plot([1.05,1.05],[-1.1,4/5-1.1],linestyle="--",**pdic)
Llen.objs += ax2u.plot([1.95,1.95],[-1.1,4/7-1.1],linestyle="--",**pdic)
Rlen = Length(ax6u)
Rlen.hlen(0.8,1.3,-1.1,"\\frac{1}{2}")
Rlen.hlen(1.7,2.2,-1.1,"\\frac{1}{2}")
Rlen.vlen(-1.1,-0.1,0.8,"1",-1)
Rlen.vlen(-1.1,2/3-1.1,1.3,"\\frac{2}{3}",+1)
Rlen.vlen(-1.1,2/3-1.1,1.7,"\\frac{2}{3}",-1)
Rlen.vlen(-1.1,1/2-1.1,2.2,"\\frac{1}{2}",+1)

#最後に現れる不等号たち
futogodic = dict(size=14,ha="center",va="baseline",zorder=110,alpha=0,
                 bbox=dict(fc="w",lw=0,boxstyle="round,pad=0.15",alpha=0))
futogos = []
futogos += [fig.text(0.05,0.65,"0.68<",color="0.3",**futogodic)]
futogos += [ax2u.text(1.5,0.20,"$\\dfrac{24}{35}$",color=col_L,**futogodic)]
futogos += [fig.text(0.35,0.65,"<",color="0.3",**futogodic)]
futogos += [ax4u.text(1.5,0.20,"$\\log{2}$",color="0.2",**futogodic)]
futogos += [fig.text(0.65,0.65,"<",color="0.3",**futogodic)]
futogos += [ax6u.text(1.5,0.20,"$\\dfrac{17}{24}$",color=col_R,**futogodic)]
futogos += [fig.text(0.95,0.65,"<0.71",color="0.3",**futogodic)]

#数式たち
linedic=dict(va="baseline",usetex=True,clip_on=True,fontsize=16)
lines1=[
r"=\frac{\,4\,}{\,5\,}\times\frac{\,1\,}{\,2\,}+\frac{\,4\,}{\,7\,}\times\frac{\,1\,}{\,2\,}",
r"=\frac{\,24\,}{\,35\,}\,>\,0.68",
]
lines2=[
r"=\int_{1}^{2}\!\frac{\,1\,}{\,x\,}\,dx",
r"=\Bigg[\log x\,\Bigg]_{1}^{2}",
r"=\;\log 2",
]
lines3=[
r"=\frac{1}{2}\!\times\!\!\left(\!1\!+\!\frac{2}{3}\!+\!\frac{2}{3}\!+\!\frac{1}{2}\right)\!\!\times\!\frac{1}{2}",
r"=\frac{\,17\,}{\,24\,}\,<\,0.71",
]

#数式を書き込んでいきます
colors = [(1,1,1,alpha) for alpha in np.arange(0,11)/10]
cmap = ListedColormap(colors)
TXT = []
PCM = []
for ax,lines in zip([ax2d,ax3d,ax1d],[lines2,lines3,lines1]):
    for i,line in enumerate(lines):
        latex = "$\\displaystyle " + line + "$"
        txt = ax.text(0,-(i+1)*2+0.73,latex,**linedic)
        TXT.append(txt)
        X,Y = np.mgrid[-2:14:0.1,-(i+1)*2:-i*2+0.1:2]
        C = np.ones((len(X)-1,1))
        C[0] = 0
        pcm = ax.pcolormesh(X,Y,C,cmap=cmap,zorder=10)
        PCM.append(pcm)
      
#コメントたち
commentdic = dict(ha="center",va="center",size=20,color="white",
                  zorder=200,linespacing=2.4,fontfamily="Meiryo",
                  bbox=dict(color="black",pad=300))
phrases = []
phrases.append("""
今から
$0.68\\,<\\,\\log2\\,<\\,0.71$
をお見せします
""")
phrases.append("""
$\\log2$ は
常用対数じゃなくて
自然対数の方なので
気をつけてね
""")
phrases.append("""
以上
$0.68\\,<\\,\\log2\\,<\\,0.71$
でした!
""")
phrases.append("""
ちなみに
$\\log2\\,=\\,0.6931\\ldots$
だそうです
""")
phrases.append("""
もちろん
$2\\,<\\,e$ なので
$\\log2$ は
1より小さくなります
""")
phrases.append("""
おしまい
(*`・ω・)ゞ
""")

#コメントを埋め込んでいきます
comments = []
for i,phrase in enumerate(phrases):
    comment = fig.text(0.5,0.5,phrase,**commentdic)
    comments.append(comment)
    if i>0:
        comment.set_visible(False)
    
#お気に入りのイージング関数
def easing(x):
    if x<0.5:
        return 2*x**2
    else:
        return 1-(-2*x+2)**2/2

#図形を平行移動させる関数
def slider(a,P,verts,x,y):
    old_xy = np.array(verts)
    slider = np.tile([a*x,a*y],(len(verts),1))
    new_xy = old_xy + slider
    P.set_xy(new_xy)
    if a==1:
        verts.clear()
        verts.extend(new_xy)

#図形を回転移動させる関数
def rotate(a,P,verts,theta):
    old_xy = np.array(verts).T
    anchor = np.tile(verts[0],(len(verts),1)).T
    R = np.array([[np.cos(a*theta),-np.sin(a*theta)],
                  [np.sin(a*theta), np.cos(a*theta)]])
    new_xy = R @ (old_xy-anchor) + anchor
    P.set_xy(new_xy.T)
    if a==1:
        verts.clear()
        verts.extend(new_xy.T)

#数式が徐々に現れる関数
def appearing(i,pcm):
    C = np.ones(len(pcm.get_array()))
    C[:2*i+1] = 0
    C[2*i+1:2*i+20] = np.arange(0.05,1.00,0.05)
    pcm.set_array(C)

#セクションを判定する関数
def section(i):
    n = np.argmin(~(i<endings[1:]))
    k = i-endings[n]
    T = list(periods.values())[n]
    a = easing(k/(T-1))
    keys = list(periods.keys())
    key = keys[n]
    pre = keys[n-1]
    return k,a,key,pre

#台本の構成
periods = {"C1":50,"C2":50,
           "A1":30,"T1":40,"T2":40,"T3":50,
           "A2":30,"R1":30,"R2":30,"R3":30,"T4":70,"T5":70,
           "A3":30,"L1":30,"L2":30,"L3":30,"L4":30,"T6":60,"T7":70,
           "A4":60,"E1":40,
           "C3":50,"C4":50,"C5":50,"C6":30}
endings = np.cumsum(list(periods.values()))
endings = np.append(0,endings)

#上演
def update(i):
    k,a,key,pre = section(i)
    
    if "T" in key:
        appearing(k,PCM[int(key[1])-1])
    elif "A1" == key:
        area.set_alpha(a)
    elif "A2" == key:
        for R in [R1w,R2w]:
            R.set_alpha(a)
        for R in [R1k,R2k]: 
            R.set_alpha(0.5*a)
    elif "A3" == key:
        for L in [L1w,L2w]:
            L.set_alpha(a)
        for L in [L1a,L1b,L2a,L2b]:
            L.set_alpha(0.5*a)
    elif "A4" == key:
        for wbg in wbgs:
            wbg.set_alpha(a)
        for futogo in futogos:
            futogo.set_alpha(a)
            futogo.get_bbox_patch().set_alpha(a)
    elif "L1" == key:
        slider(a,L1a,vL1a,0,-1.1)
        slider(a,L1b,vL1b,0,-1.1)
        slider(a,L2a,vL2a,0,-1.1)
        slider(a,L2b,vL2b,0,-1.1)
    elif "L2"== key:
        slider(a,L1a,vL1a,-.2,0)
        slider(a,L1b,vL1b,-.2,0)
        slider(a,L2a,vL2a,0.2,0)
        slider(a,L2b,vL2b,0.2,0)
    elif "L3"== key:
        for obj in Llen.objs:
            obj.set_alpha(a)
    elif "L4"== key:
        rotate(a,L1b,vL1b,-np.pi)
        rotate(a,L2b,vL2b,-np.pi)
    elif "R1" == key:
        slider(a,R1k,vR1,0,-1.1)
        slider(a,R2k,vR2,0,-1.1)
    elif "R2"== key:
        slider(a,R1k,vR1,-.2,0)
        slider(a,R2k,vR2,0.2,0)
    elif "R3"== key:
        for obj in Rlen.objs:
            obj.set_alpha(a)
    
    if k==0:
        if "C" in key:
            comments[int(key[1])-1].set_visible(True)
        elif "A2"==key:
            ax6u.set_visible(True)
        elif "A3"==key:
            ax2u.set_visible(True)
        elif "L3"==key:
            for obj in Llen.boxs:
                obj.set_visible(True)
        elif "R3"==key:
            for obj in Rlen.boxs:
                obj.set_visible(True)
        
        if "C" in pre:
            comments[int(pre[1])-1].set_visible(False)

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