Написание интерпретатора Smallf*ck

проблема, которую я пытаюсь решить, это ката Codewars: https://www.codewars.com/kata/58678d29dbca9a68d80000d7/train/python

Я прохожу 123 из 124 тестов, но тот, который я терплю неудачу, связан с тем, как я обрабатываю вложенные циклы. Я просто не могу найти способ воспроизвести проблему, потому что они не показывают вам тестовый ввод. Любая помощь приветствуется; вот что у меня есть для проблемы до сих пор:

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)

Пожалуйста, поместите часть задания (или соответствующее содержание) также в вопрос. Ссылка может не работать в будущем, но ТАК, и ваш вопрос останется там навсегда. :)

Tatranskymedved 25.12.2020 17:11

Я думаю, что вижу проблему. В этом последнем блоке if, где вы проверяете sf[instr] == "]", вы никогда не удаляете соответствующую позицию «[» при переходе за «]». Таким образом, во вложенном цикле внешний цикл вместо этого вернется к этому внутреннему «[». т.е. brack_pos.pop() должно произойти в обоих случаях.

Cereal 25.12.2020 18:19

@CerealСпасибо большое! Это оказалось проблемой, теперь я прохожу все тестовые случаи. Если вы хотите опубликовать свой комментарий как фактическое решение, я с радостью отмечу его правильным. Еще раз спасибо!

Elision 25.12.2020 18:39

@Elision Конечно, подойдет

Cereal 25.12.2020 18:50
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема заключается в проверке последнего блока if на sf[instr] == "]", где brack_pos.pop() выполняется только при возврате к открывающей скобке, а не при перемещении за закрывающую скобку. т.е. 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)

Другие вопросы по теме