0:00 いつものようにヒーリングタイムを観ながら寝る。 都電荒川線の映像だと思うのだが、見覚えがない景色ばかり続くから私が真面目に探索しなかった早稲田側の絵だと思っている。

6:35 目が覚める。今日も天気が悪そうだ。しばらくしてから起床する。 朝飯は納豆とレーズンロール。食い終わって国民年金免除申請の郵送準備をする。今度は切手不要だからミスの恐れはない。

8:00 ワイドーショーの時間帯に突入。外出まで研究活動。 麻雀で同一色牌からなる門前手牌は(暗槓はないものとする)何通りあるかという問題の続きだ。 数学の形でいうと $n_i\;(i = 1, \dotsc, 9)$ を数牌 $i$ の枚数とする。このとき

\[\sum_{i = 1}^9 n_i = 13,\;0 \le n_i \le 4\]

を満たす $(n_1, \dotsc, n_9)$ の組み合わせを求めたい。

10:30 投函および区役所に書類を提出しにいったん外出する。隅田公園を通る。 区役所前のポストに年金のヤツを投函。区役所に入り福祉課の S 氏に近況報告および書類提出。 トイレを済ませて向島の部屋に戻る。

11:30 頭を冷やしたらさっきの組み合わせを書き出すコードが書けたようだ。 出力する。

num of cases: 32
Counter({1: 7, 2: 1, 4: 1})
Counter({1: 7, 3: 2})
Counter({1: 6, 2: 2, 3: 1})
Counter({1: 6, 3: 1, 4: 1})
Counter({1: 5, 2: 4})
Counter({1: 5, 2: 2, 4: 1})
Counter({1: 5, 3: 2, 2: 1})
Counter({1: 5, 4: 2})
Counter({1: 4, 2: 3, 3: 1})
Counter({1: 4, 2: 1, 3: 1, 4: 1})
Counter({1: 4, 3: 3})
Counter({2: 5, 1: 3})
Counter({1: 3, 2: 3, 4: 1})
Counter({1: 3, 2: 2, 3: 2})
Counter({1: 3, 4: 2, 2: 1})
Counter({1: 3, 3: 2, 4: 1})
Counter({2: 4, 1: 2, 3: 1})
Counter({1: 2, 2: 2, 3: 1, 4: 1})
Counter({3: 3, 1: 2, 2: 1})
Counter({1: 2, 4: 2, 3: 1})
Counter({2: 6, 1: 1})
Counter({2: 4, 1: 1, 4: 1})
Counter({2: 3, 3: 2, 1: 1})
Counter({2: 2, 4: 2, 1: 1})
Counter({3: 2, 1: 1, 2: 1, 4: 1})
Counter({3: 4, 1: 1})
Counter({4: 3, 1: 1})
Counter({2: 5, 3: 1})
Counter({2: 3, 3: 1, 4: 1})
Counter({3: 3, 2: 2})
Counter({4: 2, 2: 1, 3: 1})
Counter({3: 3, 4: 1})

例:Counter({3: 2, 1: 1, 2: 1, 4: 1}) というのは $3+3+1+2+4=13$ を意味する。 萬子だとすると、一萬から九萬の 9 種から 5 種を各項に対して割り当てる順列か。 $3+3$ の部分だけ重複を考慮する必要がある。perm(9, 5) // 2 = 7560 通り。 その他の場合に対する計算方法がこれを一般化することで得られる。 検算していないが perm(9, len(counter))counter.values() の各項の階乗で除算するようなものだろう。 しかしこの計算だけでテーブル探索作戦は無茶だと判断していいだろう。 この問題はこれで終わる。

外出。三省堂にちょっと寄って四ツ目通りの奥へ。

13:45 ビッグエー墨田業平店。193 円。

  • ハムマヨパン
  • ふっくらおむすび明太マヨ
  • ジャムパン

柳島児童遊園で水を汲んでから、ちょっと雨が降っているので団地の軒下で食う。 横川コミュニティー会館図書室に行く。新聞を読んでふたたびの確率統計を読む。正規分布。

雨が一時的にやんでいるのでハローワーク墨田へ移動。求人検索。 都内のオーケー各店が大量に店員を募集している。いいスーパーなので発展して欲しい。

タイトー F ステーションオリナス錦糸町店で 3 クレ遊ぶ。ビートマニアのみ。 ARENA 3 戦目で人間二名とマッチメイク。B クラスだと一回トップ獲れれば御の字か。 あとヒエヒエペンタ新筐体が故障しているのは残念だ。

17:35 カスミオリナス錦糸町店。336 円。

  • エビチリ&麻婆茄子丼

18:10 ビッグエー墨田業平店。169 円。

  • バナナ
  • レーズンロール (4)

18:30 向島の部屋に戻る。さっきから地味に蒸し暑い。 テレビだが、プリキュアと都知事選政見放送とニュースを同時に一つのモニターで視聴したいが無理か。

19:00 晩飯。バナナ 4 本は多い。しかし朝まで保たないだろう。半額だからと飛びついたのは甘かったか。

19:40 隅田公園に寄ってトイレで排尿を済ませてから電話ボックスへ。 昨日郵送した書類はいちおう応募先に着信しているらしい。メールで教えてくれている。 こちらから返事はできないのが失礼だが。これは Hotmail が融通が利かないせいにしたい。

20:00 大雨が降ってくる。傘をさして部屋に戻る。

21:00 風呂に入る。15 分で上がる。消灯時間までひたすら麻雀の練習。外は大雨。

寝る前に例によって MX テレビのヒーリングタイムにチャンネルを合わせる。 たぶん月が変わったからだと思うが、映像がいつものジオラマではなくなっている。 おまけに番組直後の MX テレビライオン(中野ブロードウェイの 4 階某店のシャッターのイラストみたいな生き物)のアニメーションも変化した。 先月の狐の嫁入りは傑作だったから惜しい。 あと、MX テレビライオンの意匠は WACCA のエリマキトカゲと着想が同じと思われる。 など、どうでもいいことを考えつつ寝る。

Programming Notes

数学的帰納法と相性がいい関数を定義する際に functools.lru_cache で decorate しておくといい。 引数に対応する戻り値を記憶することで、次回以降の処理は探索処理になる。

from collections import Counter
from functools import lru_cache
from itertools import product

@lru_cache(maxsize=7)
def count_menchin_cases(num):
    r"""Count the number of combinations :math:`(n_1, \dotsc, n_9)`, where
    :math:`\sum n_i = 13` and :math:`n_i \le 4`.

    >>> count_menchin_cases(0)
    [Counter({1: 1})]
    >>> count_menchin_cases(1)
    [Counter({1: 1})]
    >>> count_menchin_cases(2)
    [Counter({1: 2}), Counter({2: 1})]
    >>> count_menchin_cases(3)
    [Counter({1: 3}), Counter({1: 1, 2: 1}), Counter({3: 1})]
    """

    if num in (0, 1):
        return [Counter({1: 1}),]
    if num == 2:
        return [Counter({1: 2}), Counter({2: 1})]

    results = []
    last = num // 2 + 1
    for i in range(1, last):
        for lhs, rhs in product(count_menchin_cases(i), count_menchin_cases(num - i)):
            ...

    return results