InternBootcamp/internbootcamp/libs/Skyscrapers/main.py
2025-05-23 15:27:15 +08:00

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)