漢字プリント 数学プリント
問題文
以下の問に答えよ。
  1. 和が $30$ になる2つの自然数からなる順列の総数を求めよ。
  2. 和が $30$ になる3つの自然数からなる順列の総数を求めよ。
  3. 和が $30$ になる3つの自然数からなる組合せの総数を求めよ。
(2020 神戸大学 理系第3問 文系第3問)
  1. $29$ 通り
  2. $406$ 通り
  3. $75$ 通り
※ この答えは学校側が公表したものではありません。個人が作成した非公式の答えです。
コード
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import matplotlib.gridspec as gridspec
from matplotlib.patches import PathPatch
from matplotlib.textpath import TextPath
from matplotlib.font_manager import FontProperties

#紙の準備
fig = plt.figure()
fig.suptitle("2020神戸大数学 理系第3問 文系第3問",
             color="0.5",ha="right",x=0.95,y=0.95,zorder=-1)
fig.subplots_adjust(left=0.04,right=0.96,top=0.8,bottom=0.1,wspace=1.0,hspace=0.0)
gs = gridspec.GridSpec(2,10)
ax0 = fig.add_subplot(gs[0,:])
ax0.set_xlim(0,800)
ax0.set_ylim(0,220)
ax0.set_aspect("equal")
ax0.axis("off")

#フォント辞書たち
counterdic={
"clip_on" : True,
"fontsize" : 18,
"fontfamily" : "fantasy",
"verticalalignment" : "center",
"horizontalalignment" : "center"
}
commentdic={
"ha" : "center",
"va" : "center",
"size" : 20,
"color" : "white",
"zorder" : 10,
"fontfamily": "Meiryo",
"linespacing" : 2,
}
commentbgdic={
"facecolor" : "black",
"pad" : 300,
}

#減らず口たち
msg1 = "足して30になる\n3つの数の組合せは?"
msg2 = "(答)\n75通り"
msg3 = "お魚の骨をとるより\nメンドくさかったです\n┐(´д`)┌"
comment = fig.text(0.5,0.5,msg1,
                   fontdict=commentdic,bbox=commentbgdic)

#お気に入りのイージング関数
def easing(x):
    if x<0.5:
        return 2*x**2
    else:
        return 1-(-2*x+2)**2/2

#文字を刻む
def add_text(x,y,text):
    if type(text)==int:
        text = "{:>2}".format(text)
    fp = FontProperties(family="fantasy")
    path  = TextPath((x,y),text,prop=fp)
    patch = PathPatch(path,color="k")
    ax0.add_patch(patch)

#足し算を刻む
def add_case(box_x,box_y,a,b,c):
    add_text(box_x,   box_y,a)
    add_text(box_x+16,box_y,"+")
    add_text(box_x+24,box_y,b)
    add_text(box_x+40,box_y,"+")
    add_text(box_x+48,box_y,c)

#最初の数に注目して場合分けし、全通りを刻む
for a in range(1,11):
    exec("ax{}=fig.add_subplot(gs[1,{}])".format(a,a-1))
    exec("ax{}.set_title(str(a)+\" ―\",fontfamily=\"fantasy\",color=\"0.5\")".format(a))
    exec("ax{}.set_xlim( 0,100)".format(a))
    exec("ax{}.set_ylim(-100,0)".format(a))
    exec("ax{}.xaxis.set_ticks([])".format(a))
    exec("ax{}.yaxis.set_ticks([])".format(a))
    exec("ax{}.set_aspect(\"equal\")".format(a))
    exec("ax{}.text(50,-60,str(0),fontdict=counterdic)".format(a))
    fig.text(0.04+0.92/38*(4*a-2),0.21,"個",color="0.5",ha="right")
    if a<10:
        fig.text(0.04+0.92/38*(4*a-1),0.27,"+",fontdict=counterdic)
    else:
        answer=fig.text(0.9,0.12,"= 75",fontdict=counterdic,alpha=0,size=24)
    for b in range(a,(30-a)//2+1):
        c = 30-a-b
        add_case(80*a-70,220-15*b,a,b,c)
        exec("ax{}.text(50,-60-(b-a+1)*100,str(b-a+1),fontdict=counterdic)".format(a))

#一つ一つにズームする
def zoom_in(a,t):
    k = t/30
    if k<=1:
        k = easing(k)
        left   = (80*a-80)*k
        top    = 220-15*(a-1)*k
        width  = 800-720*k
        height = width/80*22
        ax0.set_xlim(left,left+width)
        ax0.set_ylim(top-height,top)
        exec("ax{}.set_ylim(-100-100*k,-100*k)".format(a))

#個数を数えていく
def count(a,t):
    d = (30-a)//2-a
    k = t/(15*d+1)
    if k<=1:
        k = easing(k)
        down = (15*d+1)*k
        ax0.set_xlim(80*a-80,80*a)
        ax0.set_ylim(213-15*a-down,235-15*a-down)
        down = 100*d*k
        exec("ax{}.set_ylim(-200-down,-100-down)".format(a))

#全体に戻る
def zoom_out(a,t):
    k = t/30
    if k<=1:
        k = easing(k)
        left   = (80*a-80)*(1-k)
        top    = 220-(15*((30-a)//2-1)+1)*(1-k)
        width  = 800-720*(1-k)
        height = width/80*22
        ax0.set_xlim(left,left+width)
        ax0.set_ylim(top-height,top)

#それぞれの場合において
def section(a,t):
    n = (30-a)//2-a+1
    if t<45:
        zoom_in(a,t)
    elif t<45+15*n:
        count(a,t-40)
    else:
        zoom_out(a,t-45-15*n)

#場合ごとにフェーズを作る
phases = np.array([0])
for a in range(1,11):
    n = (30-a)//2-a+1
    t = phases[-1]+90+15*n
    phases = np.append(phases,t)

#動画本番
def update(i):
    if i<50:
        pass
    elif i==50:
        comment.set_visible(False)
    elif i<75:
        pass
    elif i<2100:
        k = i-75
        section_end = phases[phases>k][0]
        a = list(phases).index(section_end)
        t = k - phases[a-1]
        section(a,t)    
    elif i<2150:
        k = i-2100
        alpha = max(min(k/25,1),0)
        alpha = easing(alpha)
        answer.set_alpha(alpha)
    elif i==2150:
        comment.set_text(msg2)
        comment.set_visible(True)
    elif i==2200:
        comment.set_text(msg3)

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