0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonとコピペと生成AIで学ぶ 名門の森

Last updated at Posted at 2025-07-17

はじめに

「名門の森」は、物理体系的理解と演習を重視した問題集です。本記事では、この「名門の森」をPythonと生成AI(ChatGPTなど)を活用しながら、より実践的・再現可能な方法で学習・再構築していくことを目的としています。

◆ 学習の進め方

学習の基本方針は次の通りです:

  1. Google Colab 上で Python コードを使いながら、数式やグラフ、計算結果をインタラクティブに確認する。ブラウザとGoogleアカウントがあれば利用でき、ノートブック形式で記録と再現が可能です。
  2. わからないところや式展開の途中などは、生成AI(例:ChatGPT)に式や質問を入力して補完する。途中式の導出、変数定義、定義の再確認などに活用します。
  3. 理解した内容や確認できた数式・コード・考察は、自分の言葉でプレーンテキストまたはMarkdown+コードセル付きのノート形式で整理する。これにより、検索・再利用・共有が容易になります。

問題1:放物運動

# ============================================================
# プログラム名:monkey_hunting_simulation.py
# Program Title: Monkey Hunting Simulation – Does the projectile hit?
# ============================================================

import numpy as np
import matplotlib.pyplot as plt

# ---------------------------------------------------------------
# ■ 問題(日本語)
# 地上の射手が、木の上にいるサルを狙って物体を角度θで発射する。
# 同時にサルは枝から落下(自由落下)を始める。
# 射手がサルの初期位置を正確に狙えば、サルに命中するかを確認せよ。
#
# ■ Problem (English)
# A projectile is launched at a monkey hanging from a tree.
# The monkey lets go and begins to fall at the same moment the projectile is fired.
# If the initial velocity vector is aimed exactly at the monkey’s initial position,
# will the projectile hit the monkey?
# ---------------------------------------------------------------

# -------------------------------
# PARAMETERS / パラメータ設定
# -------------------------------

g = 9.8             # gravitational acceleration [m/s^2] / 重力加速度
v0 = 20.0           # initial speed [m/s] / 発射初速度
a = 10.0            # horizontal distance to monkey [m] / 水平方向距離
b = 5.0             # vertical height of monkey [m] / 鉛直方向高さ

# Compute angle theta so that the initial velocity vector points to (a, b)
# θ = arctan(b / a)
theta = np.arctan2(b, a)

# Velocity components
v0x = v0 * np.cos(theta)
v0y = v0 * np.sin(theta)

# Time to impact (based on straight-line motion)
t_hit = np.sqrt(a**2 + b**2) / v0

# Time samples from 0 to t_hit
t = np.linspace(0, t_hit, 100)

# -------------------------------
# TRAJECTORIES / 軌道計算
# -------------------------------

# P's trajectory: projectile motion
x_p = v0x * t
y_p = v0y * t - 0.5 * g * t**2

# Q's trajectory: free fall from (a, b)
x_q = np.full_like(t, a)
y_q = b - 0.5 * g * t**2

# -------------------------------
# PLOTTING / プロット描画
# -------------------------------

plt.figure(figsize=(8, 6))
plt.plot(x_p, y_p, label='Projectile P', color='blue')
plt.plot(x_q, y_q, label='Falling monkey Q', color='red', linestyle='--')
plt.plot(a, 0, 'ko', label='Impact Point')  # 衝突点
plt.plot(0, 0, 'bo', label='Launch Point')
plt.plot(a, b, 'ro', label='Monkey Start Position')
plt.xlabel('Horizontal distance x [m]')
plt.ylabel('Vertical height y [m]')
plt.title('Monkey Hunting Simulation')
plt.grid(True)
plt.axis('equal')
plt.legend()
plt.tight_layout()
plt.show()

# -------------------------------
# RESULT / 結果表示
# -------------------------------

