You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于字母高低猜秘密单词的Python脚本故障排查求助

问题描述

需要开发Python脚本,通过最多5次猜测获取服务器提供的小写秘密单词。每次猜测后,服务器会反馈对应索引字符与秘密单词的关系:大于、小于、匹配或无对应索引。

初始思路是发送16个'm'组成的字符串,再解析服务器反馈。现有解析反馈的analyze_feedback函数、生成下轮猜测的generate_next_guess函数及后续逻辑,首次运行正常,但后续几轮猜测失效。

服务器首次反馈示例

The character 'm' from your guess at index 0 is less than the character at that same index in the password.
The character 'm' from your guess at index 14 does not have a corresponding character at that same index in the password.
The character 'm' from your guess at index 6 is less than the character at that same index in the password.
The character 'm' from your guess at index 3 is less than the character at that same index in the password.
The character 'm' from your guess at index 2 is greater than the character at that same index in the password.
The character 'm' from your guess at index 13 does not have a corresponding character at that same index in the password.
The character 'm' from your guess at index 7 is greater than the character at that same index in the password.
The character 'm' from your guess at index 5 is greater than the character at that same index in the password.
The character 'm' from your guess at index 12 does not have a corresponding character at that same index in the password.
The character 'm' from your guess at index 11 does not have a corresponding character at that same index in the password.
The character 'm' from your guess at index 1 is less than the character at that same index in the password.
The character 'm' from your guess at index 9 is greater than the character at that same index in the password.
The character 'm' from your guess at index 8 is greater than the character at that same index in the password.
The character 'm' from your guess at index 10 is less than the character at that same index in the password.
The character 'm' from your guess at index 4 is greater than the character at that same index in the password.

现有代码

解析反馈函数

def analyze_feedback(feedback):
    greater_than = []
    less_than = []
    match = []
    no_match = []
    comparison = []
    feedback = feedback.split("\n", 1)[1]
    for line in feedback.splitlines():
        list_things = line.split()
        
        letter = list_things[2]
        index = list_things[8]
        comparison = list_things[10]
        matches = list_things[9]

        index.replace("'","")
        index = int(index)
        letter = letter.replace("'","")

        
        # print(letter, index, comparison, matches)
        if matches == "matches":
            match.append(index)
        elif comparison == "less":
            less_than.append(index)
        elif comparison == "greater":
            greater_than.append(index)
        else:
            no_match.append(index)
    return no_match, greater_than, less_than

生成下轮猜测函数

def generate_next_guess(current_guess, comparison, previous_guess):
    guess = ""
    if comparison == "greater":
        middle_index = (ord(current_guess) + ord('a')) // 2
        guess = chr(middle_index)
    elif comparison == "less":
        middle_index = (ord(current_guess) + ord('z')) // 2
        guess = chr(middle_index)
    else:
        return current_guess

    return guess

主逻辑片段

password = ["m","m","m","m","m","m","m","m","m","m","m","m","m","m","m",]
length_no_match = len(no_match)
password = password[:-length_no_match]
for i in greater_than:
    guess = generate_next_guess(password[i], "greater")
    password[i] = guess

for i in less_than:
    guess = generate_next_guess(password[i], "less")
    password[i] = guess
result = "".join(password)

send_data_to_server(client_socket, result)

当前核心问题

生成下轮猜测时始终取当前字符与端点('a'或'z')的中间值,没有跟踪每一轮的二分查找范围,导致首次尝试后后续几轮逻辑失效,无法快速缩小字符范围。


修复方案

1. 提升解析函数的鲁棒性

原解析依赖固定索引拆分字符串,遇到空格不规则的反馈容易出错,改用正则表达式匹配更可靠:

import re

def analyze_feedback(feedback):
    greater_than = []
    less_than = []
    match = []
    no_match = []
    # 匹配反馈内容的正则表达式
    pattern = re.compile(r"character '(\w)' from your guess at index (\d+) is (less than|greater than|matches|does not have a corresponding)")
    for line in feedback.splitlines():
        match_obj = pattern.search(line)
        if not match_obj:
            continue
        letter = match_obj.group(1)
        index = int(match_obj.group(2))
        result = match_obj.group(3)
        
        if result == "matches":
            match.append((index, letter))  # 保存已匹配的字符
        elif result == "less than":
            less_than.append(index)
        elif result == "greater than":
            greater_than.append(index)
        elif result == "does not have a corresponding":
            no_match.append(index)
    return no_match, greater_than, less_than, match

