Python程序设计 作业2(上)

简介: Python程序设计 作业2

1. 完成课程讲义中状态机的实现:


fe08e3006c284663b4f7695c55214bd9.png


(1) 累加器 Accumulator


例子:列表[-1, 2, 3, -2, 5, 6]中的数字相加,我们得到和是 13。


output = Accumulator().transduce([-1,2,3,-2,5,6]) #output=[-1, 1, 4, 2, 7, 13]


(2) 二进制相加 Binary_Addition


例子:011 和 001 相加我们得到 100。

output = Binary_Addition().transduce([(1,1),(1,0),(0,0)]) #output=[0, 0, 1]


(3) 反向器 Reverser


实现一个反向器,逆向输出一个序列。输入的形式如下:

sequence1 + [‘end’] + sequence2

其中 sequence1 是字符串列表,‘end’表示 sequence1 的终结,sequence2 为任意序列。反向器的作用如下:当 sequence1 里的每个元素输入时,反向器输出 None。当[‘end’]和 sequence2 的每个元素输入时,反向器依次反向输出 sequence1 中的元素;当没有元素输出时,则输出 None。


例子:

output = Reverser().transduce([‘foo’,’ ', ‘bar’] + [‘end’] + list(range(5))) #output = [None, None, None, ‘bar’, ’ ', ‘foo’, None, None, None]

解释:输出中前三个 None 为输入 sequence1 时输出。从输入‘end’开始,sequence1 中的元素开始反向输出。sequence1 输出完毕后,继续输出 None。(即输入 list(range(5))中的 2,3,4 时)。


更多测试例子:

①output=Reverser().transduce([‘foo’, ’ ', ‘bar’] + [‘end’] + [‘end’]*3+list(range(2)))
#output = [None, None, None, ‘bar’, ’ ', ‘foo’, None, None, None]
②output = Reverser().transduce(list(‘the’) + [‘end’] + list(range(3)))
#output = [None, None, None, ‘e’, ‘h’, ‘t’, None]
③output=Reverser().transduce([] + [‘end’] + list(range(5)))
#output = [None, None, None, None, None, None]
④output=output=Reverser().transduce(list(‘nehznehS evol I’) + [‘end’]+ list(range(15)))
#output = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, ‘I’, ’ ', ‘l’, ‘o’, ‘v’, ‘e’, ’ ', ‘S’, ‘h’, ‘e’, ‘n’, ‘z’, ‘h’, ‘e’, ‘n’, None]

实现要求:

(1) 不同的状态机子类继承父类 SM;

(2) 补充父类的 transduce 函数,子类不能重写 transduce 函数;

(3) 补充每个子类的 transition_fn 和 output_fn 函数,其中累加器的实现代码如下:

class Accumulator(SM): 
    start_state = 0
    def transition_fn(self, s, x): 
        return s + x
    def output_fn(self, s): 
        return s

建议:利用累加器的代码实现父类的 transduce 函数,再实现二进制相加和反向器的 transition_fn 和 output_fn 函数。


【解题思路】

①定义状态机:

首先定义一个状态机,设置初始状态用于传递运行状态。然后定义初始状态转移函数与输出函数。只在父类中定义基本的方法即可,并只需实现状态转移的transduce方法即可,其他方法在子类中实现即可。


②定义累加器类:

累加器类是继承于状态机类的子类。对于累加器类,可以根据下一状态都等于上一状态加上传入的参数的特性编写状态转移函数。对于输出函数,只需直接返回累加完的当前状态表示结果即可。


③定义二进制加法类:

二进制加法类是继承于状态机类的子类。对于二进制加法类,采取一个元组表示当前状态值,元组的第一个元素表示进位值,即记录低一位是否产生进位。元组的第二个元素表示已经计算的当前结果,由于二进制是逆序存储的,故对于每次加法,只需将计算出来的结果append到列表的结尾即可。

对于每次加法,一共有4种可能情况,穷举4种情况,依次进行判断即可。

最后的输出函数,需要再对最终是否产生进位进行一次判断,如果不产生进位,则直接返回元组的第二个参数即可;如果产生进位,则先执行append(1)后,再返回元组的第二个元素即可。


④定义反相器:

反相器类是继承于状态机类的子类。对于反相器类,采取的方法是记录‘end’的位置,最后统一进行计算的方法。状态值是一个四元元组分别表示是否结束,len的位置,seq1的长度和已经输入的列表。在输出中直接处理即可。


【编程实现】

# 定义状态机
class StateMachine:
    def __init__(self):
        self.start_state = None  # default start state
    def transition_fn(self, s, x):
        pass
    def output_fn(self, s):
        pass
    def transduce(self, input_seq):
        for i in range(len(input_seq)):
            self.start_state = self.transition_fn(self, self.start_state, input_seq[i])
        print(self.output_fn(self, self.start_state))
# 定义累加器
class Accumulator(StateMachine):
    start_state = 0
    def transition_fn(self, s, x):
        return s + x
    def output_fn(self, s):
        return s
# 定义二进制相加器
class Binary_Addition(StateMachine):
    start_state = (0, [])  # (carry,digit)
    def transition_fn(self, s, x):
        temp = s[1]
        # 分情况判断进位
        if s[0] + x[0] + x[1] == 3:
            temp.append(1)
            s = (1, temp)
        elif s[0] + x[0] + x[1] == 2:
            temp.append(0)
            s = (1, temp)
        elif s[0] + x[0] + x[1] == 1:
            temp.append(1)
            s = (0, temp)
        else:
            temp.append(0)
            s = (0, temp)
        return s
    def output_fn(self, s):
        # 判断最高位进位
        if s[0] == 1:
            s[1].append(1)
        return s[1]
# 定义反相器
class Reverser(StateMachine):
    start_state = (0, 0, 0, [])  # isEnd,len(seq1),total lenth
    def transition_fn(self, s, x):
        # 不断刷新state中的值
        temp = s[3]
        temp.append(x)
        if s[0] == 1:
            return 1, s[1], s[2] + 1, temp
        if x == 'end':
            return 1, s[1], s[2] + 1, temp
        else:
            return 0, s[1] + 1, s[2] + 1, temp
    def output_fn(self, s):
        # 循环获取输出
        res = []
        for i in range(s[2]):
            if i < s[1]:
                res.append(None)
            elif s[1] <= i <= 2 * s[1] - 1:
                res.append(s[3][2 * s[1] - 1 - i])
            else:
                res.append(None)
        return res

首先定义状态机父类,定义构造函数,输出函数,状态转换函数,以及transduce函数。通过仔细观察几个输入样例,不难发现,输入的list中的项数跟需要操作的次数相同,因此可以直接使用循环循环插传入list的长度,然后调用输出函数即可。


累加器类是继承于状态机类的子类。对于累加器类,可以根据下一状态都等于上一状态加上传入的参数的特性编写状态转移函数。对于输出函数,只需直接返回累加完的当前状态表示结果即可。


二进制加法类是继承于状态机类的子类。对于二进制加法类,采取一个元组表示当前状态值,元组的第一个元素表示进位值,即记录低一位是否产生进位。元组的第二个元素表示已经计算的当前结果,由于二进制是逆序存储的,故对于每次加法,只需将计算出来的结果append到列表的结尾即可。对于每次加法,一共有4种可能情况,即产生进位与否,当前位是0还是1。依次进行判断即可。最后的输出函数,需要再对最终是否产生进位进行一次判断,如果不产生进位,则直接返回元组的第二个参数即可;如果产生进位,则先执行append(1)后,再返回元组的第二个元素即可。


反相器类是继承于状态机类的子类。对于反相器类,采取的方法是记录‘end’的位置,最后统一进行计算的方法。状态值是一个四元元组分别表示是否结束,len的位置,seq1的长度和已经输入的列表。在输出中直接处理即可。最后输出时,只需首先输出seq1的长度个None,然后依次进行反向输出,最后再补齐None即可。


【测试结果】

(1)累加器:

输入:


2399109d172544ebb2475743648a0450.png

输出:

3e3deb16d20c4e49a73cf424d4524d2d.png

(2)二进制加法器:

输入:

62286f322ee643b491b760b112efc197.png


输出:

ca3c29ee992845a1928b8d94305a4a96.png


(3)反相器:

输入:

6f9238e96ba64d829bcdd02e36a74c78.png


输出:

0c71717d175346fc971398d543494a3a.png


输入:

84b03382fada46d2bf5dfb04ef6d5c38.png

输出:

3271e7f935d440dba8babda7311ada75.png


输入:

e76f8393c7444e25b2521cb731ab5796.png

输出:

c8c6c980a4ae4ae78a632cc78dbab8af.png

输入:

d3bc275ec76e43a2a8e734db24a5e11c.png

输出:

93e534fb41784639a6613408359b6651.png

[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, ‘I’, ’ ', ‘l’, ‘o’, ‘v’, ‘e’, ’ ', ‘S’, ‘h’, ‘e’, ‘n’, ‘z’, ‘h’, ‘e’, ‘n’, None]


相关文章
|
3月前
|
机器学习/深度学习 人工智能 算法
【代数学作业1完整版-python实现GNFS一般数域筛】构造特定的整系数不可约多项式:涉及素数、模运算和优化问题
【代数学作业1完整版-python实现GNFS一般数域筛】构造特定的整系数不可约多项式:涉及素数、模运算和优化问题
63 0
|
5月前
|
Python
使用python统计字符串中字母个数的函数程序设计
要统计Python字符串中的字母,首先就应该要判断出这些字符为字母,那该如何判断呢?我们可以将该字符串通过Python内置的字符串方法upper()来全部转换为大写,然后通过for循环来遍历该字符串,每次迭代过程中都使用isupper()方法来判断该字符是否为大写。这样就可以避免将字符串中的中文统计在内。我们首先来通过一个实例来了解isupper()方法的用法,如下:
49 2
|
3月前
|
机器学习/深度学习 人工智能 算法
【代数学作业1-python实现GNFS一般数域筛】构造特定的整系数不可约多项式:涉及素数、模运算和优化问题
【代数学作业1-python实现GNFS一般数域筛】构造特定的整系数不可约多项式:涉及素数、模运算和优化问题
57 0
|
8月前
|
Python Windows
Python程序设计实例 | 带图标的exe可执行文件的打包
* 本系列推文案例中,建议Python采用3.10及以上版本,NumPy采用1.22.3及以上版本,Matplotlib采用3.5.1及以上版本,Pandas采用1.4.2及以上版本。Python从3.10这个版本开始,标准发行版本中自带的IDLE交互式环境中输入提示符>>>单独放在左侧,不能随输入语句一起复制。为了清晰区分实例在交互环境中的输入和输出,本系列推文在每个输入语句的开头依然保留输入提示符>>>。
87 0
|
1月前
|
安全 数据安全/隐私保护 Python
292: 程序设计C 实验五 题目三 设计密码(python)
292: 程序设计C 实验五 题目三 设计密码(python)
|
7月前
|
数据安全/隐私保护 Python
python之用户登录程序设计
python之用户登录程序设计
|
3月前
|
Python
python作业题
python作业题
|
8月前
|
Python
Python程序设计实例 | 列表
* 本系列推文案例中,建议Python采用3.10及以上版本,NumPy采用1.22.3及以上版本,Matplotlib采用3.5.1及以上版本,Pandas采用1.4.2及以上版本。Python从3.10这个版本开始,标准发行版本中自带的IDLE交互式环境中输入提示符>>>单独放在左侧,不能随输入语句一起复制。为了清晰区分实例在交互环境中的输入和输出,本系列推文在每个输入语句的开头依然保留输入提示符>>>。
140 0
Python程序设计实例 | 列表
|
5月前
|
Python
【作业】python课-实验一
python课-实验一 01_lambda计算圆
29 0
|
5月前
|
索引 Python
Python 列表查找元素位置的高级函数代码程序设计
Python中,要查找list列表中元素的位置,即元素在列表中的索引位置,可以使用list列表类型内置的方法index(),但这个并不能直接使用,因为要考虑到查找的元素可能并不存在于list列表之中,而使用index()方法查找列表中并不存在的元素,Python将抛出ValueError,程序也可能因此终止,为了避免这种情况
42 3