Python3:双向队列deque实战 - BrainFuck执行器

基础知识

Python3中的双向队列(deque)是一个能够从两端进行操作的序列容器。它的特点是可以高效地在两端进行元素的插入和删除操作,而不像列表(list)那样在头部插入或删除元素时会导致整个序列的复制和移动。Python的标准库collections中提供了deque的实现,使用方法和列表类似,可以通过append、appendleft、pop和popleft等方法进行操作。在这里介绍了deque的常用语法。
Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。它只有8种关键字,是一个极小化的语言。虽然语言比较小和简单,但是它是图灵完备的,于是经常用于计算理论中相关论题的验证。

BrainFuck执行器实现

计算模型:定义Table类,定义一个双向无限长的寄存器空间,仅在指针指向的位置可存取值。每一个寄存器内初始值为0。指针初始指向的位置为0. 支持指针的移动,读写指针位置值及字节操作(增减)。

双向队列在处理一些需要同时从头尾操作的场合非常有用,,所以在这里用一个双向队列及指向这个队列中位置的指针实现我们定义的计算模型。在实现中,保证指针的下标始终不小于0.

import collections


class Table:
    def __init__(self):
        self.register = collections.deque([0])
        self.ptr = 0

    def ptr_l(self):
        if self.ptr == 0:
            self.register.appendleft(0)
        else:
            self.ptr -= 1

    def ptr_r(self):
        self.ptr += 1
        if self.ptr == len(self.register):
            self.register.append(0)

    def add1(self):
        self.register[self.ptr] += 1

    def sub1(self):
        self.register[self.ptr] -= 1

    def set(self, value):
        self.register[self.ptr] = value

    def get(self):
        return self.register[self.ptr]

解释器:定义Env类,包含一个计算模型和指令的读取、执行方法。这个类通过process方法执行指令,从代码段code读取指令,从输入缓冲区inp读取输入,在self.table执行指令,写输出到输出缓冲区outp,最终一起输出outp的内容。

class Env:
    def __init__(self):
        self.table = Table()

    def process(self, code, inp):
        num_ins, ptr_ins = 0, 0
        ptr_inp = 0
        outp = ""
        while ptr_ins < len(code):
            if code[ptr_ins] == '>':
                self.table.ptr_l()
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == '<':
                self.table.ptr_r()
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == '+':
                self.table.add1()
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == '-':
                self.table.sub1()
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == '.':
                outp += chr(self.table.get())
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == ',':
                if ptr_inp < len(inp):
                    self.table.set(ord(inp[ptr_inp]))
                    ptr_inp += 1
                else:
                    raise ValueError('Input exhausted')
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == '[':
                if self.table.get() == 0:
                    while ptr_ins < len(code) and code[ptr_ins] != ']':
                        num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            elif code[ptr_ins] == ']':
                if self.table.get() != 0:
                    while ptr_ins >= 0 and code[ptr_ins] != '[':
                        num_ins, ptr_ins = num_ins + 1, ptr_ins - 1
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
            else:
                num_ins, ptr_ins = num_ins + 1, ptr_ins + 1
        return outp

测试:将代码段和输入缓冲区的内容作为参数传入interpreter,从interpreter.process获得输出。

if __name__ == '__main__':
    interpreter = Env()

    # hello world
    hello_world_code = '>++++++++[ < +++++++++ > -] < . > ++++[ < +++++++ > -] < +.+++++++..+++.>>++++++[ < +++++++ > -] < ++.------------. > ++++++[ < +++++++++ > -] < +. < .+++.------.--------.>> > ++++[ < ++++++++ > -] < +.'
    print(interpreter.process(hello_world_code, None))

    # toUpper
    toUpper_code = ', ----------[----------------------., ----------]'
    print(interpreter.process(toUpper_code, 'hello\n'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值