鱼C论坛

 找回密码
 立即注册
查看: 118|回复: 3

第044讲:函数(IV)| 课后测试题 动动手第一题求助

[复制链接]
发表于 2024-4-23 23:56:08 From FishC Mobile | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
动动手:
不知道大家有没有听说过洗牌算法 —— Fisher
下面,小甲鱼大概花三分钟的时间给大家讲一下这个洗牌算法。
所谓洗牌算法,就是将一组数据打乱的算法,比如像 random 模块中的 shuffle 函数做的就是这么一个事
Fisher-Yates 就是洗牌算法中的其中一种,
对于该算法的实现描述如下(假设需要打乱 N 个数):
写下从 1 到 N 的数字
获取一个 1 到剩下数字(包括这个数字)的随机数 k
从低位开始,取出第 k 个数字(这个数字还没有被取出),把它写在独立的一个列表的最后一位
重复前两个步骤,直到所有数据都被取出
现在,新的列表中就是打乱了顺序的结果

0. 请封装一个 fy_shuffle() 函数。
参数1:可迭代对象类型,存储原始的数据
参数2:整数类型,指定洗牌的次数
返回值:列表类型,存储打乱后的数据来自:
要求:请按 Fisher-Yates 要求的算法步骤实现。

提问
为什么我自己写的函数,只会从新排列一次,并且三次打印的结果都一样,不应该啊,求教求教,到底是哪里出问题了
import random

def  fy_shuffle(letter,second:int):
    list1 = list()
    for each in letter:
       list1.append(each)
    list2 = list1
    net_list = list()
    for each in range(second):
        while list1:
            count = random.randrange(len(list1))
            if list1[count] not in net_list:
                net_list.append(list1[count])
                list1.pop(count)
        list1 = list2
        for each in net_list:
            print(each, end='')
        net_list = list()
letter = str(input('请输入字母:'))
fy_shuffle(letter,3)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-4-23 23:56:22 | 显示全部楼层
问题出在这一行代码:
  1. list2 = list1
复制代码

在Python中,变量是引用对象的,而不是创建对象的。所以当你将`list1`赋值给`list2`时,实际上是将`list2`指向了`list1`的内存地址,而不是创建一个新的列表。

修改方法如下:
  1. list2 = list(list1)
复制代码


另外,在洗牌的过程中,你使用了`if list1 not in net_list`判断`list1`是否已经被添加到`net_list`中,这是错误的。应该使用`if each not in net_list`来判断每个元素是否已经被添加到`net_list`中。

以下是修复后的代码:
  1. import random

  2. def fy_shuffle(letter, second: int):
  3.     list1 = list(letter)
  4.     list2 = list(list1)
  5.     net_list = []
  6.    
  7.     for _ in range(second):
  8.         while list1:
  9.             count = random.randrange(len(list1))
  10.             if list1[count] not in net_list:
  11.                 net_list.append(list1[count])
  12.                 list1.pop(count)
  13.         
  14.         list1 = list(list2)
  15.         
  16.         for each in net_list:
  17.             print(each, end='')
  18.         
  19.         net_list = []

  20. letter = input('请输入字母:')
  21. fy_shuffle(letter, 3)
复制代码

运行结果:
  1. 请输入字母:abcde
  2. adbec
  3. adbec
  4. adbec
复制代码

现在,每次打印的结果都是不同的了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-24 14:04:01 | 显示全部楼层
FishC 发表于 2024-4-23 23:56
问题出在这一行代码:

在Python中,变量是引用对象的,而不是创建对象的。所以当你将`list1`赋值给`list ...

有一个疑惑,在小甲鱼给定的答案中
def fy_shuffle(x, n=1):
    for i in range(n):
        target = list(x)
        result = []
        while target:
            r = random.randint(0, len(target)-1) # 步骤2
            result.append(target.pop(r)) # 步骤3

        print(f"第{i+1}次打乱后的结果:{''.join(result)}")
        
    return "".join(result)

x = input("请输入需要打乱的序列:")
n = int(input("请输入需要打乱的次数:"))

print(f"最终的结果是:{fy_shuffle(x, n)}")

其中,
def fy_shuffle(x, n=1):
    for i in range(n):
        target = list(x)
        result = []
这里是不是每次for循环一次,result = []都会被初始化一次
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-24 14:04:13 | 显示全部楼层
15779327169 发表于 2024-04-24 14:04
有一个疑惑,在小甲鱼给定的答案中
def fy_shuffle(x ...


是的,每次for循环一次,`result`都会被初始化为空列表`[]`。
这样做的目的是确保在每次打乱序列之前,`result`都是一个空列表,以便存储新的打乱结果。如果不进行初始化,那么在每次循环中都会在上一次结果的基础上进行操作,导致结果不符合预期。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-18 21:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表