Smallf * ck(简单的Brainfuck方言)解释器无穷循环

问题描述 投票:0回答:1

我正在尝试实现Smallf * ck解释器。

Smallfuck是Brainfuck的一种更为简洁的方言,它以位而不是字节进行操作,具有有限的存储带大小,并且没有I / O命令。因此,只剩下5个命令:

* : flip the current bit;
> : increment the data pointer (move it to the next cell to the right);
< : decrement the data pointer (move it to the next cell to the left);
[ : “begin loop”:
    if the current bit is 1, increment the instruction pointer
    (move it to the next command to the right), otherwise,
    move it to the next command to the right of the matching ] command;
] : “end loop”:
    if the current bit is 0, increment the instruction pointer,
    otherwise move it to the next command to the right of the matching [ command.
    Can also be interpreted as unconditional jump to the matching [ command,
    since [ performs an extra check itself.

示例输入:"*>*>*>*>*>*>*>*", "00101100"应返回"11010011"

到目前为止,我的实现:

def interpreter(code, tape):
    ptr, cmd_pos = 0, 0
    tape = [int(num) for num in tape]
    while ptr < len(tape) and cmd_pos < len(code):
        if code[cmd_pos] == ">":
            ptr += 1
        elif code[cmd_pos] == "<":
            ptr -= 1
        elif code[cmd_pos] == "*":
            tape[ptr] = 1 if tape[ptr] == 0 else 0
        elif code[cmd_pos] == "[":
            if tape[ptr] == 0:
                found = False
                while not found:
                    cmd_pos += 1
                    if code[cmd_pos] == "]":
                        found = True
        elif code[cmd_pos] == "]":
            found = False
            while not found:
                cmd_pos -= 1
                if code[cmd_pos] == "[":
                    found = True
        cmd_pos += 1
    return ''.join([str(num) for num in tape])

还有一个codewars问题,这就是我这样做的原因:https://www.codewars.com/kata/58678d29dbca9a68d80000d7/train/python

我不知道我的代码出了什么问题...基本的东西起作用,但是循环不起作用。在代码战的一些测试案例中,我创建了一个无限循环,我不知道为什么。

非常感谢您的帮助,也许有人在执行此操作时甚至有很多乐趣:

python python-3.x interpreter brainfuck
1个回答
2
投票

您还需要考虑嵌套循环。例如,如果您使用代码“ [* [>]]”,则当实现到达外部循环的末尾时,它将寻找它的第一个“ [”并从那里继续。但是,由于它是外循环的“]”,因此应继续在同一外循环的“ [”(在“]”左侧搜索时找到的第二个)继续。为此,您可以例如计算在向左看时遇到的“]”数:

    elif code[cmd_pos] == "]" and tape[ptr]==1:
        found = False
        nestedLoopCounter = 1
        while not found:
            cmd_pos -= 1
            if code[cmd_pos] == "]":
                nestedLoopCounter+=1
            elif code[cmd_pos] == "[":
                nestedLoopCounter-=1
                if nestedLoopCounter==0:
                    found = True
        cmd_pos-=1

还要注意,您首先需要检查当前单元格中的值是否为1。“ [”也一样。如果遇到循环的开始并且当前单元格值为0,那么要跳过循环,您需要查找匹配的“]”,而不仅仅是找到的第一个。

© www.soinside.com 2019 - 2024. All rights reserved.