mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-19 12:58:04 +00:00
170 lines
5.5 KiB
Python
Executable file
170 lines
5.5 KiB
Python
Executable file
#!/usr/bin/python3.6
|
|
import itertools
|
|
from operator import mul
|
|
from functools import reduce
|
|
import sys
|
|
from time import time
|
|
from math import floor
|
|
|
|
def satisfies_r(s, row, r):
|
|
return satisfies_l(s, list(reversed(row)), r)
|
|
|
|
def satisfies_l(s, row, l):
|
|
if len(set(row)) < s:
|
|
return False
|
|
if l == 0:
|
|
return True
|
|
seen = 0
|
|
curr_max = 0
|
|
for entry in row:
|
|
if entry > curr_max:
|
|
curr_max = entry
|
|
seen += 1
|
|
if entry == s or seen > l:
|
|
break
|
|
return l == seen
|
|
|
|
def possible_rows(s, l, r):
|
|
p = []
|
|
for row in itertools.permutations(range(1, s + 1)):
|
|
if satisfies_l(s, row, l) and satisfies_r(s, row, r):
|
|
p.append(list(row))
|
|
return p
|
|
|
|
def format_time(s):
|
|
sinm = 60
|
|
sinh = 60 * sinm
|
|
sind = 24 * sinh
|
|
d = h = m = 0
|
|
r = s
|
|
if s > sind:
|
|
d = floor(r / sind)
|
|
r -= d * sind
|
|
if s > sinh:
|
|
h = floor(r / sinh)
|
|
r -= h * sinh
|
|
if s > sinm:
|
|
m = floor(r / sinm)
|
|
r -= m * sinm
|
|
return f'{d}:{h:02d}:{m:02d}:{r:02d}'
|
|
|
|
def print_time(done, total, s):
|
|
eta = format_time(int((total / done - 1) * s))
|
|
print(f'progress: {done} / {total} = {done * 100 / total:.2f}%, est. max. time left: {eta}')
|
|
|
|
def print_time_found(done, total, s):
|
|
dhms = format_time(int(s))
|
|
print(f'Solution found after searching {done} / {total} = {done * 100 / total:.2f}% in {dhms}')
|
|
|
|
def is_valid_solution(s, solution, t, b):
|
|
count = 0
|
|
for i in range(s):
|
|
c = [row[i] for row in solution]
|
|
if not (satisfies_l(s, c, t[i]) and satisfies_r(s, c, b[i])):
|
|
break
|
|
count += 1
|
|
return count == s
|
|
|
|
def solve(s, l, r, t, b, verbose,simple_output):
|
|
rows = [possible_rows(s, l[i], r[i]) for i in range(s)]
|
|
sol_count = 0
|
|
total = reduce(mul, [len(row) for row in rows], 1)
|
|
first_time = time()
|
|
prev_time = first_time
|
|
curr_time = first_time
|
|
start_freq = 10000
|
|
time_freq = start_freq
|
|
log = "" # 初始化日志变量
|
|
|
|
# 记录排列总数
|
|
log += f"现在通过笛卡尔积遍历的方式尝试所有可能的排列组合,总共有 {total} 种可能的排列组合需要尝试。\n"
|
|
if verbose > 0:
|
|
print(f'{total} possible solutions')
|
|
|
|
for solution in itertools.product(*rows):
|
|
sol_count += 1
|
|
|
|
if (simple_output and sol_count < 4) or not simple_output:
|
|
log += f"现在判断第 {sol_count} 个可能的排列组合:。\n" # 记录当前尝试的解
|
|
|
|
log += f"这是基于每行的可能排列组合生成的解。\n"
|
|
for i, row in enumerate(solution):
|
|
log += f" - 第 {i + 1} 行是从该行的所有可能排列中选出的一个。\n"
|
|
log += f" 当前这一行的所有可能排列是:{rows[i]}。\n"
|
|
log += f" 我们选择了排列 {row} 作为第 {i + 1} 行。\n"
|
|
log += f"逐行拼接这些排列,形成完整棋盘{solution}。\n"
|
|
if simple_output and (sol_count == 4):
|
|
log += f"...像这样判断下去。\n"
|
|
|
|
# 输出进度信息
|
|
if verbose > 0 and sol_count % time_freq == 0:
|
|
curr_time = time()
|
|
if curr_time >= prev_time + verbose:
|
|
if time_freq == start_freq:
|
|
time_freq = sol_count / 10
|
|
elapsed_time = curr_time - first_time
|
|
progress_info = f"已尝试 {sol_count} 个解,共计 {total} 个解。\n"
|
|
log += progress_info # 记录进度信息
|
|
print(progress_info)
|
|
prev_time = curr_time
|
|
|
|
# 检查当前解是否符合要求
|
|
if is_valid_solution(s, solution, t, b):
|
|
curr_time = time()
|
|
elapsed_time = curr_time - first_time
|
|
found_info = f"这样,就找到了一个符合要求的解,这是第 {sol_count} 个尝试。\n"
|
|
log += found_info
|
|
log += f"有效解为:{solution}。\n"
|
|
if verbose > 0:
|
|
print(found_info)
|
|
return solution, log # 返回解和日志
|
|
else:
|
|
if (simple_output and sol_count < 4) or not simple_output:
|
|
log += f"很遗憾,这样的组合并不满足规则,它不是有效的解,现在进行下一次尝试。\n"
|
|
|
|
# 如果没有找到解
|
|
log += "所有排列组合尝试完毕,未找到符合条件的解。\n"
|
|
return ["无解"], log # 返回无解信息和日志
|
|
|
|
|
|
|
|
def solver_main(size: int, left: list[int], right: list[int], top: list[int], bottom: list[int],simple_output):
|
|
"""
|
|
Main function to solve the skyscraper puzzle.
|
|
|
|
Parameters:
|
|
size (int): The dimension of the grid (maximum 9).
|
|
left (list[int]): Left-side views.
|
|
right (list[int]): Right-side views.
|
|
top (list[int]): Top-side views.
|
|
bottom (list[int]): Bottom-side views.
|
|
"""
|
|
# Validate size
|
|
if size > 9:
|
|
print('Error: size should be 9 or smaller')
|
|
return
|
|
|
|
# Validate the lengths of the view lists
|
|
if len(left) != size or len(right) != size or len(top) != size or len(bottom) != size:
|
|
print('Error: All view lists must have a length equal to the size of the grid')
|
|
return
|
|
|
|
# Optional verbosity for debugging
|
|
verbose = 1
|
|
if verbose > 0:
|
|
print("Input Parameters:")
|
|
print(f"Size: {size}")
|
|
print(f"Left: {left}")
|
|
print(f"Right: {right}")
|
|
print(f"Top: {top}")
|
|
print(f"Bottom: {bottom}")
|
|
|
|
# Solve the skyscraper puzzle
|
|
solution,log = solve(size, left, right, top, bottom, verbose,simple_output)
|
|
|
|
return solution,log
|
|
# Print the solution grid
|
|
print("Solution:")
|
|
for row in solution:
|
|
print(row)
|
|
|