# Compute vertical difference at x = a
# t_hit is the time both reach same horizontal point
y_p_at_hit = v0y * t_hit - 0.5 * g * t_hit**2
y_q_at_hit = b - 0.5 * g * t_hit**2
diff = abs(y_p_at_hit - y_q_at_hit)

print("---- Simulation Result ----")
print(f"Time to impact: {t_hit:.3f} s")
print(f"Projectile y at impact: {y_p_at_hit:.3f} m")
print(f"Monkey y at impact:     {y_q_at_hit:.3f} m")
print(f"Vertical difference:     {diff:.5f} m")

if diff < 0.01:
    print("✅ HIT: The projectile hits the falling monkey.")
else:
    print("❌ MISS: The projectile misses the monkey.")

問題2:放物運動

import numpy as np
import pandas as pd

# Program Name: Projectile Motion Calculation Based on Meimon no Mori p.12
print("Program Name: Projectile Motion Calculation Based on Meimon no Mori p.12\n")

# 定数設定
g = 9.8               # 重力加速度 [m/s^2]
e = 0.8               # 反発係数
theta_deg = 45        # 発射角度 [度]
theta = np.radians(theta_deg)  # ラジアンに変換
v0 = 10.0             # 初速度 [m/s]
l = 5.0               # 壁までの距離 [m]

# 計算
# 最高点の高さ h1
h1 = (v0**2) * (np.sin(theta)**2) / (2 * g)

# 反射後の最高点の高さ h2
h2 = (e * v0 * np.sin(theta))**2 / (2 * g)

# AB間の時間 t2
t1 = l / (v0 * np.cos(theta))
t2 = 2 * v0 * np.sin(theta) / g

# BC = e * v0 * cosθ * (t2 - t1)
vx = v0 * np.cos(theta)
BC = e * vx * (t2 - t1)

# OB = e^2 * v0^2 * sin(2θ) / g
OB = (e**2) * v0**2 * np.sin(2 * theta) / g

# 合計距離 l = OB + BC
l_total = OB + BC

# 結果のデータフレーム作成
results = pd.DataFrame({
    "項目": [
        "初速度 v0 [m/s]",
        "発射角度 θ [deg]",
        "最高点の高さ h1 [m]",
        "反射後の高さ h2 [m]",
        "AB間の時間差 t2 - t1 [s]",
        "水平方向距離 BC [m]",
        "着地点 OB [m]",
        "合計距離 l = OB + BC [m]"
    ],
    "": [
        v0,
        theta_deg,
        round(h1, 3),
        round(h2, 3),
        round(t2 - t1, 3),
        round(BC, 3),
        round(OB, 3),
        round(l_total, 3)
    ]
})

# Google Colabで表示
results

問題3:放物運動

# ============================================================
# Program: reflection_projectile_theoretical_vs_simulation.py
# Purpose: 名門の森に基づく「斜方投射+多段反射」運動の可視化と理論比較
# ============================================================

import numpy as np
import matplotlib.pyplot as plt

# -----------------------------
# PARAMETERS / パラメータ設定
# -----------------------------
g = 9.8                   # gravity [m/s^2]
h = 2.0                   # initial height [m]
e = 0.8                   # coefficient of restitution
theta_deg = 45            # launch angle in degrees
theta = np.radians(theta_deg)

# -----------------------------
# Step 1: 初速度 v0 = sqrt(2gh)
# -----------------------------
v0 = np.sqrt(2 * g * h)

# -----------------------------
# Step 2: 速度成分
# -----------------------------
v0x = v0 * np.cos(theta)
v0y = v0 * np.sin(theta)

# -----------------------------
# Step 3: 時間と高さを各バウンドについて計算
# -----------------------------
n_bounce = 3  # バウンド回数
colors = ['blue', 'green', 'orange', 'purple']
x_all = []
y_all = []