2. 跟踪每个索引的二分查找范围

为每个索引维护当前的字符范围(low, high),初始值为('a', 'z'),同时保存已确定的字符:

# 初始化:假设最大长度16,每个位置的范围都是a-z
char_ranges = {i: (ord('a'), ord('z')) for i in range(16)}
# 保存已确认匹配的字符
confirmed_chars = {}

3. 修正猜测生成逻辑

基于当前的字符范围计算中间值,而非固定使用端点:

def generate_next_guess(index, char_ranges, confirmed_chars):
    if index in confirmed_chars:
        return confirmed_chars[index]
    low, high = char_ranges[index]
    mid = (low + high) // 2
    return chr(mid)

4. 反馈后更新范围与长度

每次收到反馈后,更新对应索引的范围,并修正密码的实际长度:

# 解析服务器反馈
no_match, greater_than, less_than, match = analyze_feedback(server_feedback)

# 更新已确认的字符
for idx, char in match:
    confirmed_chars[idx] = char
    char_ranges[idx] = (ord(char), ord(char))  # 固定范围为该字符

# 更新大于/小于的字符范围
for idx in greater_than:
    current_char = current_guess[idx]
    # 当前猜测字符大于目标,将范围上限设为当前字符的前一个
    char_ranges[idx] = (char_ranges[idx][0], ord(current_char) - 1)

for idx in less_than:
    current_char = current_guess[idx]
    # 当前猜测字符小于目标,将范围下限设为当前字符的后一个
    char_ranges[idx] = (ord(current_char) + 1, char_ranges[idx][1])

# 根据无对应索引的反馈,确定密码实际长度
if no_match:
    max_valid_index = max([i for i in range(password_length) if i not in no_match], default=-1)
    password_length = max_valid_index + 1

5. 完整循环逻辑

import re

def analyze_feedback(feedback):
    greater_than = []
    less_than = []
    match = []
    no_match = []
    pattern = re.compile(r"character '(\w)' from your guess at index (\d+) is (less than|greater than|matches|does not have a corresponding)")
    for line in feedback.splitlines():
        match_obj = pattern.search(line)
        if not match_obj:
            continue
        letter = match_obj.group(1)
        index = int(match_obj.group(2))
        result = match_obj.group(3)
        
        if result == "matches":
            match.append((index, letter))
        elif result == "less than":
            less_than.append(index)
        elif result == "greater than":
            greater_than.append(index)
        elif result == "does not have a corresponding":
            no_match.append(index)
    return no_match, greater_than, less_than, match

def generate_next_guess(index, char_ranges, confirmed_chars):
    if index in confirmed_chars:
        return confirmed_chars[index]
    low, high = char_ranges[index]
    mid = (low + high) // 2
    return chr(mid)

# 初始化参数
char_ranges = {i: (ord('a'), ord('z')) for i in range(16)}
confirmed_chars = {}
password_length = 16  # 初始假设最大长度
max_attempts = 5

for attempt in range(max_attempts):
    # 生成当前猜测字符串
    current_guess = []
    for i in range(password_length):
        current_guess.append(generate_next_guess(i, char_ranges, confirmed_chars))
    current_guess_str = "".join(current_guess)
    
    # 发送猜测到服务器
    send_data_to_server(client_socket, current_guess_str)
    
    # 获取服务器反馈
    server_feedback = receive_data_from_server(client_socket)
    
    # 解析反馈并更新状态
    no_match, greater_than, less_than, match = analyze_feedback(server_feedback)
    
    # 更新已确认字符
    for idx, char in match:
        confirmed_chars[idx] = char
        char_ranges[idx] = (ord(char), ord(char))
    
    # 更新字符范围
    for idx in greater_than:
        current_char = current_guess[idx]
        char_ranges[idx] = (char_ranges[idx][0], ord(current_char) - 1)
    
    for idx in less_than:
        current_char = current_guess[idx]
        char_ranges[idx] = (ord(current_char) + 1, char_ranges[idx][1])
    
    # 更新密码长度
    if no_match:
        max_valid_index = max([i for i in range(password_length) if i not in no_match], default=-1)
        password_length = max_valid_index + 1
    
    # 检查是否全部字符已匹配
    if len(confirmed_chars) == password_length:
        final_password = "".join([confirmed_chars[i] for i in range(password_length)])
        print(f"密码已找到: {final_password}")
        break
else:
    print(f"超过{max_attempts}次尝试,未能找到密码")

内容的提问来源于stack exchange,提问作者Chline Erfindoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:25:05