编写 Smallf*ck 解释器
Writing a Smallf*ck interpreter
我要解决的问题是这个 Codewars 套路:https://www.codewars.com/kata/58678d29dbca9a68d80000d7/train/python
我通过了 124 项测试中的 123 项,但我失败的一项与我处理嵌套循环的方式有关。我似乎无法找到一种方法来复制问题,因为它们没有向您显示测试输入。任何帮助表示赞赏;到目前为止,这是我对这个问题的看法:
import re
def interpreter(code, tape):
#Filter out non-command characters
code_pure = re.findall(r"(\>|\<|\*|\[|\])", code)
sf = "".join(code_pure)
#Convert tape to list so that elements are mutable
tape_list = []
for bit in tape:
tape_list.append(bit)
#Keep track of pointer and instruction position
pointer = 0
instr = 0
brack_pos = [] #Contains positions of "[" brackets
while instr < len(sf):
#If pointer goes out of bounds then end the program
if pointer >= len(tape_list) or pointer < 0:
return "".join(tape_list)
#"*" flips the current bit
if sf[instr] == "*":
if tape_list[pointer] == "1":
tape_list[pointer] = "0"
elif tape_list[pointer] == "0":
tape_list[pointer] = "1"
instr += 1
#Move right one bit
elif sf[instr] == ">":
pointer += 1
instr += 1
#Move left one bit
elif sf[instr] == "<":
pointer -= 1
instr += 1
elif sf[instr] == "[":
#If pointer is on 0, skip the loop
if tape_list[pointer] == "0":
brack_cnt = 1
while brack_cnt != 0:
instr += 1
if sf[instr] == "[":
brack_cnt += 1
elif sf[instr] == "]":
brack_cnt -= 1
instr += 1
#If pointer is 1, step into the loop
elif tape_list[pointer] != "0":
brack_pos.append(instr)
instr += 1
elif sf[instr] == "]":
if tape_list[pointer] == "0":
instr += 1
elif tape_list[pointer] != "0":
instr = brack_pos[-1]
brack_pos.pop()
return "".join(tape_list)
问题出在检查 sf[instr] == "]"
的最后一个 if 块中,其中 brack_pos.pop()
仅在循环回到左括号时执行,而不是在移动经过右括号时执行。 IE。 brack_pos.pop()
需要无条件。
顺便说一句,这似乎是一个有趣的练习。这是我想出的:
def interpreter(code, tape):
# Implement your interpreter here
tape = list(tape)
# Find matching brackets
jump = [0]*len(code)
open_bracket_stack = []
for i,c in enumerate(code):
if c == '[':
open_bracket_stack.append(i)
elif c == ']':
matching = open_bracket_stack.pop()
jump[i] = matching
jump[matching] = i
code_ptr = 0
tape_ptr = 0
while(code_ptr < len(code) and tape_ptr < len(tape) and tape_ptr >= 0):
c = code[code_ptr]
if c == '>':
tape_ptr += 1
elif c == '<':
tape_ptr -= 1
elif c == '*':
tape[tape_ptr] = '1' if tape[tape_ptr] == '0' else '0'
elif c == '[' and tape[tape_ptr] == '0':
code_ptr = jump[code_ptr]
elif c == ']' and tape[tape_ptr] == '1':
code_ptr = jump[code_ptr]
code_ptr += 1
return "".join(tape)
我要解决的问题是这个 Codewars 套路:https://www.codewars.com/kata/58678d29dbca9a68d80000d7/train/python
我通过了 124 项测试中的 123 项,但我失败的一项与我处理嵌套循环的方式有关。我似乎无法找到一种方法来复制问题,因为它们没有向您显示测试输入。任何帮助表示赞赏;到目前为止,这是我对这个问题的看法:
import re
def interpreter(code, tape):
#Filter out non-command characters
code_pure = re.findall(r"(\>|\<|\*|\[|\])", code)
sf = "".join(code_pure)
#Convert tape to list so that elements are mutable
tape_list = []
for bit in tape:
tape_list.append(bit)
#Keep track of pointer and instruction position
pointer = 0
instr = 0
brack_pos = [] #Contains positions of "[" brackets
while instr < len(sf):
#If pointer goes out of bounds then end the program
if pointer >= len(tape_list) or pointer < 0:
return "".join(tape_list)
#"*" flips the current bit
if sf[instr] == "*":
if tape_list[pointer] == "1":
tape_list[pointer] = "0"
elif tape_list[pointer] == "0":
tape_list[pointer] = "1"
instr += 1
#Move right one bit
elif sf[instr] == ">":
pointer += 1
instr += 1
#Move left one bit
elif sf[instr] == "<":
pointer -= 1
instr += 1
elif sf[instr] == "[":
#If pointer is on 0, skip the loop
if tape_list[pointer] == "0":
brack_cnt = 1
while brack_cnt != 0:
instr += 1
if sf[instr] == "[":
brack_cnt += 1
elif sf[instr] == "]":
brack_cnt -= 1
instr += 1
#If pointer is 1, step into the loop
elif tape_list[pointer] != "0":
brack_pos.append(instr)
instr += 1
elif sf[instr] == "]":
if tape_list[pointer] == "0":
instr += 1
elif tape_list[pointer] != "0":
instr = brack_pos[-1]
brack_pos.pop()
return "".join(tape_list)
问题出在检查 sf[instr] == "]"
的最后一个 if 块中,其中 brack_pos.pop()
仅在循环回到左括号时执行,而不是在移动经过右括号时执行。 IE。 brack_pos.pop()
需要无条件。
顺便说一句,这似乎是一个有趣的练习。这是我想出的:
def interpreter(code, tape):
# Implement your interpreter here
tape = list(tape)
# Find matching brackets
jump = [0]*len(code)
open_bracket_stack = []
for i,c in enumerate(code):
if c == '[':
open_bracket_stack.append(i)
elif c == ']':
matching = open_bracket_stack.pop()
jump[i] = matching
jump[matching] = i
code_ptr = 0
tape_ptr = 0
while(code_ptr < len(code) and tape_ptr < len(tape) and tape_ptr >= 0):
c = code[code_ptr]
if c == '>':
tape_ptr += 1
elif c == '<':
tape_ptr -= 1
elif c == '*':
tape[tape_ptr] = '1' if tape[tape_ptr] == '0' else '0'
elif c == '[' and tape[tape_ptr] == '0':
code_ptr = jump[code_ptr]
elif c == ']' and tape[tape_ptr] == '1':
code_ptr = jump[code_ptr]
code_ptr += 1
return "".join(tape)