x_last = 0
for i in range(n_bounce):
    # 各バウンドの速度
    vx_i = (e ** i) * v0x
    vy_i = (e ** i) * v0y
    t_flight = 2 * vy_i / g  # 滞空時間

    # 時間分割
    t = np.linspace(0, t_flight, 100)
    x = x_last + vx_i * t
    y = vy_i * t - 0.5 * g * t**2

    x_all.append(x)
    y_all.append(y)
    x_last = x[-1]  # 次の初期位置に

# -----------------------------
# Step 4: 理論値の計算
# -----------------------------
# T_inf = 2 * e * v0 * sinθ / (g * (1 - e))
T_inf = (2 * e * v0 * np.sin(theta)) / (g * (1 - e))

# OB_theory = (4 * e * h * sinθ) / (1 - e^2)
OB_theory = (4 * e * h * np.sin(theta)) / (1 - e**2)

# -----------------------------
# Step 5: プロット描画
# -----------------------------
plt.figure(figsize=(10, 5))
for i in range(n_bounce):
    plt.plot(x_all[i], y_all[i], label=f'Trajectory {i+1}', color=colors[i])

plt.axhline(0, color='gray', linestyle='--')
plt.title("Multiple Reflection Projectile ")
plt.xlabel("Horizontal distance x [m]")
plt.ylabel("Vertical height y [m]")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

# -----------------------------
# Step 6: 結果出力
# -----------------------------
print("===== Simulation Summary =====")
print(f"Initial speed v₀           = {v0:.3f} m/s")
print(f"Total flight time (T_inf)  = {T_inf:.3f} s")
print(f"Theoretical OB distance     = {OB_theory:.3f} m")
print(f"Simulated x_final           = {x_last:.3f} m")
print("===============================")


問題4:剛体の釣り合い


# ============================================================
# Program: moment_and_force_balance.py
# Purpose: Calculation and Visualization of Moment and Force Balance for a Rigid Body on an Inclined Plane Based on Meimon no Mori
# ============================================================

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# -----------------------------
# Parameters / パラメータ設定
# -----------------------------
g = 9.8           # gravity acceleration [m/s^2]
M = 1.0           # mass of the rod [kg], assumed for calculation
l = 1.0           # length unit [m], assumed for scaling
theta_deg = 53.13 # angle θ in degrees (approx. for sinθ=4/5, cosθ=3/5)
theta = np.radians(theta_deg)

# Trigonometric values from triangle ABC (3:4:5)
cos_theta = 3/5
sin_theta = 4/5

# -----------------------------
# Step 1: Moment about point B
# -----------------------------
# Mg * 5l * cosθ = R * 10l * sinθ
R = (M * g * 5 * l * cos_theta) / (10 * l * sin_theta)
R = (3/8) * M * g  # Simplified as per derivation

# -----------------------------
# Step 2: Vertical force balance
# -----------------------------
N = M * g

# -----------------------------
# Step 3: Horizontal force balance
# -----------------------------
F = R

# -----------------------------
# Step 4: Net reaction force at point B
# -----------------------------
net_force = np.sqrt(N**2 + F**2)
net_force_simplified = (np.sqrt(73) / 8) * M * g

# -----------------------------
# Step 5: Alternative moment about point A (verification)
# -----------------------------
# N * 10l * cosθ = Mg * 5l * cosθ + F * 10l * sinθ
moment_A_left = N * 10 * l * cos_theta
moment_A_right = M * g * 5 * l * cos_theta + F * 10 * l * sin_theta
moment_A_check = np.isclose(moment_A_left, moment_A_right)

# -----------------------------
# Step 6: DataFrame for results
# -----------------------------
results = pd.DataFrame({
    "項目 / Item": [
        "支持反力 R [N] / Support force R",
        "垂直抗力 N [N] / Normal force N",
        "静止摩擦力 F [N] / Friction force F",
        "合力の大きさ [N] / Net reaction force",
        "A点まわりのモーメント平衡 / Moment balance at A"
    ],
    "値 / Value": [
        round(R, 3),
        round(N, 3),
        round(F, 3),
        round(net_force, 3),
        "Satisfied" if moment_A_check else "Not satisfied"
    ]
})

