File size: 3,471 Bytes
7391a59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5a6f7bc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import gradio as gr
import numpy as np

try:
    # demo close
    demo.close()
except:
    pass

import gradio as gr
import numpy as np

# --- LaTeX形式で行列を表現 ---
def matrix_to_latex(M, name="A"):
    rows = [" & ".join(map(lambda x: f"{x:.1f}", row)) for row in M]
    body = " \\\\ ".join(rows)
    return f"{name} = \\begin{{bmatrix}} {body} \\end{{bmatrix}}"

# --- ランダム行列生成 ---
def random_matrix(rows, cols, min_val, max_val, step):
    values = np.arange(min_val, max_val + step / 2, step)
    return np.random.choice(values, size=(rows, cols))

# --- 問題生成 ---
def generate_problem(rows_A, cols_A, cols_B, min_val, max_val, step):
    rows_B = cols_A  # 行列積が可能なように調整
    A = random_matrix(int(rows_A), int(cols_A), min_val, max_val, step)
    B = random_matrix(int(rows_B), int(cols_B), min_val, max_val, step)

    md = (
        "### 以下の行列の積を求めよ:\n\n"
        + "$$ " + matrix_to_latex(A, "A") + " $$\n\n"
        + "$$ " + matrix_to_latex(B, "B") + " $$\n\n"
        + "求めるもの:$$ A \\times B $$"
    )
    # 新しい問題と一緒に解答欄を空にリセット
    return (A.tolist(), B.tolist(), md, "")

# --- 解答生成 ---
def show_answer(A, B):
    A = np.array(A); B = np.array(B)
    C = A @ B

    steps = []
    for i in range(C.shape[0]):
        for j in range(C.shape[1]):
            terms = [f"{A[i,k]:.1f}\\times{B[k,j]:.1f}" for k in range(A.shape[1])]
            steps.append(f"$c_{{{i+1}{j+1}}} = " + " + ".join(terms) + f" = {C[i,j]:.1f}$")

    md = (
        "### 【解答】\n\n"
        + "$$ " + matrix_to_latex(C, "C") + " $$\n\n"
        + "### 【計算手順】\n\n"
        + "\n\n".join(steps)
    )
    return md

# --- Gradio UI設定 ---
latex_delims = [
    {"left": "$$", "right": "$$", "display": True},
    {"left": "$", "right": "$", "display": False},
]

with gr.Blocks(title="行列積ランダム出題") as demo:
    gr.Markdown("## 🎲 ランダム行列積クイズ\n"
                "行列サイズや数値範囲を調整して、練習用の問題を自動生成できます。")

    with gr.Accordion("⚙️ パラメータ設定", open=False):
        with gr.Row():
            rows_A = gr.Slider(2, 4, value=3, step=1, label="Aの行数")
            cols_A = gr.Slider(2, 4, value=3, step=1, label="Aの列数(=Bの行数)")
            cols_B = gr.Slider(2, 4, value=3, step=1, label="Bの列数")
        with gr.Row():
            min_val = gr.Number(value=-5.0, label="最小値(例:-5)")
            max_val = gr.Number(value=5.0, label="最大値(例:5)")
            step_val = gr.Number(value=0.5, label="刻み幅(例:0.5)")

    A_state = gr.State()
    B_state = gr.State()

    problem_md = gr.Markdown("", latex_delimiters=latex_delims, label="問題")
    answer_md  = gr.Markdown("", latex_delimiters=latex_delims, label="解答")

    with gr.Row():
        gen_btn = gr.Button("🔄 問題を再作成", variant="primary")
        ans_btn = gr.Button("💡 解答提示", variant="secondary")

    # 新しい問題作成時に、解答欄もクリア
    gen_btn.click(
        fn=generate_problem,
        inputs=[rows_A, cols_A, cols_B, min_val, max_val, step_val],
        outputs=[A_state, B_state, problem_md, answer_md]
    )

    ans_btn.click(
        fn=show_answer,
        inputs=[A_state, B_state],
        outputs=answer_md
    )

demo.launch()