Peteryo01223 发表于 2021-5-24 11:51:32

一个Py题:我看不懂报错内容

本帖最后由 Peteryo01223 于 2021-5-24 11:56 编辑

题目:500个小孩,围成一个圈。从第一个小孩开始计数,每次逢3,或3的倍数,出圈,如:3/6/27/468等等。直到最后剩一个小孩,请问他(她)最初的编号是多少?
答案:
# 第一个类:kid
# 第二个类:circle
# kid 属性:编号gid,lefthand、righthand
# 圈属性:head 和 tail。
# 圈的行为:加入(add)一个小孩,移除(remove)一个小孩。

class Kid:
    def __init__(self, gid):
      self.gid = gid # 小孩属性之编号
      self.left = None # 小孩属性之左手
      self.right = None # 小孩属性之右手


class Circle:
    # 初始化的时候,定义圈的头和尾
    def __init__(self, count):
      self.head = None
      self.tail = None

      for i in range(count):
            self.add(Kid(i+1))

    def add(self, kid):
      # 向圈里,加入一个小孩
      if self.head is None and self.tail is None:
            self.head = kid
            self.tail = kid
            kid.left = kid
            kid.right = kid
      else:
            kid.left = self.head
            kid.right = self.tail
            self.head.right = kid
            self.tail.left = kid
            self.tail = kid

    def remove(self, kid):
      # 从圈里面移除一个小孩
      if kid is self.head:
            self.head = kid.left
      if kid is self.left:
            self.tail = kid.right

      kid.left.right = kid.right
      kid.right.left = kid.left
      kid.left = None
      kid.right = None


circle = Circle(500)
cur = circle.head # 指针指向开头
step = 1

while circle.head is not circle.tail:
    # 当圈里不只一个小孩的时候,就继续
    cur = cur.left
    if step % 3 == 0:
      circle.remove(cur.right)
    step += 1

print(circle.head.gid)

报错内容:
D:\PycharmProjects\learnpython\venv\Scripts\python.exe D:/PycharmProjects/learnpython/ch7/20210524a.py
Traceback (most recent call last):
File "D:/PycharmProjects/learnpython/ch7/20210524a.py", line 58, in <module>
    circle.remove(cur.right)
File "D:/PycharmProjects/learnpython/ch7/20210524a.py", line 41, in remove
    if kid is self.left:
AttributeError: 'Circle' object has no attribute 'left'
看不懂报错内容,请高手们指点迷津,谢谢~此题难度太大了,我实在不会改。

Twilight6 发表于 2021-5-24 12:18:09



Circle 类中的remove 方法的第二个 if 条件 self.left 改成 self.tail 即可

    def remove(self, kid):
      # 从圈里面移除一个小孩
      if kid is self.head:
            self.head = kid.left
      if kid is self.tail:
            self.tail = kid.right

      kid.left.right = kid.right
      kid.right.left = kid.left
      kid.left = None
      kid.right = None

Peteryo01223 发表于 2021-5-24 13:19:17

Twilight6 发表于 2021-5-24 12:18
Circle 类中的remove 方法的第二个 if 条件 self.left 改成 self.tail 即可

great~

Peteryo01223 发表于 2021-5-24 13:33:16

Twilight6 发表于 2021-5-24 12:18
Circle 类中的remove 方法的第二个 if 条件 self.left 改成 self.tail 即可

多问你一句:第26-29行,我能四行合并如下么?
self.head = self.tail = kid.left = kid.right = kid
我试了试,Python 答案变成 1 了,感觉不能这么写。但是,我不懂背后的逻辑。

Twilight6 发表于 2021-5-24 13:42:18

Peteryo01223 发表于 2021-5-24 13:33
多问你一句:第26-29行,我能四行合并如下么?

我试了试,Python 答案变成 1 了,感觉不能这么写。 ...



可以这样写呀,而且最后值不会改变,是等价的

因为赋值操作,是将左边的值赋值给右边,所以这样相当于将 kid 依次赋值给了 kid.right、kid.left、self.tail、self.head

页: [1]
查看完整版本: 一个Py题:我看不懂报错内容