# -----------------------------
# Step 7: Vector visualization with adjusted scale
# -----------------------------
plt.figure(figsize=(10, 6))

# Origin at point B (0,0)
origin = np.array([0, 0])

# Vectors for forces at point B
N_vector = np.array([0, N])  # Normal force (vertical)
F_vector = np.array([F, 0])  # Friction force (horizontal)
R_vector = np.array([-R * sin_theta, R * cos_theta])  # Support force at angle
net_force_vector = N_vector + F_vector  # Net reaction force at B

# Plot vectors with adjusted scale
scale = 20.0  # Adjusted scale (larger value = shorter arrows)
plt.quiver(*origin, *N_vector, color='blue', scale=scale, label='Normal force N', width=0.005, alpha=0.8)
plt.quiver(*origin, *F_vector, color='red', scale=scale, label='Friction force F', width=0.005, alpha=0.8)
plt.quiver(*origin, *R_vector, color='green', scale=scale, label='Support force R', width=0.005, alpha=0.8)
plt.quiver(*origin, *net_force_vector, color='purple', scale=scale, label='Net reaction force', width=0.005, alpha=0.8)

# Set axis limits based on maximum force magnitude
max_force = max(N, F, net_force, np.linalg.norm(R_vector)) * 1.2  # 20% margin
plt.xlim(-max_force, max_force)
plt.ylim(-max_force, max_force)

# Plot settings
plt.title("Force Vectors at Point B")
plt.xlabel("Horizontal Force [N]")
plt.ylabel("Vertical Force [N]")
plt.grid(True)
plt.legend()
plt.axis('equal')  # Equal scaling for x and y axes
plt.tight_layout()

# Show plot
plt.show()

# -----------------------------
# Step 8: Display results
# -----------------------------
print("===== Calculation Summary =====")
print(results.to_string(index=False))
print("===============================")

問題5:剛体の釣り合い

# ============================================================
# Program: sliding_vs_tipping_analysis.py
# Purpose: Sliding vs. Tipping condition analysis for rigid body on incline
# 名門の森の式に基づき、滑り条件・転倒条件を数式で比較
# ============================================================

import numpy as np
import pandas as pd

# -----------------------------
# Parameters / パラメータ設定
# -----------------------------
g = 9.8           # gravity [m/s^2]
M = 1.0           # mass [kg]
a = 0.5           # center of mass to base (horizontal) [m]
b = 1.0           # center of mass to base (vertical) [m]
mu = 0.6          # friction coefficient
theta_deg = 30    # incline angle [deg]
theta = np.radians(theta_deg)  # convert to radians

# -----------------------------
# Step 1: Sliding condition (摩擦による滑り)
# F1 = Mg (μ cosθ - sinθ)
F1 = M * g * (mu * np.cos(theta) - np.sin(theta))

# -----------------------------
# Step 2: Tipping condition (モーメントによる転倒)
# F2 = (Mg / 2b) * (a cosθ - b sinθ)
F2 = (M * g / (2 * b)) * (a * np.cos(theta) - b * np.sin(theta))

# -----------------------------
# Step 3: Comparison
# → F1 > F2 → tipping occurs first
# → F2 > F1 → sliding occurs first
if F1 > F2:
    mode = "Tipping occurs first (転倒が先)"
elif F2 > F1:
    mode = "Sliding occurs first (滑りが先)"
else:
    mode = "Simultaneous (同時に発生)"

# -----------------------------
# Output as table
# -----------------------------
result_data = {
    "Incline θ (deg)": theta_deg,
    "F1 (Sliding condition)": round(F1, 3),
    "F2 (Tipping condition)": round(F2, 3),
    "Result": mode
}

df = pd.DataFrame([result_data])
print("=== Sliding vs. Tipping Analysis ===")
print(df.to_string(index=False))

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?