-- coding: utf-8 --
""" M+4动态目标版状态机【大任务4 / 小任务M+4 / 跑100万步】
本版本改动:
- 大任务阈值 BIG_TARGET = 4
- 小任务动态目标 = M + 4
- M >= 0 时,目标值锁定为 4
- M < 0 时,目标值 = M + 4
- 运行步数 MAX_STEPS = 1_000_000
- 默认只输出汇总CSV,不输出100万行明细,防止电脑卡死
- 保留任务后首赢 M+1 规则
- 主赛道每一步结束后,统一用最新pos和最新M判断 pos<M """
import csv from pathlib import Path from datetime import datetime
============================================================
参数区
============================================================
MAX_STEPS = 10_000_000
100万步建议 False;如果一定要逐步明细,可改 True
EXPORT_DETAIL = False
PI_DIGITS_TXT_NAME = "pi_digits.txt"
SUMMARY_CSV_NAME = "千万.csv" DETAIL_CSV_NAME = "m_plus_4_detail_1000000.csv"
BIG_TARGET = 4
MAIN_MODE = "主赛道" WAIT_MODE = "等待模式"
def get_desktop_path(): desktop = Path.home() / "Desktop" if desktop.exists(): return desktop
chinese_desktop = Path.home() / "桌面"
if chinese_desktop.exists():
return chinese_desktop
return Path.cwd()
def load_pi_digits_from_desktop(): desktop_path = get_desktop_path() txt_path = desktop_path / PI_DIGITS_TXT_NAME
if not txt_path.exists():
raise FileNotFoundError(
f"未找到文件:{txt_path}\n"
f"请把 {PI_DIGITS_TXT_NAME} 放到桌面。"
)
with open(txt_path, "r", encoding="utf-8") as f:
raw_text = f.read()
digits = "".join(ch for ch in raw_text if ch.isdigit())
# 兼容 3.14159...
if digits.startswith("314159"):
digits = digits[1:]
if not digits.startswith("14159"):
raise ValueError(
"π数字文件内容错误:必须从小数点后 14159 开始。\n"
"正确示例:14159265358979323846..."
)
if len(digits) < MAX_STEPS:
raise ValueError(
f"π数字长度不足:当前只有 {len(digits)} 位,"
f"但需要运行 {MAX_STEPS} 步。"
)
return digits, txt_path
def is_odd_digit(digit): return digit in (1, 3, 5, 7, 9)
def calc_target(m_value): """ M+4动态目标值:
M < 0:
target = M + 4
M >= 0:
target = 4
"""
if m_value < 0:
return m_value + BIG_TARGET
return BIG_TARGET
def update_m_and_target(new_m): return new_m, calc_target(new_m)
def run_state_machine(pi_digits, max_steps, keep_detail=False): pos = 0 m_value = 0 target = calc_target(m_value)
mode = MAIN_MODE
red_count = 0
green_count = 0
big_task_count = 0
small_task_count = 0
odd_count = 0
even_count = 0
m_limit = 0
pos_limit = 0
after_task_wait_confirm = False
after_task_reason = ""
detail_rows = []
start_time = datetime.now()
print(f"开始运行:{start_time}")
print(f"运行步数:{max_steps:,}")
print(f"大任务阈值:{BIG_TARGET}")
print("动态目标:M < 0 时 target=M+4;M >= 0 时 target=4")
for step_index in range(1, max_steps + 1):
digit = ord(pi_digits[step_index - 1]) - 48
odd_flag = is_odd_digit(digit)
if odd_flag:
odd_count += 1
digit_type = "单"
else:
even_count += 1
digit_type = "双"
before_mode = mode
before_pos = pos
before_m = m_value
before_target = target
before_wait_confirm = after_task_wait_confirm
before_wait_reason = after_task_reason
marker = "-"
status = ""
operation_parts = []
step_win_loss = ""
step_allow_m_plus_one = False
m_plus_one_executed = False
wait_triggered_this_step = False
reached_small_task = False
reached_big_task = False
# ====================================================
# 1. 主赛道
# ====================================================
if mode == MAIN_MODE:
status = "主赛道运行"
if odd_flag:
step_win_loss = "赢:主赛道单数"
pos += 1
operation_parts.append("主赛道遇单,判定为赢,pos+1")
if after_task_wait_confirm:
step_allow_m_plus_one = True
m_value += 1
target = calc_target(m_value)
m_plus_one_executed = True
operation_parts.append(
f"任务后首赢:执行M=M+1,重算目标值;来源={after_task_reason}"
)
after_task_wait_confirm = False
after_task_reason = ""
else:
step_allow_m_plus_one = False
operation_parts.append("非任务后等待确认状态,本步不执行M+1")
else:
step_win_loss = "输:主赛道双数"
pos -= 1
operation_parts.append("主赛道遇双,判定为输,pos-1")
if after_task_wait_confirm:
step_allow_m_plus_one = False
operation_parts.append(
f"任务后遇双,判定为输:不允许M+1;来源={after_task_reason}"
)
after_task_wait_confirm = False
after_task_reason = ""
else:
step_allow_m_plus_one = False
operation_parts.append("非任务后等待确认状态,本步不执行M+1")
# 主赛道本步结束后,用最新pos和最新M判断 pos<M
if pos < m_value:
m_value, target = update_m_and_target(pos)
mode = WAIT_MODE
status = "触发等待模式"
wait_triggered_this_step = True
operation_parts.append(
"主赛道本步结束后:pos<M,M=pos,重算目标值,进入等待模式"
)
# ====================================================
# 2. 等待模式
# ====================================================
elif mode == WAIT_MODE:
status = "等待模式"
step_win_loss = "不判输赢:等待模式只统计红绿点"
step_allow_m_plus_one = False
if odd_flag:
green_count += 1
marker = "绿点"
mode = MAIN_MODE
after_task_wait_confirm = True
after_task_reason = "等待模式解锁"
operation_parts.append(
"等待模式遇单,绿点+1,pos不变,退出等待;进入任务后等待确认"
)
else:
red_count += 1
marker = "红点"
operation_parts.append(
"等待模式遇双,红点+1,pos不变,继续等待"
)
else:
raise RuntimeError(f"未知模式:{mode}")
# ====================================================
# 3. 实时状态:任务结算前
# ====================================================
realtime_mode = mode
realtime_pos = pos
realtime_m = m_value
realtime_target = target
if realtime_m < m_limit:
m_limit = realtime_m
if realtime_pos < pos_limit:
pos_limit = realtime_pos
# ====================================================
# 4. 大任务优先判定
# ====================================================
if pos == BIG_TARGET:
reached_big_task = True
big_task_count += 1
operation_parts.append(
"pos=4,完成大任务;本轮小任务自动终止;重置pos=0、M=0、target=4;进入任务后等待确认"
)
pos = 0
m_value = 0
target = calc_target(m_value)
mode = MAIN_MODE
after_task_wait_confirm = True
after_task_reason = "完成大任务"
else:
# ====================================================
# 5. 小任务判定
# ====================================================
if pos == target:
reached_small_task = True
small_task_count += 1
m_value, target = update_m_and_target(pos)
after_task_wait_confirm = True
after_task_reason = "完成小任务"
operation_parts.append(
"pos=当前动态目标值,完成小任务;不重置pos;M=当前pos,重算目标值;进入任务后等待确认"
)
settled_mode = mode
settled_pos = pos
settled_m = m_value
settled_target = target
if settled_pos > BIG_TARGET:
raise RuntimeError(
f"全局约束错误:第 {step_index} 步 pos={settled_pos} > {BIG_TARGET}"
)
if keep_detail:
detail_rows.append({
"步数": step_index,
"数字": digit,
"单双": digit_type,
"步前模式": before_mode,
"步前pos": before_pos,
"步前M": before_m,
"步前目标值": before_target,
"步前任务后等待确认": before_wait_confirm,
"步前等待确认来源": before_wait_reason,
"当前状态": status,
"本步输赢判定": step_win_loss,
"本步是否允许M+1": step_allow_m_plus_one,
"本步是否执行M+1": m_plus_one_executed,
"本步是否触发等待": wait_triggered_this_step,
"实时模式": realtime_mode,
"实时pos": realtime_pos,
"实时M": realtime_m,
"实时目标值": realtime_target,
"标记": marker,
"红点累计": red_count,
"绿点累计": green_count,
"是否完成小任务": reached_small_task,
"是否完成大任务": reached_big_task,
"小任务完成数": small_task_count,
"大任务完成数": big_task_count,
"结算后模式": settled_mode,
"结算后pos": settled_pos,
"结算后M": settled_m,
"结算后目标值": settled_target,
"结算后任务后等待确认": after_task_wait_confirm,
"结算后等待确认来源": after_task_reason,
"核心合规操作": ";".join(operation_parts),
})
if step_index % 100_000 == 0:
print(
f"已运行 {step_index:,} 步 | "
f"红点={red_count:,} | 绿点={green_count:,} | "
f"大任务={big_task_count:,} | 小任务={small_task_count:,} | "
f"pos={pos} | M={m_value} | target={target}"
)
red_green_diff = red_count - green_count
theoretical_red_green_diff = big_task_count * BIG_TARGET + pos
conservation_error = abs(red_green_diff - theoretical_red_green_diff)
odd_even_abs_diff = abs(odd_count - even_count)
conservation_pass = odd_even_abs_diff == conservation_error
end_time = datetime.now()
result = {
"max_steps": max_steps,
"odd_count": odd_count,
"even_count": even_count,
"odd_even_abs_diff": odd_even_abs_diff,
"red_count": red_count,
"green_count": green_count,
"red_green_diff": red_green_diff,
"small_task_count": small_task_count,
"big_task_count": big_task_count,
"final_pos": pos,
"final_m": m_value,
"final_target": target,
"final_mode": mode,
"final_after_task_wait_confirm": after_task_wait_confirm,
"final_after_task_reason": after_task_reason,
"m_limit": m_limit,
"pos_limit": pos_limit,
"theoretical_red_green_diff": theoretical_red_green_diff,
"conservation_error": conservation_error,
"conservation_pass": conservation_pass,
"start_time": str(start_time),
"end_time": str(end_time),
"elapsed_time": str(end_time - start_time),
"detail_rows": detail_rows,
}
return result
def export_summary_csv(result, output_path, pi_source_path): rows = [ ["项目", "数值"], ["π数字文件", str(pi_source_path)], ["运行开始时间", result["start_time"]], ["运行结束时间", result["end_time"]], ["运行耗时", result["elapsed_time"]],
["总步数", result["max_steps"]],
["大任务阈值", BIG_TARGET],
["动态目标规则", "M<0时 target=M+4;M>=0时 target=4"],
["单数数量", result["odd_count"]],
["双数数量", result["even_count"]],
["单双计数绝对差", result["odd_even_abs_diff"]],
["红点累计总数", result["red_count"]],
["绿点累计总数", result["green_count"]],
["红绿点差值=红点-绿点", result["red_green_diff"]],
["小任务完成总数", result["small_task_count"]],
["完成大任务总次数", result["big_task_count"]],
["最终pos", result["final_pos"]],
["最终M", result["final_m"]],
["最终动态目标值", result["final_target"]],
["最终模式", result["final_mode"]],
["最终任务后等待确认", result["final_after_task_wait_confirm"]],
["最终等待确认来源", result["final_after_task_reason"]],
["全程M极限最小值", result["m_limit"]],
["全程pos极限最小值", result["pos_limit"]],
["", ""],
["守恒总账校验", ""],
["理论红绿点差=完成大任务次数×4+最终pos", result["theoretical_red_green_diff"]],
["实际红绿点差=红点-绿点", result["red_green_diff"]],
["守恒误差", result["conservation_error"]],
["单双计数绝对差", result["odd_even_abs_diff"]],
["守恒公式是否通过", result["conservation_pass"]],
]
with open(output_path, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerows(rows)
def export_detail_csv(detail_rows, output_path): if not detail_rows: return
fieldnames = list(detail_rows[0].keys())
with open(output_path, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(detail_rows)
def print_summary(result, pi_source_path): print() print("========== M+4动态目标版统计结果 ==========") print(f"π数字文件: {pi_source_path}") print(f"总步数: {result['max_steps']:,}") print(f"运行耗时: {result['elapsed_time']}") print() print(f"单数数量: {result['odd_count']:,}") print(f"双数数量: {result['even_count']:,}") print(f"单双计数绝对差: {result['odd_even_abs_diff']:,}") print() print(f"红点累计总数: {result['red_count']:,}") print(f"绿点累计总数: {result['green_count']:,}") print(f"红绿点差值: {result['red_green_diff']:,}") print() print(f"小任务完成总数: {result['small_task_count']:,}") print(f"完成大任务总次数: {result['big_task_count']:,}") print() print(f"最终pos: {result['final_pos']}") print(f"最终M: {result['final_m']}") print(f"最终动态目标值: {result['final_target']}") print(f"最终模式: {result['final_mode']}") print(f"最终任务后等待确认: {result['final_after_task_wait_confirm']}") print(f"最终等待确认来源: {result['final_after_task_reason']}") print(f"全程M极限最小值: {result['m_limit']}") print(f"全程pos极限最小值: {result['pos_limit']}") print() print("========== 守恒总账校验 ==========") print(f"理论红绿点差: {result['theoretical_red_green_diff']}") print(f"实际红绿点差: {result['red_green_diff']}") print(f"守恒误差: {result['conservation_error']}") print(f"单双计数绝对差: {result['odd_even_abs_diff']}") print(f"守恒公式是否通过: {result['conservation_pass']}")
def main(): desktop_path = get_desktop_path()
summary_csv_path = desktop_path / SUMMARY_CSV_NAME
detail_csv_path = desktop_path / DETAIL_CSV_NAME
pi_digits, pi_source_path = load_pi_digits_from_desktop()
result = run_state_machine(
pi_digits=pi_digits,
max_steps=MAX_STEPS,
keep_detail=EXPORT_DETAIL,
)
export_summary_csv(result, summary_csv_path, pi_source_path)
if EXPORT_DETAIL:
export_detail_csv(result["detail_rows"], detail_csv_path)
print_summary(result, pi_source_path)
print()
print("========== CSV文件已生成 ==========")
print(f"汇总CSV: {summary_csv_path}")
if EXPORT_DETAIL:
print(f"明细CSV: {detail_csv_path}")
if name == "main": main()