"""#30 懐疑役★2つ(計算検証役 2026-09-30):(1) 2016・2017年度の調整の率を「調整の分」に数える分け方 (2) R3・R4 の賃金に合わせた分の大きさ。 T は decompose.py と同じ年表。各年の差 r−p を ①物価と使われた賃金の差 ②調整 ③据え置き に分け、積み上げは掛け算、順番6通り。""" import itertools from math import prod, log exec(open("decompose.py", encoding="utf-8").read().split("out = []")[0]) # T だけ読む(出力ファイルは書かない) def comps(t, who, alt): y, p, w, dn, de, rn, re_ = t; d = dn if who == 0 else de; r = rn if who == 0 else re_ if d == "据": a, b, c = 0.0, 0.0, r - p if alt >= 1 and y == "H28": b, c = -0.7, r - p + 0.7 # 物価0.8−調整0.7=0.1 が据え置き、差0.8のうち0.7が調整 else: base = w if d == "賃金" else p; a, b, c = base - p, -(base - r), 0.0 if alt >= 2 and y == "H29": b, c = -0.5, 0.5 # 決まっていた▲0.5を調整に数え、掛からなかった分を③で戻す return a, b, c def cum(x): return (prod(1 + v / 100 for v in x) - 1) * 100 def run(who, alt): P = [t[1] for t in T]; C = [comps(t, who, alt) for t in T]; pc = cum(P); rc = cum([p + sum(c) for p, c in zip(P, C)]) res = {} for order in itertools.permutations(range(3)): on = set(); prev = pc; ct = {} for k in order: on.add(k); cur = cum([p + sum(c[j] for j in on) for p, c in zip(P, C)]); ct[k] = prev - cur; prev = cur res[order] = ct L = [sum(log(1 + (p + sum(c[:k + 1])) / 100) - log(1 + (p + sum(c[:k])) / 100) for p, c in zip(P, C)) for k in range(3)] lg = [-(pc - rc) * 0 + (pc - rc) * (-L[k]) / (-sum(L)) for k in range(3)] return pc, rc, res, lg for alt, name in ((0, "今の分け方(実際に差し引いた調整だけ)"), (1, "案A:2016年度の▲0.7だけ調整に数える"), (2, "案B:2016年度▲0.7・2017年度▲0.5を調整に数える(2017年度は掛からなかった分を③に戻す)")): for who, lab in ((1, "既裁定(1956/4/1以前生まれ)"), (0, "新規(それより後)")): pc, rc, res, lg = run(who, alt) print(f"\n## {name}/{lab}:物価累積 {pc:.2f}・改定率累積 {rc:.2f}・差 {pc-rc:.2f}") for k, n in enumerate(("①賃金に合わせた分", "②調整", "③据え置き")): v = [r[k] for r in res.values()]; print(f" {n}:{min(v):.2f}〜{max(v):.2f}(平均 {sum(v)/6:.2f})/対数按分 {lg[k]:.2f}") mins = [min(r[k] for r in res.values()) for k in range(3)]; maxs = [max(r[k] for r in res.values()) for k in range(3)] print(" 順位が6通りすべてで ①>②?", all(r[0] > r[1] for r in res.values()), "/②>①?", all(r[1] > r[0] for r in res.values()), "/6通り中 ①>② の数", sum(r[0] > r[1] for r in res.values())) # (2) R3・R4 の①(今の分け方) print("\n## ★2 R3・R4 の賃金に合わせた分(今の分け方。既裁定・新規とも R3・R4 は同じ)") P = [t[1] for t in T]; C = [comps(t, 1, 0) for t in T]; pc = cum(P) for order in itertools.permutations(range(3)): pass idx = {t[0]: i for i, t in enumerate(T)} def stack(sel_years, who=1): # ①のうち選んだ年だけ外したときの積み上げの下がり(他の成分は残したまま/先に外す) P = [t[1] for t in T]; C = [comps(t, who, 0) for t in T] base = cum([p + sum(c) for p, c in zip(P, C)]) x = [p + sum(c) - (c[0] if T[i][0] in sel_years else 0) for i, (p, c) in enumerate(zip(P, C))] return cum(x) - base, base for ys in (["R3"], ["R4"], ["R3", "R4"]): d_last, _ = stack(ys) # ①を最後に足す=他が全部ある状態で①を外したときの差は「最後」の寄与 print(f" {'・'.join(ys)}の①を他の成分が全部ある状態で外す(順番で最後に足す場合):{-d_last:+.3f}") # 順番6通りでの R3+R4 の①の寄与(①全体のうち R3・R4 の分を、各順番で①の寄与を年別に比例配分せず、単独計算) for order in itertools.permutations(range(3)): on = [k for k in order[:order.index(0)]] PP = [t[1] for t in T]; CC = [comps(t, 1, 0) for t in T] def cc(ex): # 前に足されている成分 on のうえで ① を足す。ex=年集合なら ① をその年だけ入れる return cum([p + sum(c[j] for j in on) + (c[0] if T[i][0] in ex else 0) for i, (p, c) in enumerate(zip(PP, CC))]) b0 = cc(set()) out = [f"{y}: {b0 - cc({y}):.3f}" for y in ("R3", "R4")] + [f"R3+R4: {b0 - cc({'R3','R4'}):.3f}", f"①全体: {b0 - cc({t[0] for t in T}):.3f}"] print(" 順番", "→".join("①②③"[k] for k in order), "|", "/".join(out))