DeepSeek辅助编写的计算数独可选数的python程序第3部分
·
就是增加了批处理
在第2个程序的基础上,增加功能函数,读入换行分隔的文本文件,输出行号、原文本、迭代后文本、原已知数、现已知数的csv文件,只给出新增的代码,以及调用的命令行,例如 sudofill.py input.txt ouput.csv
新增代码如下
import csv
import sys
def process_sudoku_line(board_str, line_num):
"""处理单个数独字符串,返回结果信息"""
if len(board_str) != 81:
return {
'line_num': line_num,
'original': board_str,
'final': 'ERROR: 长度不是81字符',
'initial_known': 0,
'final_known': 0,
'filled_count': 0
}
if not set(board_str).issubset(set('0123456789')):
return {
'line_num': line_num,
'original': board_str,
'final': 'ERROR: 包含非数字字符',
'initial_known': 0,
'final_known': 0,
'filled_count': 0
}
# 计算初始已知数
initial_known = 81 - board_str.count('0')
# 迭代求解
final_board, all_iterations = solve_iteratively_silent(board_str)
# 计算最终已知数
final_known = 81 - final_board.count('0')
return {
'line_num': line_num,
'original': board_str,
'final': final_board,
'initial_known': initial_known,
'final_known': final_known,
'filled_count': final_known - initial_known
}
def solve_iteratively_silent(initial_board):
"""静默版本的迭代求解,不打印过程,只返回结果"""
current_board = initial_board
while True:
# 计算候选数
candidates = find_candidates(current_board)
# 检查是否有唯一候选数可以填充
has_single_candidates = False
for r in range(9):
for c in range(9):
pos = r * 9 + c
if current_board[pos] == '0' and len(candidates[r][c]) == 1:
has_single_candidates = True
break
if has_single_candidates:
break
if not has_single_candidates:
break
# 填充唯一候选数
board_list = list(current_board)
changed = False
for r in range(9):
for c in range(9):
pos = r * 9 + c
if board_list[pos] == '0' and len(candidates[r][c]) == 1:
num = next(iter(candidates[r][c]))
board_list[pos] = str(num)
changed = True
if not changed:
break
new_board = "".join(board_list)
# 检查是否已经解决
if new_board.count('0') == 0:
current_board = new_board
break
# 更新当前数独
current_board = new_board
# 安全检查:最多迭代100次
# 这个值可以调整,但对于正常数独,100次足够了
return current_board, [] # 返回空迭代历史
def batch_process_file(input_file, output_file):
"""批量处理文件中的所有数独"""
print(f"处理文件: {input_file}")
print(f"输出到: {output_file}")
results = []
try:
with open(input_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
total_lines = len(lines)
print(f"读取到 {total_lines} 行")
for i, line in enumerate(lines, 1):
# 清理行:去除空白字符
board_str = line.strip()
if not board_str: # 跳过空行
continue
print(f"处理第 {i} 行: {board_str[:20]}...")
# 处理数独
result = process_sudoku_line(board_str, i)
results.append(result)
# 显示进度
print(f" 初始已知数: {result['initial_known']}, 最终已知数: {result['final_known']}, 填充数: {result['filled_count']}")
except FileNotFoundError:
print(f"错误: 找不到文件 {input_file}")
return
except Exception as e:
print(f"读取文件时出错: {e}")
return
# 写入CSV文件
try:
with open(output_file, 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['line_num', 'original', 'final', 'initial_known', 'final_known', 'filled_count']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for result in results:
writer.writerow(result)
print(f"\n成功处理 {len(results)} 个数独")
print(f"结果已保存到 {output_file}")
# 显示统计信息
if results:
total_filled = sum(r['filled_count'] for r in results)
avg_filled = total_filled / len(results) if len(results) > 0 else 0
print(f"\n统计信息:")
print(f" 总填充数: {total_filled}")
print(f" 平均每个数独填充数: {avg_filled:.2f}")
# 按填充数分组统计
fill_groups = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, '6+': 0}
for r in results:
filled = r['filled_count']
if filled < 0:
filled = 0 # 错误情况的处理
if filled <= 5:
fill_groups[filled] += 1
else:
fill_groups['6+'] += 1
print(f"\n填充数分布:")
for key in sorted(fill_groups.keys()):
count = fill_groups[key]
if count > 0:
print(f" 填充{key}个数字: {count}个数独")
except Exception as e:
print(f"写入CSV文件时出错: {e}")
def batch_main():
"""批量处理模式的主函数"""
print("数独批量处理工具")
print("=" * 50)
if len(sys.argv) != 3:
print("用法: python sudofill.py input.txt output.csv")
print("\n参数说明:")
print(" input.txt - 包含数独字符串的文本文件(每行一个81字符的数独)")
print(" output.csv - 输出CSV文件路径")
print("\n示例: python sudofill.py puzzles.txt results.csv")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
batch_process_file(input_file, output_file)
# 在main()函数中添加批量处理选项
def enhanced_main():
"""增强版主函数,支持命令行参数和交互模式"""
if len(sys.argv) == 3:
# 命令行参数模式
batch_main()
else:
# 交互模式(原main函数的内容)
print("数独唯一候选数迭代求解器")
print("=" * 50)
# ... 原main函数的其余代码保持不变 ...
# 这里需要将原main函数的内容复制过来
# 由于原main函数较长,这里只显示关键修改
print("\n提示:要批量处理文件,请使用命令行:")
print(" python sudofill.py input.txt output.csv")
# 调用原main函数逻辑(这里需要整合)
# 由于代码较长,建议将原main函数改名为interactive_main()
# 然后在这里调用
interactive_main()
def interactive_main():
"""交互模式主函数(原main函数重命名)"""
main()
# 修改if __name__ == "__main__": 部分
if __name__ == "__main__":
# 检查命令行参数
if len(sys.argv) == 3:
# 批量处理模式
batch_main()
elif len(sys.argv) == 1:
# 交互模式
interactive_main()
else:
print("用法:")
print(" 交互模式: python sudofill.py")
print(" 批量处理: python sudofill.py input.txt output.csv")
sys.exit(1)
使用说明:
将新增代码添加到原程序的末尾
确保原程序中的函数(如find_candidates、solve_iteratively、print_summary等)仍然可用
运行批量处理时,程序会显示处理进度和统计信息
CSV文件可以用Excel或其他电子表格软件打开查看
输出如下
C:\d\1230>python candnum3.py input10sudo.txt output10sudo.txt
数独批量处理工具
==================================================
处理文件: input10sudo.txt
输出到: output10sudo.txt
读取到 10 行
处理第 1 行: 10200506768479015075...
初始已知数: 50, 最终已知数: 81, 填充数: 31
处理第 2 行: 06540809209000178028...
初始已知数: 43, 最终已知数: 81, 填充数: 38
...
初始已知数: 44, 最终已知数: 81, 填充数: 37
处理第 10 行: 00013527007894035015...
初始已知数: 42, 最终已知数: 81, 填充数: 39
成功处理 10 个数独
结果已保存到 output10sudo.txt
统计信息:
总填充数: 348
平均每个数独填充数: 34.80
填充数分布:
写入CSV文件时出错: '<' not supported between instances of 'str' and 'int'
更多推荐
所有评论(0)