from itertools import combinations
import threading
from collections import defaultdict
import math
from multiprocessing import Pool
# 配置参数(优化阈值)
TARGET = 255966 # 目标值
BASE_VALUES = [36.5, 41.5, 59, 68.5, 74, 91.5] # 基础系数列表
FLUCTUATION = 1.0 # 系数波动范围
MAX_SOLUTIONS = 3 # 每个组合的最大解数量
SOLVER_TIMEOUT = 180 # 求解超时时间(秒)
THREE_VAR_THRESHOLD = 259000 # 使用三个变量的阈值
PRODUCT_RANGE_THRESHOLD = 129000 # 乘积范围限制阈值
HIGH_TARGET_THRESHOLD = 259000 # 更高目标值阈值
SHOW_PROGRESS = True # 是否显示进度
MAX_SOLUTIONS_PER_COMB = 100 # 每个组合的最大解数量,用于提前终止
USE_MULTIPROCESSING = True # 是否使用多进程加速
def is_valid_product(p):
"""确保单个乘积不超过129000"""
return p <= 129000 # 严格限制所有乘积不超过129000
def find_single_variable_solutions(values):
"""查找单个数的解(a*x = TARGET)"""
solutions = []
for a in values:
quotient = TARGET / a
if quotient != int(quotient):
continue
x = int(quotient)
if 1 <= x <= 10000 and is_valid_product(a * x):
solutions.append((a, x))
if len(solutions) >= MAX_SOLUTIONS:
break
return solutions
def find_two_variable_solutions(values):
"""优化的双变量求解算法,确保每个乘积不超过129000"""
solutions = defaultdict(list)
for i, a in enumerate(values):
for b in values[i:]:
seen_xy = set()
# 调整x的最大值,确保a*x不超过129000
max_x
= min
(math.
floor((TARGET
- b
) / a
), math.
floor(129000 / a
)) min_x
= max
(1, math.
ceil((TARGET
- b
* 10000) / a
))
if max_x < min_x:
continue
x_count = max_x - min_x + 1
x_step = max(1, x_count // 1000)
for x in range(min_x, max_x + 1, x_step):
ax = a * x
if ax > 129000: # 额外检查确保不超过129000
continue
remainder = TARGET - ax
if remainder < b:
break
if remainder > b * 10000:
continue
if remainder % b == 0:
y = remainder // b
by = b * y
if 1 <= y <= 10000 and by <= 129000: # 确保b*y也不超过129000
xy_pair = (x, y) if a <= b else (y, x)
if xy_pair not in seen_xy:
seen_xy.add(xy_pair)
solutions[(a, b)].append((a, x, b, y))
if len(solutions[(a, b)]) >= MAX_SOLUTIONS_PER_COMB:
break
return solutions
def process_three_var_combination(args):
"""处理三变量组合的辅助函数,用于并行计算"""
a, b, c, value_ranges, target = args
solutions = []
seen_xyz = set()
min_x, max_x = value_ranges[a]
x_count = max_x - min_x + 1
x_step = max(1, x_count // 1000)
for x in range(min_x, max_x + 1, x_step):
ax = a * x
if not is_valid_product(ax):
continue
remainder1 = target - ax
if remainder1 < 0:
break
max_y
= math.
floor((remainder1
- c
) / b
) min_y
= max
(1, math.
ceil((remainder1
- c
* 10000) / b
))
if max_y < min_y:
continue
y_count = max_y - min_y + 1
y_step = max(1, y_count // 100)
for y in range(min_y, max_y + 1, y_step):
by = b * y
if not is_valid_product(by):
continue
remainder2 = remainder1 - by
if remainder2 < 0:
break
if remainder2 > c * 10000:
continue
if remainder2 % c == 0:
z = remainder2 // c
if 1 <= z <= 10000 and is_valid_product(c * z):
xyz_tuple = tuple(sorted([x, y, z]))
if xyz_tuple not in seen_xyz:
seen_xyz.add(xyz_tuple)
solutions.append((a, x, b, y, c, z))
if len(solutions) >= MAX_SOLUTIONS_PER_COMB:
return solutions
return solutions
def find_three_variable_solutions(values):
"""优化的三变量求解算法,确保每个乘积不超过129000"""
solutions = defaultdict(list)
sorted_values = sorted(values)
# 预计算每个系数的有效范围,确保每个乘积不超过129000
value_ranges = {}
for a in sorted_values:
min_x
= max
(1, math.
ceil(1 / a
)) # 最小为1 max_x
= min
(10000, math.
floor(129000 / a
)) # 确保a*x <= 129000 value_ranges[a] = (min_x, max_x)
combinations_list = []
for i, a in enumerate(sorted_values):
for j in range(i + 1, len(sorted_values)):
b = sorted_values[j]
for k in range(j + 1, len(sorted_values)):
c = sorted_values[k]
combinations_list.append((a, b, c, value_ranges, TARGET))
if USE_MULTIPROCESSING:
with Pool() as pool:
results = pool.map(process_three_var_combination, combinations_list)
for i, (a, b, c, _, _) in enumerate(combinations_list):
if results[i]:
solutions[(a, b, c)] = results[i]
else:
total_combinations = len(combinations_list)
for i, (a, b, c, _, _) in enumerate(combinations_list):
res = process_three_var_combination((a, b, c, value_ranges, TARGET))
if res:
solutions[(a, b, c)] = res
if SHOW_PROGRESS and i % 10 == 0:
print(f"\r三变量组合进度: {i}/{total_combinations} 组", end='')
if SHOW_PROGRESS and not USE_MULTIPROCESSING:
print(f"\r三变量组合进度: {total_combinations}/{total_combinations} 组 - 完成")
return solutions
def find_balanced_solutions(solutions, var_count, num=2):
"""从所有解中筛选出最平衡的解"""
if var_count == 1 or not solutions:
return solutions
balanced = []
for sol in solutions:
vars = sol[1::2] # 获取解中的变量值
diff = max(vars) - min(vars) # 计算变量之间的最大差值
balanced.append((diff, sol))
# 按差值排序,返回差值最小的解
return [s for _, s in sorted(balanced, key=lambda x: x[0])[:num]]
def find_original_solutions(solutions, balanced_solutions, num=3):
"""从剩余解中获取原始顺序的解"""
if not solutions:
return []
remaining = [s for s in solutions if s not in balanced_solutions]
return remaining[:num]
def display_solutions(solutions_dict, var_count):
"""优化的解显示函数"""
if not solutions_dict:
return
print(f"\n找到 {len(solutions_dict)} 组{var_count}变量解:")
for i, (coeffs, pair_solutions) in enumerate(sorted(solutions_dict.items()), 1):
balanced = find_balanced_solutions(pair_solutions, var_count)
original = find_original_solutions(pair_solutions, balanced)
all_display = balanced + original
if var_count == 1:
a = coeffs
print(f"\n{i}. 组合: a={a} ({len(pair_solutions)} 个有效解)")
elif var_count == 2:
a, b = coeffs
print(f"\n{i}. 组合: a={a}, b={b} ({len(pair_solutions)} 个有效解)")
else:
a, b, c = coeffs
print(f"\n{i}. 组合: a={a}, b={b}, c={c} ({len(pair_solutions)} 个有效解)")
for j, sol in enumerate(all_display, 1):
tag = "[平衡解]" if j <= len(balanced) else "[原始解]"
if var_count == 1:
a, x = sol
print(f" {j}. x={x}, a*x={a*x:.1f}, 总和={a*x:.1f} {tag}")
elif var_count == 2:
a, x, b, y = sol
print(f" {j}. x={x}, y={y}, a*x={a*x:.1f}, b*y={b*y:.1f}, 总和={a*x + b*y:.1f} {tag}")
else:
a, x, b, y, c, z = sol
print(f" {j}. x={x}, y={y}, z={z}, "
f"a*x={a*x:.1f}, b*y={b*y:.1f}, c*z={c*z:.1f}, "
f"总和={a*x + b*y + c*z:.1f} {tag}")
def run_with_timeout(func, args=(), kwargs=None, timeout=SOLVER_TIMEOUT):
"""运行函数并设置超时限制"""
if kwargs is None:
kwargs = {}
result = []
error = []
def wrapper():
try:
result.append(func(*args, **kwargs))
except Exception as e:
error.append(e)
thread = threading.Thread(target=wrapper)
thread.daemon = True
thread.start()
thread.join(timeout)
if thread.is_alive():
print(f"警告: {func.__name__} 超时({timeout}秒),跳过此方法")
return None
if error:
return result[0]
def main():
print(f"目标值: {TARGET}")
# 生成波动后的系数
FLUCTUATED_VALUES = [round(v - FLUCTUATION, 1) for v in BASE_VALUES]
# 尝试基础系数
print(f"\n==== 尝试基础系数 ====")
# 目标值255966 > 259000不成立,会按顺序尝试单、双、三变量解
base_solutions = {
'single': run_with_timeout(find_single_variable_solutions, args=(BASE_VALUES,)),
'two': run_with_timeout(find_two_variable_solutions, args=(BASE_VALUES,)),
'three': []
}
has_solution = False
# 显示单变量解
if base_solutions['single']:
has_solution = True
display_solutions({a: [sol] for a, sol in zip(BASE_VALUES, base_solutions['single']) if sol}, 1)
# 显示双变量解
if base_solutions['two'] and len(base_solutions['two']) > 0:
has_solution = True
display_solutions(base_solutions['two'], 2)
# 单变量和双变量都无解时,尝试三变量解
if not has_solution:
print(f"\n==== 单变量和双变量无解,尝试三变量解 ====")
base_solutions['three'] = run_with_timeout(find_three_variable_solutions, args=(BASE_VALUES,))
if base_solutions['three'] and len(base_solutions['three']) > 0:
has_solution = True
display_solutions(base_solutions['three'], 3)
if has_solution:
print(f"\n使用基础系数列表,共找到有效解")
return
# 如果基础系数没有找到解,尝试波动系数
print(f"\n==== 尝试波动系数 ====")
fluctuated_solutions = {
'single': run_with_timeout(find_single_variable_solutions, args=(FLUCTUATED_VALUES,)),
'two': run_with_timeout(find_two_variable_solutions, args=(FLUCTUATED_VALUES,)),
'three': []
}
has_solution = False
# 显示单变量解
if fluctuated_solutions['single']:
has_solution = True
display_solutions({a: [sol] for a, sol in zip(FLUCTUATED_VALUES, fluctuated_solutions['single']) if sol}, 1)
# 显示双变量解
if fluctuated_solutions['two'] and len(fluctuated_solutions['two']) > 0:
has_solution = True
display_solutions(fluctuated_solutions['two'], 2)
# 单变量和双变量都无解时,尝试三变量解
if not has_solution:
print(f"\n==== 单变量和双变量无解,尝试三变量解 ====")
fluctuated_solutions['three'] = run_with_timeout(find_three_variable_solutions, args=(FLUCTUATED_VALUES,))
if fluctuated_solutions['three'] and len(fluctuated_solutions['three']) > 0:
has_solution = True
display_solutions(fluctuated_solutions['three'], 3)
if has_solution:
print(f"\n使用波动系数列表,共找到有效解")
return
# 如果所有系数集都没有找到解
print("\n没有找到符合条件的解,即使使用波动后的系数列表。")
if __name__ == "__main__":
main()
print(f"\n总耗时: {time.time() - start_time:.2f}秒")
ZnJvbSBpdGVydG9vbHMgaW1wb3J0IGNvbWJpbmF0aW9ucwppbXBvcnQgdGltZQppbXBvcnQgdGhyZWFkaW5nCmZyb20gY29sbGVjdGlvbnMgaW1wb3J0IGRlZmF1bHRkaWN0CmltcG9ydCBtYXRoCmZyb20gbXVsdGlwcm9jZXNzaW5nIGltcG9ydCBQb29sCgojIOmFjee9ruWPguaVsO+8iOS8mOWMlumYiOWAvO+8iQpUQVJHRVQgPSAyNTU5NjYgICMg55uu5qCH5YC8CkJBU0VfVkFMVUVTID0gWzM2LjUsIDQxLjUsIDU5LCA2OC41LCA3NCwgOTEuNV0gICMg5Z+656GA57O75pWw5YiX6KGoCkZMVUNUVUFUSU9OID0gMS4wICAjIOezu+aVsOazouWKqOiMg+WbtApNQVhfU09MVVRJT05TID0gMyAgIyDmr4/kuKrnu4TlkIjnmoTmnIDlpKfop6PmlbDph48KU09MVkVSX1RJTUVPVVQgPSAxODAgICMg5rGC6Kej6LaF5pe25pe26Ze0KOenkikKVEhSRUVfVkFSX1RIUkVTSE9MRCA9IDI1OTAwMCAgIyDkvb/nlKjkuInkuKrlj5jph4/nmoTpmIjlgLwKUFJPRFVDVF9SQU5HRV9USFJFU0hPTEQgPSAxMjkwMDAgICMg5LmY56ev6IyD5Zu06ZmQ5Yi26ZiI5YC8CkhJR0hfVEFSR0VUX1RIUkVTSE9MRCA9IDI1OTAwMCAgIyDmm7Tpq5jnm67moIflgLzpmIjlgLwKU0hPV19QUk9HUkVTUyA9IFRydWUgICMg5piv5ZCm5pi+56S66L+b5bqmCk1BWF9TT0xVVElPTlNfUEVSX0NPTUIgPSAxMDAgICMg5q+P5Liq57uE5ZCI55qE5pyA5aSn6Kej5pWw6YeP77yM55So5LqO5o+Q5YmN57uI5q2iClVTRV9NVUxUSVBST0NFU1NJTkcgPSBUcnVlICAjIOaYr+WQpuS9v+eUqOWkmui/m+eoi+WKoOmAnwoKZGVmIGlzX3ZhbGlkX3Byb2R1Y3QocCk6CiAgICAiIiLnoa7kv53ljZXkuKrkuZjnp6/kuI3otoXov4cxMjkwMDAiIiIKICAgIHJldHVybiBwIDw9IDEyOTAwMCAgIyDkuKXmoLzpmZDliLbmiYDmnInkuZjnp6/kuI3otoXov4cxMjkwMDAKCmRlZiBmaW5kX3NpbmdsZV92YXJpYWJsZV9zb2x1dGlvbnModmFsdWVzKToKICAgICIiIuafpeaJvuWNleS4quaVsOeahOino++8iGEqeCA9IFRBUkdFVO+8iSIiIgogICAgc29sdXRpb25zID0gW10KICAgIGZvciBhIGluIHZhbHVlczoKICAgICAgICBxdW90aWVudCA9IFRBUkdFVCAvIGEKICAgICAgICBpZiBxdW90aWVudCAhPSBpbnQocXVvdGllbnQpOgogICAgICAgICAgICBjb250aW51ZQogICAgICAgIHggPSBpbnQocXVvdGllbnQpCiAgICAgICAgaWYgMSA8PSB4IDw9IDEwMDAwIGFuZCBpc192YWxpZF9wcm9kdWN0KGEgKiB4KToKICAgICAgICAgICAgc29sdXRpb25zLmFwcGVuZCgoYSwgeCkpCiAgICAgICAgICAgIGlmIGxlbihzb2x1dGlvbnMpID49IE1BWF9TT0xVVElPTlM6CiAgICAgICAgICAgICAgICBicmVhawogICAgcmV0dXJuIHNvbHV0aW9ucwoKZGVmIGZpbmRfdHdvX3ZhcmlhYmxlX3NvbHV0aW9ucyh2YWx1ZXMpOgogICAgIiIi5LyY5YyW55qE5Y+M5Y+Y6YeP5rGC6Kej566X5rOV77yM56Gu5L+d5q+P5Liq5LmY56ev5LiN6LaF6L+HMTI5MDAwIiIiCiAgICBzb2x1dGlvbnMgPSBkZWZhdWx0ZGljdChsaXN0KQogICAgZm9yIGksIGEgaW4gZW51bWVyYXRlKHZhbHVlcyk6CiAgICAgICAgZm9yIGIgaW4gdmFsdWVzW2k6XToKICAgICAgICAgICAgc2Vlbl94eSA9IHNldCgpCiAgICAgICAgICAgICMg6LCD5pW0eOeahOacgOWkp+WAvO+8jOehruS/nWEqeOS4jei2hei/hzEyOTAwMAogICAgICAgICAgICBtYXhfeCA9IG1pbihtYXRoLmZsb29yKChUQVJHRVQgLSBiKSAvIGEpLCBtYXRoLmZsb29yKDEyOTAwMCAvIGEpKQogICAgICAgICAgICBtaW5feCA9IG1heCgxLCBtYXRoLmNlaWwoKFRBUkdFVCAtIGIgKiAxMDAwMCkgLyBhKSkKICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIG1heF94IDwgbWluX3g6CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgIHhfY291bnQgPSBtYXhfeCAtIG1pbl94ICsgMQogICAgICAgICAgICB4X3N0ZXAgPSBtYXgoMSwgeF9jb3VudCAvLyAxMDAwKQogICAgICAgICAgICAKICAgICAgICAgICAgZm9yIHggaW4gcmFuZ2UobWluX3gsIG1heF94ICsgMSwgeF9zdGVwKToKICAgICAgICAgICAgICAgIGF4ID0gYSAqIHgKICAgICAgICAgICAgICAgIGlmIGF4ID4gMTI5MDAwOiAgIyDpop3lpJbmo4Dmn6Xnoa7kv53kuI3otoXov4cxMjkwMDAKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgcmVtYWluZGVyID0gVEFSR0VUIC0gYXgKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgaWYgcmVtYWluZGVyIDwgYjoKICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgaWYgcmVtYWluZGVyID4gYiAqIDEwMDAwOgogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZiByZW1haW5kZXIgJSBiID09IDA6CiAgICAgICAgICAgICAgICAgICAgeSA9IHJlbWFpbmRlciAvLyBiCiAgICAgICAgICAgICAgICAgICAgYnkgPSBiICogeQogICAgICAgICAgICAgICAgICAgIGlmIDEgPD0geSA8PSAxMDAwMCBhbmQgYnkgPD0gMTI5MDAwOiAgIyDnoa7kv51iKnnkuZ/kuI3otoXov4cxMjkwMDAKICAgICAgICAgICAgICAgICAgICAgICAgeHlfcGFpciA9ICh4LCB5KSBpZiBhIDw9IGIgZWxzZSAoeSwgeCkKICAgICAgICAgICAgICAgICAgICAgICAgaWYgeHlfcGFpciBub3QgaW4gc2Vlbl94eToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZW5feHkuYWRkKHh5X3BhaXIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2x1dGlvbnNbKGEsIGIpXS5hcHBlbmQoKGEsIHgsIGIsIHkpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGVuKHNvbHV0aW9uc1soYSwgYildKSA+PSBNQVhfU09MVVRJT05TX1BFUl9DT01COgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICByZXR1cm4gc29sdXRpb25zCgpkZWYgcHJvY2Vzc190aHJlZV92YXJfY29tYmluYXRpb24oYXJncyk6CiAgICAiIiLlpITnkIbkuInlj5jph4/nu4TlkIjnmoTovoXliqnlh73mlbDvvIznlKjkuo7lubbooYzorqHnrpciIiIKICAgIGEsIGIsIGMsIHZhbHVlX3JhbmdlcywgdGFyZ2V0ID0gYXJncwogICAgc29sdXRpb25zID0gW10KICAgIHNlZW5feHl6ID0gc2V0KCkKICAgIAogICAgbWluX3gsIG1heF94ID0gdmFsdWVfcmFuZ2VzW2FdCiAgICB4X2NvdW50ID0gbWF4X3ggLSBtaW5feCArIDEKICAgIHhfc3RlcCA9IG1heCgxLCB4X2NvdW50IC8vIDEwMDApCiAgICAKICAgIGZvciB4IGluIHJhbmdlKG1pbl94LCBtYXhfeCArIDEsIHhfc3RlcCk6CiAgICAgICAgYXggPSBhICogeAogICAgICAgIGlmIG5vdCBpc192YWxpZF9wcm9kdWN0KGF4KToKICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgCiAgICAgICAgcmVtYWluZGVyMSA9IHRhcmdldCAtIGF4CiAgICAgICAgaWYgcmVtYWluZGVyMSA8IDA6CiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIAogICAgICAgIG1heF95ID0gbWF0aC5mbG9vcigocmVtYWluZGVyMSAtIGMpIC8gYikKICAgICAgICBtaW5feSA9IG1heCgxLCBtYXRoLmNlaWwoKHJlbWFpbmRlcjEgLSBjICogMTAwMDApIC8gYikpCiAgICAgICAgCiAgICAgICAgaWYgbWF4X3kgPCBtaW5feToKICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgCiAgICAgICAgeV9jb3VudCA9IG1heF95IC0gbWluX3kgKyAxCiAgICAgICAgeV9zdGVwID0gbWF4KDEsIHlfY291bnQgLy8gMTAwKQogICAgICAgIAogICAgICAgIGZvciB5IGluIHJhbmdlKG1pbl95LCBtYXhfeSArIDEsIHlfc3RlcCk6CiAgICAgICAgICAgIGJ5ID0gYiAqIHkKICAgICAgICAgICAgaWYgbm90IGlzX3ZhbGlkX3Byb2R1Y3QoYnkpOgogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIAogICAgICAgICAgICByZW1haW5kZXIyID0gcmVtYWluZGVyMSAtIGJ5CiAgICAgICAgICAgIGlmIHJlbWFpbmRlcjIgPCAwOgogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICBpZiByZW1haW5kZXIyID4gYyAqIDEwMDAwOgogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIAogICAgICAgICAgICBpZiByZW1haW5kZXIyICUgYyA9PSAwOgogICAgICAgICAgICAgICAgeiA9IHJlbWFpbmRlcjIgLy8gYwogICAgICAgICAgICAgICAgaWYgMSA8PSB6IDw9IDEwMDAwIGFuZCBpc192YWxpZF9wcm9kdWN0KGMgKiB6KToKICAgICAgICAgICAgICAgICAgICB4eXpfdHVwbGUgPSB0dXBsZShzb3J0ZWQoW3gsIHksIHpdKSkKICAgICAgICAgICAgICAgICAgICBpZiB4eXpfdHVwbGUgbm90IGluIHNlZW5feHl6OgogICAgICAgICAgICAgICAgICAgICAgICBzZWVuX3h5ei5hZGQoeHl6X3R1cGxlKQogICAgICAgICAgICAgICAgICAgICAgICBzb2x1dGlvbnMuYXBwZW5kKChhLCB4LCBiLCB5LCBjLCB6KSkKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGVuKHNvbHV0aW9ucykgPj0gTUFYX1NPTFVUSU9OU19QRVJfQ09NQjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzb2x1dGlvbnMKICAgIAogICAgcmV0dXJuIHNvbHV0aW9ucwoKZGVmIGZpbmRfdGhyZWVfdmFyaWFibGVfc29sdXRpb25zKHZhbHVlcyk6CiAgICAiIiLkvJjljJbnmoTkuInlj5jph4/msYLop6Pnrpfms5XvvIznoa7kv53mr4/kuKrkuZjnp6/kuI3otoXov4cxMjkwMDAiIiIKICAgIHNvbHV0aW9ucyA9IGRlZmF1bHRkaWN0KGxpc3QpCiAgICBzb3J0ZWRfdmFsdWVzID0gc29ydGVkKHZhbHVlcykKICAgIAogICAgIyDpooTorqHnrpfmr4/kuKrns7vmlbDnmoTmnInmlYjojIPlm7TvvIznoa7kv53mr4/kuKrkuZjnp6/kuI3otoXov4cxMjkwMDAKICAgIHZhbHVlX3JhbmdlcyA9IHt9CiAgICBmb3IgYSBpbiBzb3J0ZWRfdmFsdWVzOgogICAgICAgIG1pbl94ID0gbWF4KDEsIG1hdGguY2VpbCgxIC8gYSkpICAjIOacgOWwj+S4ujEKICAgICAgICBtYXhfeCA9IG1pbigxMDAwMCwgbWF0aC5mbG9vcigxMjkwMDAgLyBhKSkgICMg56Gu5L+dYSp4IDw9IDEyOTAwMAogICAgICAgIHZhbHVlX3Jhbmdlc1thXSA9IChtaW5feCwgbWF4X3gpCiAgICAKICAgIGNvbWJpbmF0aW9uc19saXN0ID0gW10KICAgIGZvciBpLCBhIGluIGVudW1lcmF0ZShzb3J0ZWRfdmFsdWVzKToKICAgICAgICBmb3IgaiBpbiByYW5nZShpICsgMSwgbGVuKHNvcnRlZF92YWx1ZXMpKToKICAgICAgICAgICAgYiA9IHNvcnRlZF92YWx1ZXNbal0KICAgICAgICAgICAgZm9yIGsgaW4gcmFuZ2UoaiArIDEsIGxlbihzb3J0ZWRfdmFsdWVzKSk6CiAgICAgICAgICAgICAgICBjID0gc29ydGVkX3ZhbHVlc1trXQogICAgICAgICAgICAgICAgY29tYmluYXRpb25zX2xpc3QuYXBwZW5kKChhLCBiLCBjLCB2YWx1ZV9yYW5nZXMsIFRBUkdFVCkpCiAgICAKICAgIGlmIFVTRV9NVUxUSVBST0NFU1NJTkc6CiAgICAgICAgd2l0aCBQb29sKCkgYXMgcG9vbDoKICAgICAgICAgICAgcmVzdWx0cyA9IHBvb2wubWFwKHByb2Nlc3NfdGhyZWVfdmFyX2NvbWJpbmF0aW9uLCBjb21iaW5hdGlvbnNfbGlzdCkKICAgICAgICAKICAgICAgICBmb3IgaSwgKGEsIGIsIGMsIF8sIF8pIGluIGVudW1lcmF0ZShjb21iaW5hdGlvbnNfbGlzdCk6CiAgICAgICAgICAgIGlmIHJlc3VsdHNbaV06CiAgICAgICAgICAgICAgICBzb2x1dGlvbnNbKGEsIGIsIGMpXSA9IHJlc3VsdHNbaV0KICAgIGVsc2U6CiAgICAgICAgdG90YWxfY29tYmluYXRpb25zID0gbGVuKGNvbWJpbmF0aW9uc19saXN0KQogICAgICAgIGZvciBpLCAoYSwgYiwgYywgXywgXykgaW4gZW51bWVyYXRlKGNvbWJpbmF0aW9uc19saXN0KToKICAgICAgICAgICAgcmVzID0gcHJvY2Vzc190aHJlZV92YXJfY29tYmluYXRpb24oKGEsIGIsIGMsIHZhbHVlX3JhbmdlcywgVEFSR0VUKSkKICAgICAgICAgICAgaWYgcmVzOgogICAgICAgICAgICAgICAgc29sdXRpb25zWyhhLCBiLCBjKV0gPSByZXMKICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIFNIT1dfUFJPR1JFU1MgYW5kIGkgJSAxMCA9PSAwOgogICAgICAgICAgICAgICAgcHJpbnQoZiJccuS4ieWPmOmHj+e7hOWQiOi/m+W6pjoge2l9L3t0b3RhbF9jb21iaW5hdGlvbnN9IOe7hCIsIGVuZD0nJykKICAgIAogICAgaWYgU0hPV19QUk9HUkVTUyBhbmQgbm90IFVTRV9NVUxUSVBST0NFU1NJTkc6CiAgICAgICAgcHJpbnQoZiJccuS4ieWPmOmHj+e7hOWQiOi/m+W6pjoge3RvdGFsX2NvbWJpbmF0aW9uc30ve3RvdGFsX2NvbWJpbmF0aW9uc30g57uEIC0g5a6M5oiQIikKICAgIAogICAgcmV0dXJuIHNvbHV0aW9ucwoKZGVmIGZpbmRfYmFsYW5jZWRfc29sdXRpb25zKHNvbHV0aW9ucywgdmFyX2NvdW50LCBudW09Mik6CiAgICAiIiLku47miYDmnInop6PkuK3nrZvpgInlh7rmnIDlubPooaHnmoTop6MiIiIKICAgIGlmIHZhcl9jb3VudCA9PSAxIG9yIG5vdCBzb2x1dGlvbnM6CiAgICAgICAgcmV0dXJuIHNvbHV0aW9ucwogICAgCiAgICBiYWxhbmNlZCA9IFtdCiAgICBmb3Igc29sIGluIHNvbHV0aW9uczoKICAgICAgICB2YXJzID0gc29sWzE6OjJdICAjIOiOt+WPluino+S4reeahOWPmOmHj+WAvAogICAgICAgIGRpZmYgPSBtYXgodmFycykgLSBtaW4odmFycykgICMg6K6h566X5Y+Y6YeP5LmL6Ze055qE5pyA5aSn5beu5YC8CiAgICAgICAgYmFsYW5jZWQuYXBwZW5kKChkaWZmLCBzb2wpKQogICAgCiAgICAjIOaMieW3ruWAvOaOkuW6j++8jOi/lOWbnuW3ruWAvOacgOWwj+eahOinowogICAgcmV0dXJuIFtzIGZvciBfLCBzIGluIHNvcnRlZChiYWxhbmNlZCwga2V5PWxhbWJkYSB4OiB4WzBdKVs6bnVtXV0KCmRlZiBmaW5kX29yaWdpbmFsX3NvbHV0aW9ucyhzb2x1dGlvbnMsIGJhbGFuY2VkX3NvbHV0aW9ucywgbnVtPTMpOgogICAgIiIi5LuO5Ymp5L2Z6Kej5Lit6I635Y+W5Y6f5aeL6aG65bqP55qE6KejIiIiCiAgICBpZiBub3Qgc29sdXRpb25zOgogICAgICAgIHJldHVybiBbXQogICAgCiAgICByZW1haW5pbmcgPSBbcyBmb3IgcyBpbiBzb2x1dGlvbnMgaWYgcyBub3QgaW4gYmFsYW5jZWRfc29sdXRpb25zXQogICAgcmV0dXJuIHJlbWFpbmluZ1s6bnVtXQoKZGVmIGRpc3BsYXlfc29sdXRpb25zKHNvbHV0aW9uc19kaWN0LCB2YXJfY291bnQpOgogICAgIiIi5LyY5YyW55qE6Kej5pi+56S65Ye95pWwIiIiCiAgICBpZiBub3Qgc29sdXRpb25zX2RpY3Q6CiAgICAgICAgcmV0dXJuCiAgICAKICAgIHByaW50KGYiXG7mib7liLAge2xlbihzb2x1dGlvbnNfZGljdCl9IOe7hHt2YXJfY291bnR95Y+Y6YeP6Kej77yaIikKICAgIAogICAgZm9yIGksIChjb2VmZnMsIHBhaXJfc29sdXRpb25zKSBpbiBlbnVtZXJhdGUoc29ydGVkKHNvbHV0aW9uc19kaWN0Lml0ZW1zKCkpLCAxKToKICAgICAgICBiYWxhbmNlZCA9IGZpbmRfYmFsYW5jZWRfc29sdXRpb25zKHBhaXJfc29sdXRpb25zLCB2YXJfY291bnQpCiAgICAgICAgb3JpZ2luYWwgPSBmaW5kX29yaWdpbmFsX3NvbHV0aW9ucyhwYWlyX3NvbHV0aW9ucywgYmFsYW5jZWQpCiAgICAgICAgYWxsX2Rpc3BsYXkgPSBiYWxhbmNlZCArIG9yaWdpbmFsCiAgICAgICAgCiAgICAgICAgaWYgdmFyX2NvdW50ID09IDE6CiAgICAgICAgICAgIGEgPSBjb2VmZnMKICAgICAgICAgICAgcHJpbnQoZiJcbntpfS4g57uE5ZCIOiBhPXthfSAoe2xlbihwYWlyX3NvbHV0aW9ucyl9IOS4quacieaViOinoykiKQogICAgICAgIGVsaWYgdmFyX2NvdW50ID09IDI6CiAgICAgICAgICAgIGEsIGIgPSBjb2VmZnMKICAgICAgICAgICAgcHJpbnQoZiJcbntpfS4g57uE5ZCIOiBhPXthfSwgYj17Yn0gKHtsZW4ocGFpcl9zb2x1dGlvbnMpfSDkuKrmnInmlYjop6MpIikKICAgICAgICBlbHNlOgogICAgICAgICAgICBhLCBiLCBjID0gY29lZmZzCiAgICAgICAgICAgIHByaW50KGYiXG57aX0uIOe7hOWQiDogYT17YX0sIGI9e2J9LCBjPXtjfSAoe2xlbihwYWlyX3NvbHV0aW9ucyl9IOS4quacieaViOinoykiKQogICAgICAgIAogICAgICAgIGZvciBqLCBzb2wgaW4gZW51bWVyYXRlKGFsbF9kaXNwbGF5LCAxKToKICAgICAgICAgICAgdGFnID0gIlvlubPooaHop6NdIiBpZiBqIDw9IGxlbihiYWxhbmNlZCkgZWxzZSAiW+WOn+Wni+ino10iCiAgICAgICAgICAgIAogICAgICAgICAgICBpZiB2YXJfY291bnQgPT0gMToKICAgICAgICAgICAgICAgIGEsIHggPSBzb2wKICAgICAgICAgICAgICAgIHByaW50KGYiICB7an0uIHg9e3h9LCBhKng9e2EqeDouMWZ9LCDmgLvlkow9e2EqeDouMWZ9IHt0YWd9IikKICAgICAgICAgICAgZWxpZiB2YXJfY291bnQgPT0gMjoKICAgICAgICAgICAgICAgIGEsIHgsIGIsIHkgPSBzb2wKICAgICAgICAgICAgICAgIHByaW50KGYiICB7an0uIHg9e3h9LCB5PXt5fSwgYSp4PXthKng6LjFmfSwgYip5PXtiKnk6LjFmfSwg5oC75ZKMPXthKnggKyBiKnk6LjFmfSB7dGFnfSIpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBhLCB4LCBiLCB5LCBjLCB6ID0gc29sCiAgICAgICAgICAgICAgICBwcmludChmIiAge2p9LiB4PXt4fSwgeT17eX0sIHo9e3p9LCAiCiAgICAgICAgICAgICAgICAgICAgICBmImEqeD17YSp4Oi4xZn0sIGIqeT17Yip5Oi4xZn0sIGMqej17Yyp6Oi4xZn0sICIKICAgICAgICAgICAgICAgICAgICAgIGYi5oC75ZKMPXthKnggKyBiKnkgKyBjKno6LjFmfSB7dGFnfSIpCgpkZWYgcnVuX3dpdGhfdGltZW91dChmdW5jLCBhcmdzPSgpLCBrd2FyZ3M9Tm9uZSwgdGltZW91dD1TT0xWRVJfVElNRU9VVCk6CiAgICAiIiLov5DooYzlh73mlbDlubborr7nva7otoXml7bpmZDliLYiIiIKICAgIGlmIGt3YXJncyBpcyBOb25lOgogICAgICAgIGt3YXJncyA9IHt9CiAgICAKICAgIHJlc3VsdCA9IFtdCiAgICBlcnJvciA9IFtdCiAgICAKICAgIGRlZiB3cmFwcGVyKCk6CiAgICAgICAgdHJ5OgogICAgICAgICAgICByZXN1bHQuYXBwZW5kKGZ1bmMoKmFyZ3MsICoqa3dhcmdzKSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIGVycm9yLmFwcGVuZChlKQogICAgCiAgICB0aHJlYWQgPSB0aHJlYWRpbmcuVGhyZWFkKHRhcmdldD13cmFwcGVyKQogICAgdGhyZWFkLmRhZW1vbiA9IFRydWUKICAgIHRocmVhZC5zdGFydCgpCiAgICB0aHJlYWQuam9pbih0aW1lb3V0KQogICAgCiAgICBpZiB0aHJlYWQuaXNfYWxpdmUoKToKICAgICAgICBwcmludChmIuitpuWRijoge2Z1bmMuX19uYW1lX199IOi2heaXtu+8iHt0aW1lb3V0feenku+8ie+8jOi3s+i/h+atpOaWueazlSIpCiAgICAgICAgcmV0dXJuIE5vbmUKICAgIAogICAgaWYgZXJyb3I6CiAgICAgICAgcmFpc2UgZXJyb3JbMF0KICAgIAogICAgcmV0dXJuIHJlc3VsdFswXQoKZGVmIG1haW4oKToKICAgIHByaW50KGYi55uu5qCH5YC8OiB7VEFSR0VUfSIpCiAgICAKICAgICMg55Sf5oiQ5rOi5Yqo5ZCO55qE57O75pWwCiAgICBGTFVDVFVBVEVEX1ZBTFVFUyA9IFtyb3VuZCh2IC0gRkxVQ1RVQVRJT04sIDEpIGZvciB2IGluIEJBU0VfVkFMVUVTXQogICAgCiAgICAjIOWwneivleWfuuehgOezu+aVsAogICAgcHJpbnQoZiJcbj09PT0g5bCd6K+V5Z+656GA57O75pWwID09PT0iKQogICAgCiAgICAjIOebruagh+WAvDI1NTk2NiA+IDI1OTAwMOS4jeaIkOeri++8jOS8muaMiemhuuW6j+WwneivleWNleOAgeWPjOOAgeS4ieWPmOmHj+inowogICAgYmFzZV9zb2x1dGlvbnMgPSB7CiAgICAgICAgJ3NpbmdsZSc6IHJ1bl93aXRoX3RpbWVvdXQoZmluZF9zaW5nbGVfdmFyaWFibGVfc29sdXRpb25zLCBhcmdzPShCQVNFX1ZBTFVFUywpKSwKICAgICAgICAndHdvJzogcnVuX3dpdGhfdGltZW91dChmaW5kX3R3b192YXJpYWJsZV9zb2x1dGlvbnMsIGFyZ3M9KEJBU0VfVkFMVUVTLCkpLAogICAgICAgICd0aHJlZSc6IFtdCiAgICB9CiAgICAKICAgIGhhc19zb2x1dGlvbiA9IEZhbHNlCiAgICAKICAgICMg5pi+56S65Y2V5Y+Y6YeP6KejCiAgICBpZiBiYXNlX3NvbHV0aW9uc1snc2luZ2xlJ106CiAgICAgICAgaGFzX3NvbHV0aW9uID0gVHJ1ZQogICAgICAgIGRpc3BsYXlfc29sdXRpb25zKHthOiBbc29sXSBmb3IgYSwgc29sIGluIHppcChCQVNFX1ZBTFVFUywgYmFzZV9zb2x1dGlvbnNbJ3NpbmdsZSddKSBpZiBzb2x9LCAxKQogICAgCiAgICAjIOaYvuekuuWPjOWPmOmHj+inowogICAgaWYgYmFzZV9zb2x1dGlvbnNbJ3R3byddIGFuZCBsZW4oYmFzZV9zb2x1dGlvbnNbJ3R3byddKSA+IDA6CiAgICAgICAgaGFzX3NvbHV0aW9uID0gVHJ1ZQogICAgICAgIGRpc3BsYXlfc29sdXRpb25zKGJhc2Vfc29sdXRpb25zWyd0d28nXSwgMikKICAgIAogICAgIyDljZXlj5jph4/lkozlj4zlj5jph4/pg73ml6Dop6Pml7bvvIzlsJ3or5XkuInlj5jph4/op6MKICAgIGlmIG5vdCBoYXNfc29sdXRpb246CiAgICAgICAgcHJpbnQoZiJcbj09PT0g5Y2V5Y+Y6YeP5ZKM5Y+M5Y+Y6YeP5peg6Kej77yM5bCd6K+V5LiJ5Y+Y6YeP6KejID09PT0iKQogICAgICAgIGJhc2Vfc29sdXRpb25zWyd0aHJlZSddID0gcnVuX3dpdGhfdGltZW91dChmaW5kX3RocmVlX3ZhcmlhYmxlX3NvbHV0aW9ucywgYXJncz0oQkFTRV9WQUxVRVMsKSkKICAgICAgICAKICAgICAgICBpZiBiYXNlX3NvbHV0aW9uc1sndGhyZWUnXSBhbmQgbGVuKGJhc2Vfc29sdXRpb25zWyd0aHJlZSddKSA+IDA6CiAgICAgICAgICAgIGhhc19zb2x1dGlvbiA9IFRydWUKICAgICAgICAgICAgZGlzcGxheV9zb2x1dGlvbnMoYmFzZV9zb2x1dGlvbnNbJ3RocmVlJ10sIDMpCiAgICAKICAgIGlmIGhhc19zb2x1dGlvbjoKICAgICAgICBwcmludChmIlxu5L2/55So5Z+656GA57O75pWw5YiX6KGo77yM5YWx5om+5Yiw5pyJ5pWI6KejIikKICAgICAgICByZXR1cm4KICAgIAogICAgIyDlpoLmnpzln7rnoYDns7vmlbDmsqHmnInmib7liLDop6PvvIzlsJ3or5Xms6Lliqjns7vmlbAKICAgIHByaW50KGYiXG49PT09IOWwneivleazouWKqOezu+aVsCA9PT09IikKICAgIAogICAgZmx1Y3R1YXRlZF9zb2x1dGlvbnMgPSB7CiAgICAgICAgJ3NpbmdsZSc6IHJ1bl93aXRoX3RpbWVvdXQoZmluZF9zaW5nbGVfdmFyaWFibGVfc29sdXRpb25zLCBhcmdzPShGTFVDVFVBVEVEX1ZBTFVFUywpKSwKICAgICAgICAndHdvJzogcnVuX3dpdGhfdGltZW91dChmaW5kX3R3b192YXJpYWJsZV9zb2x1dGlvbnMsIGFyZ3M9KEZMVUNUVUFURURfVkFMVUVTLCkpLAogICAgICAgICd0aHJlZSc6IFtdCiAgICB9CiAgICAKICAgIGhhc19zb2x1dGlvbiA9IEZhbHNlCiAgICAKICAgICMg5pi+56S65Y2V5Y+Y6YeP6KejCiAgICBpZiBmbHVjdHVhdGVkX3NvbHV0aW9uc1snc2luZ2xlJ106CiAgICAgICAgaGFzX3NvbHV0aW9uID0gVHJ1ZQogICAgICAgIGRpc3BsYXlfc29sdXRpb25zKHthOiBbc29sXSBmb3IgYSwgc29sIGluIHppcChGTFVDVFVBVEVEX1ZBTFVFUywgZmx1Y3R1YXRlZF9zb2x1dGlvbnNbJ3NpbmdsZSddKSBpZiBzb2x9LCAxKQogICAgCiAgICAjIOaYvuekuuWPjOWPmOmHj+inowogICAgaWYgZmx1Y3R1YXRlZF9zb2x1dGlvbnNbJ3R3byddIGFuZCBsZW4oZmx1Y3R1YXRlZF9zb2x1dGlvbnNbJ3R3byddKSA+IDA6CiAgICAgICAgaGFzX3NvbHV0aW9uID0gVHJ1ZQogICAgICAgIGRpc3BsYXlfc29sdXRpb25zKGZsdWN0dWF0ZWRfc29sdXRpb25zWyd0d28nXSwgMikKICAgIAogICAgIyDljZXlj5jph4/lkozlj4zlj5jph4/pg73ml6Dop6Pml7bvvIzlsJ3or5XkuInlj5jph4/op6MKICAgIGlmIG5vdCBoYXNfc29sdXRpb246CiAgICAgICAgcHJpbnQoZiJcbj09PT0g5Y2V5Y+Y6YeP5ZKM5Y+M5Y+Y6YeP5peg6Kej77yM5bCd6K+V5LiJ5Y+Y6YeP6KejID09PT0iKQogICAgICAgIGZsdWN0dWF0ZWRfc29sdXRpb25zWyd0aHJlZSddID0gcnVuX3dpdGhfdGltZW91dChmaW5kX3RocmVlX3ZhcmlhYmxlX3NvbHV0aW9ucywgYXJncz0oRkxVQ1RVQVRFRF9WQUxVRVMsKSkKICAgICAgICAKICAgICAgICBpZiBmbHVjdHVhdGVkX3NvbHV0aW9uc1sndGhyZWUnXSBhbmQgbGVuKGZsdWN0dWF0ZWRfc29sdXRpb25zWyd0aHJlZSddKSA+IDA6CiAgICAgICAgICAgIGhhc19zb2x1dGlvbiA9IFRydWUKICAgICAgICAgICAgZGlzcGxheV9zb2x1dGlvbnMoZmx1Y3R1YXRlZF9zb2x1dGlvbnNbJ3RocmVlJ10sIDMpCiAgICAKICAgIGlmIGhhc19zb2x1dGlvbjoKICAgICAgICBwcmludChmIlxu5L2/55So5rOi5Yqo57O75pWw5YiX6KGo77yM5YWx5om+5Yiw5pyJ5pWI6KejIikKICAgICAgICByZXR1cm4KICAgIAogICAgIyDlpoLmnpzmiYDmnInns7vmlbDpm4bpg73msqHmnInmib7liLDop6MKICAgIHByaW50KCJcbuayoeacieaJvuWIsOespuWQiOadoeS7tueahOino++8jOWNs+S9v+S9v+eUqOazouWKqOWQjueahOezu+aVsOWIl+ihqOOAgiIpCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgc3RhcnRfdGltZSA9IHRpbWUudGltZSgpCiAgICBtYWluKCkKICAgIHByaW50KGYiXG7mgLvogJfml7Y6IHt0aW1lLnRpbWUoKSAtIHN0YXJ0X3RpbWU6LjJmfeenkiIpICAgIA==