python - 字符串的递归解压
问题描述
我正在尝试使用递归解压缩字符串。例如,输入:
3[b3[a]]
应该输出:
咩咩咩
但我得到:
咩咩咩咩咩咩咩咩咩咩咩咩咩
我有以下代码,但它显然是关闭的。第一个 find_end 函数按预期工作。我对使用递归和任何帮助理解/跟踪额外字母的来源或任何帮助我理解这种非常酷的方法的一般提示绝对是新手,将不胜感激。
def find_end(original, start, level):
if original[start] != "[":
message = "ERROR in find_error, must start with [:", original[start:]
raise ValueError(message)
indent = level * " "
index = start + 1
count = 1
while count != 0 and index < len(original):
if original[index] == "[":
count += 1
elif original[index] == "]":
count -= 1
index += 1
if count != 0:
message = "ERROR in find_error, mismatched brackets:", original[start:]
raise ValueError(message)
return index - 1
def decompress(original, level):
# set the result to an empty string
result = ""
# for any character in the string we have not looked at yet
for i in range(len(original)):
# if the character at the current index is a digit
if original[i].isnumeric():
# the character of the current index is the number of repetitions needed
repititions = int(original[i])
# start = the next index containing the '[' character
x = 0
while x < (len(original)):
if original[x].isnumeric():
start = x + 1
x = len(original)
else:
x += 1
# last = the index of the matching ']'
last = find_end(original, start, level)
# calculate a substring using `original[start + 1:last]
sub_original = original[start + 1 : last]
# RECURSIVELY call decompress with the substring
# sub = decompress(original, level + 1)
# concatenate the result of the recursive call times the number of repetitions needed to the result
result += decompress(sub_original, level + 1) * repititions
# set the current index to the index of the matching ']'
i = last
# else
else:
# concatenate the letter at the current index to the result
if original[i] != "[" and original[i] != "]":
result += original[i]
# return the result
return result
def main():
passed = True
ORIGINAL = 0
EXPECTED = 1
# The test cases
provided = [
("3[b]", "bbb"),
("3[b3[a]]", "baaabaaabaaa"),
("3[b2[ca]]", "bcacabcacabcaca"),
("5[a3[b]1[ab]]", "abbbababbbababbbababbbababbbab"),
]
# Run the provided tests cases
for t in provided:
actual = decompress(t[ORIGINAL], 0)
if actual != t[EXPECTED]:
print("Error decompressing:", t[ORIGINAL])
print(" Expected:", t[EXPECTED])
print(" Actual: ", actual)
print()
passed = False
# print that all the tests passed
if passed:
print("All tests passed")
if __name__ == '__main__':
main()
解决方案
从我从您的代码中收集的内容来看,它可能会给出错误的结果,因为您在给定级别查找最后一个匹配的右大括号时采用的方法(我不是 100% 确定,代码很多)。但是,我可以建议使用堆栈的更简洁的方法(几乎类似于 DFS,没有复杂性):
def decomp(s):
stack = []
for i in s:
if i.isalnum():
stack.append(i)
elif i == "]":
temp = stack.pop()
count = stack.pop()
if count.isnumeric():
stack.append(int(count)*temp)
else:
stack.append(count+temp)
for i in range(len(stack)-2, -1, -1):
if stack[i].isnumeric():
stack[i] = int(stack[i])*stack[i+1]
else:
stack[i] += stack[i+1]
return stack[0]
print(decomp("3[b]")) # bbb
print(decomp("3[b3[a]]")) # baaabaaabaaa
print(decomp("3[b2[ca]]")) # bcacabcacabcaca
print(decomp("5[a3[b]1[ab]]")) # abbbababbbababbbababbbababbbab
这适用于一个简单的观察:不是在读取 a 之后[
评估子字符串,而是在遇到 a 之后评估子字符串]
。这将允许您在单独评估各个部分之后构建结果。(这类似于使用编程的前缀/后缀评估)。
(如果您愿意,您也可以为此添加错误检查。在一次传递中检查字符串在语义上是否正确并在另一次传递中对其进行评估会更容易,而不是一次性完成)
推荐阅读
- php - 上传多张图片时如何随机生成
- c# - textBox1.Text(十六进制)到 texBox2.Text(二进制)
- bash - 如何检查更改代码的覆盖率?
- java - mockito 是否像 Junit 那样支持 TestNG 的 verifyCollector 之类的东西?
- php - Sqlite 写并发:如何实现缓冲?
- html - 从 jinja2 模板到 HTML 格式每行 1 个单词
- c# - Twilio-chat 文件中未调用该方法
- eclipse - Eclipse 项目(Facets)图标
- node.js - 无法从 Sequelize n:m 关联表中删除所有内容
- blockchain - PRIVATE_CONFIG=tm.ipc 是什么意思以及如何生成 tm.ipc 文件?