File size: 6,501 Bytes
df41178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
conjugate.py -- 動詞の活用を、規則で作る

  「移す」から「移して」「移した」「移しといて」…を、
  ひとつずつ書き並べるのではなく、国語で習う活用表から自動で作る。

  なぜ規則にしたか
  ────────────────
  はじめは外のAIに「述語を225個ならべて」と頼んだ。
  返ってきたのは52個で、しかも「寄せられるように」のような
  命令にならない形が混ざっていた。

  日本語の活用は規則で決まっている。
  規則で作れば、抜けもなく、間違いもなく、ただでいくらでも作れる。

  五段・一段・サ変の3つだけ扱う。頼みごとに使う動詞は、ほぼこれで足りる。

  五段活用の音の変化(学校で習う「行段」の表):
      書く → 書か 書き 書く 書け 書こ    / て形は 書いて
      移す → 移さ 移し 移す 移せ 移そ    / て形は 移して
      運ぶ → 運ば 運び 運ぶ 運べ 運ぼ    / て形は 運んで
"""

# 五段活用。語尾の1文字 → (連用形の音, て形, た形)
GODAN = {
    "う": ("い", "って", "った"),
    "つ": ("ち", "って", "った"),
    "る": ("り", "って", "った"),
    "む": ("み", "んで", "んだ"),
    "ぶ": ("び", "んで", "んだ"),
    "ぬ": ("に", "んで", "んだ"),
    "く": ("き", "いて", "いた"),
    "ぐ": ("ぎ", "いで", "いだ"),
    "す": ("し", "して", "した"),
}
# 五段の未然形(〜ない/〜せる の前)
GODAN_A = {"う": "わ", "つ": "た", "る": "ら", "む": "ま", "ぶ": "ば",
           "ぬ": "な", "く": "か", "ぐ": "が", "す": "さ"}
# 五段の命令形
GODAN_E = {"う": "え", "つ": "て", "る": "れ", "む": "め", "ぶ": "べ",
           "ぬ": "ね", "く": "け", "ぐ": "げ", "す": "せ"}

# 「て」の後に付く、頼みごとの言い方
TE_TAILS = [
    "", "ください", "くれ", "くれる", "ほしい", "ほしいな", "もらえる",
    "もらえます", "おいて", "おいてね", "ね", "よ", "な",
]
# 連用形の後に付く言い方
RENYOU_TAILS = ["たい", "ます", "ましょう", "なさい"]


def _split(verb):
    """動詞を (語幹, 種類) に分ける。

    種類は "五段" / "一段" / "サ変" / None
    """
    if verb.endswith("する"):
        return verb[:-2], "サ変"
    if len(verb) >= 2 and verb[-1] == "る":
        # 「見る・食べる」のような一段は、直前が「い段・え段」
        prev = verb[-2]
        if _is_i_or_e(prev):
            return verb[:-1], "一段"
        return verb[:-1], "五段"
    if verb and verb[-1] in GODAN:
        return verb[:-1], "五段"
    return verb, None


_I_ROW = set("いきしちにひみりぎじびぴ")
_E_ROW = set("えけせてねへめれげぜべぺ")


def _is_i_or_e(ch):
    return ch in _I_ROW or ch in _E_ROW


def forms(verb):
    """ひとつの動詞から、頼みごとに使われる言い方を全部作る"""
    stem, kind = _split(verb)
    out = set()

    if kind == "サ変":
        te, ta, ren = stem + "して", stem + "した", stem + "し"
        base = [verb, stem + "しろ", stem + "せよ", stem + "させて",
                stem + "させといて", stem + "しといて"]
    elif kind == "一段":
        te, ta, ren = stem + "て", stem + "た", stem
        base = [verb, stem + "ろ", stem + "よ", stem + "させて",
                stem + "させといて", stem + "といて"]
    elif kind == "五段":
        last = verb[-1]
        ren = stem + GODAN[last][0]
        te = stem + GODAN[last][1]
        ta = stem + GODAN[last][2]
        base = [verb, stem + GODAN_E[last],
                stem + GODAN_A[last] + "せて",
                stem + GODAN_A[last] + "せといて",
                te[:-1] + "といて" if te.endswith("て") else te]
    else:
        return {verb}

    out.update(b for b in base if b)
    for t in TE_TAILS:
        out.add(te + t)
    for t in RENYOU_TAILS:
        out.add(ren + t)
    # 「〜とく」の縮約(移しておく → 移しとく)
    out.add(te[:-1] + "とく" if te.endswith("て") else te)
    return {w for w in out if 2 <= len(w) <= 12}


# ------------------------------------------------------------------
# 動作ごとの、もとになる動詞
#   ここだけ人が選ぶ。あとの活用は機械が作る
# ------------------------------------------------------------------
BASE_VERBS = {
    "移動": ["移す", "移動する", "動かす", "まとめる", "集める", "寄せる",
             "入れる", "しまう", "片付ける", "整理する", "放り込む",
             "分ける", "仕分ける", "送る", "持っていく"],
    "数える": ["数える", "カウントする", "調べる"],
    "一覧": ["見せる", "並べる", "listする", "出す", "教える", "表示する"],
    "作成": ["作る", "作成する", "用意する", "新規作成する", "こしらえる"],
    "ごみばこ": ["捨てる", "消す", "削除する", "始末する", "処分する",
                 "ゴミ箱に入れる"],
    "改名": ["改名する", "リネームする", "名前を変える", "つけ直す"],
    "重複": ["重複する", "かぶる", "だぶる"],
    "大きさ": ["合計する"],
    "もぐる": ["もぐる", "潜る"],
    "HTML": ["HTML化する", "ページにする"],
}


def build():
    """全部の動作について、述語カードを作る。

    戻り値: {述語: 動作}
    """
    out = {}
    for act, verbs in BASE_VERBS.items():
        for v in verbs:
            for f in forms(v):
                # 先に入った動作を優先する(早い者勝ちで衝突を避ける)
                out.setdefault(f, act)
    return out


if __name__ == "__main__":
    import sys, json
    if len(sys.argv) > 1:
        for v in sys.argv[1:]:
            print(f"\n{v}  →  " + " / ".join(sorted(forms(v))))
    else:
        t = build()
        from collections import Counter
        c = Counter(t.values())
        print(f"できた述語: {len(t)} 個")
        for act, n in c.most_common():
            print(f"  {act:<8} {n:>4} 個")
        print("\n見本(移動):")
        print("  " + " / ".join(sorted(k for k, v in t.items()
                                       if v == "移動")[:24]))