鱼C论坛

 找回密码
 立即注册
查看: 4372|回复: 33

[技术交流] 小练习20160124:猜数----点评与结果

[复制链接]
发表于 2016-2-1 19:55:55 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 冬雪雪冬 于 2016-2-4 11:02 编辑

本次练习大家答题踊跃,很多人给出了优秀的答案。
这次评判的原则是在符合题意的答案中看谁的尝试次数最少,谁的用时最短。答案正确的结果如下:
ID
尝试次数
用时
zooo
5.807
0.7647
DingRan
5.803
0.4479
wei_Y
8.367
2.165
Lnan95
6.063
0.954
USTC-ssj
  1.495
落殇飞羽
5.688
0.5527
shuofxz
8.989
1.973
FDMa
5.808
0.4063
第一个答对的是 @zooo
结果最佳的是 @DingRan  和 @FDMa




@零度非安全 的作业也非常优秀,采用2分法,并给出了详尽的注释。但出现了一个小BUG,他也在比赛结束后发现了并改正,为确保对其他参赛者的公平,只好忍痛割爱了。对他这种认真精神也将予以鼓励。



本次活动的结果请大家点评,如果有异议请于2.3 22:00前提出。

===========================================================

最终结果,最佳奖 @DingRan  和 @FDMa,
第一答对奖 @zooo









第一个给出答案的是 @debi999
  1. import random
  2. #新建空列表,用于存放猜数字的记数
  3. count=[]

  4. #定义猜数字函数
  5. def funC():
  6.     a=int(random.uniform(1,100))
  7.     b=int(random.uniform(1,100))
  8.     for i in range(1,11):
  9.         if b==a:
  10.             break
  11.         else:
  12.             b=int(random.uniform(1,100))
  13.     count.append(int(i))

  14. #循环执行100000次   
  15. for j in range(0,100000):
  16.     funC()

  17. #定义猜中次数的计数器
  18. a1=0
  19. a2=0
  20. a3=0
  21. a4=0
  22. a5=0
  23. a6=0
  24. a7=0
  25. a8=0
  26. a9=0
  27. list1=[]

  28. #判断猜中次数
  29. for m in range(len(count)):
  30.     if count[m]==1:
  31.         a1+=1
  32.     elif count[m]==2:
  33.         a2+=1
  34.     elif count[m]==3:
  35.         a3+=1
  36.     elif count[m]==4:
  37.         a4+=1
  38.     elif count[m]==5:
  39.         a5+=1
  40.     elif count[m]==6:
  41.         a6+=1
  42.     elif count[m]==7:
  43.         a7+=1
  44.     elif count[m]==8:
  45.         a8+=1
  46.     elif count[m]==9:
  47.         a9+=1
  48. list1.extend([a1,a2,a3,a4,a5,a6,a7,a8,a9])

  49. #计算平均值
  50. sum= (a1+a2+a3+a4+a5+a6+a7+a8+a9)
  51. pjz=sum/(max(list1))

  52. #输出
  53. print('尝试 1 次猜中的有 %d 轮'%a1)
  54. print('尝试 2 次猜中的有 %d 轮'%a2)
  55. print('尝试 3 次猜中的有 %d 轮'%a3)
  56. print('尝试 4 次猜中的有 %d 轮'%a4)
  57. print('尝试 5 次猜中的有 %d 轮'%a5)
  58. print('尝试 6 次猜中的有 %d 轮'%a6)
  59. print('尝试 7 次猜中的有 %d 轮'%a7)
  60. print('尝试 8 次猜中的有 %d 轮'%a8)
  61. print('尝试 9 次猜中的有 %d 轮'%a9)
  62. print ('平均 %.3f 次猜中'%pjz)
复制代码


很遗憾虽然整体思路是对的,但有些错误没有完成题意的要求。
1.用两个随机数来确定答案和猜数,并反复随机猜数来使两者相等,这样效率不高,且只比较10次无法保证每轮都能猜出答案。
2.用random.uniform函数得到的是实数,虽然用int取整,一是效率低,二是数字不是完全随机分布,出现100的可能性太低。





评分

参与人数 1荣誉 +1 鱼币 +1 收起 理由
zooo + 1 + 1 支持楼主!

查看全部评分

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-2-1 20:09:40 | 显示全部楼层
下一个参赛者是 @zooo
  1. import random
  2. gesTimes = [0,0,0,0,0,0,0]#每玩一次,猜的次数统计表
  3. gameTimes = 100000 #玩的总轮数
  4. for z in range(gameTimes):
  5.     maxNum = 102#经调试后确定的上限值->100+2
  6.     minNum = 0
  7.     ans = random.randint(1,100) #1,100的随机数
  8.     playTime = 1#每轮猜的次数
  9.     gesNum = (maxNum - minNum)/2
  10.     #二分法猜数
  11.     while ans != gesNum :
  12.         if gesNum > ans:#如果大了则要变小
  13.             maxNum = gesNum
  14.             gesNum -= (maxNum - minNum)//2#变小多少
  15.         else:#如果小了则要变大
  16.             minNum = gesNum
  17.             gesNum += (maxNum - minNum)//2#变大多少
  18.         playTime += 1
  19.         #调试代码(可以屏蔽)
  20.         if 10 <playTime:
  21.             print("error:",ans) #看看有哪个值漏了
  22.             break
  23.     #录表
  24.     for i in range(7):
  25.         if playTime == (i+1) :
  26.             gesTimes[i] += 1
  27.             break
  28. #验证统计表中总数是否与游戏总轮数对应(可以屏蔽)
  29. Sum = 0
  30. for i in gesTimes:
  31.     Sum += i
  32. print("统计次数总和:",Sum)

  33. #输出结果
  34. suum = 0
  35. for i in range(7):
  36.     z = i + 1
  37.     suum += z*gesTimes[i]
  38.     print("尝试 %d 猜中的有 %d 轮"%(z,gesTimes[i]))
  39. print("平均 %2.3f 次猜中"%(suum/gameTimes)) #%2.3f控制精度
复制代码


他采用二分法来确定猜数,效率较高,并根据实际运行情况调整了maxNum,使程序更合理。
实际运行结果:
统计次数总和: 100000
尝试 1 猜中的有 992 轮
尝试 2 猜中的有 1957 轮
尝试 3 猜中的有 3998 轮
尝试 4 猜中的有 7890 轮
尝试 5 猜中的有 15999 轮
尝试 6 猜中的有 31939 轮
尝试 7 猜中的有 37225 轮
平均 5.807 次猜中
用时:0.7647s
(注:用时为我在程序中加上time函数计算的,用时和平均猜中需要次数为实测值,后续的帖子相同)
优点:注释详尽,易读性好。
小建议:gesTimes = [0,0,0,0,0,0,0] 写成 gesTimes = [0] * 7 更简介明了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 20:15:56 | 显示全部楼层
本帖最后由 冬雪雪冬 于 2016-2-1 20:52 编辑

这是 @DingRan 的答案。
  1. import random

  2. #参数
  3. gameRound = 100000 #运行轮数
  4. bottom = 1 #猜数区间的下限
  5. top = 100 #猜数区间的上限

  6. #猜数并得出结果
  7. result = [] #用来储存结果
  8. for temp in range(gameRound):
  9.     attempt = 0 #初始化尝试次数
  10.     b = bottom
  11.     t = top
  12.     secret = random.randint(b,t) #生成随机数作为答案
  13.     while True:
  14.         guess = random.randint(b,t) #开猜
  15.         attempt += 1
  16.         if guess > secret: #猜大了
  17.             t = guess - 1
  18.         elif guess < secret: #猜小了
  19.             b = guess + 1
  20.         elif guess == secret : #猜对了
  21.             break
  22.     result.append(attempt) #储存结果

  23. #输出
  24. for n in range(min(result),max(result)+1):
  25.     if n in result:
  26.         print('尝试 %d 次猜中的有 %d 轮'%(n,result.count(n)))
  27. print('平均 %.3f 次猜中'%(sum(result)/len(result)))
复制代码

方法与 @debi999 有些类似都是用随机数作为猜数,但每次根据比较的大小,调整猜数随机数的范围,大幅度提高了效率。
实际运行结果:
尝试 1 次猜中的有 995 轮
尝试 2 次猜中的有 1971 轮
尝试 3 次猜中的有 3706 轮
尝试 4 次猜中的有 6335 轮
尝试 5 次猜中的有 9883 轮
尝试 6 次猜中的有 13085 轮
尝试 7 次猜中的有 15042 轮
尝试 8 次猜中的有 14567 轮
尝试 9 次猜中的有 12186 轮
尝试 10 次猜中的有 9199 轮
尝试 11 次猜中的有 6117 轮
尝试 12 次猜中的有 3587 轮
尝试 13 次猜中的有 1877 轮
尝试 14 次猜中的有 839 轮
尝试 15 次猜中的有 381 轮
尝试 16 次猜中的有 148 轮
尝试 17 次猜中的有 55 轮
尝试 18 次猜中的有 21 轮
尝试 19 次猜中的有 3 轮
尝试 20 次猜中的有 3 轮
平均 7.488 次猜中
用时:1.8126s

他在后续的帖子给出了新的答案:
  1. import random

  2. #参数
  3. gameRound = 100000 #运行轮数
  4. bottom = 1 #猜数区间的下限
  5. top = 100 #猜数区间的上限

  6. #猜数并得出结果
  7. result = [] #用来储存结果
  8. for temp in range(gameRound):
  9.     attempt = 0 #初始化尝试次数
  10.     b = bottom
  11.     t = top
  12.     secret = random.randint(b,t) #生成随机数作为答案
  13.     while True:
  14.         guess = (b+t) // 2 #开猜
  15.         attempt += 1
  16.         if guess > secret: #猜大了
  17.             t = guess - 1
  18.         elif guess < secret: #猜小了
  19.             b = guess + 1
  20.         elif guess == secret : #猜对了
  21.             break
  22.     result.append(attempt) #储存结果

  23. #输出
  24. for n in range(min(result),max(result)+1):
  25.     if n in result:
  26.         print('尝试 %d 次猜中的有 %d 轮'%(n,result.count(n)))
  27. print('平均 %.3f 次猜中'%(sum(result)/len(result)))
复制代码


采用变化的2分法,效率大幅提高。
实际运行结果:
尝试 1 次猜中的有 947 轮
尝试 2 次猜中的有 1910 轮
尝试 3 次猜中的有 3939 轮
尝试 4 次猜中的有 8053 轮
尝试 5 次猜中的有 16396 轮
尝试 6 次猜中的有 31725 轮
尝试 7 次猜中的有 37030 轮
平均 5.803 次猜中
用时:0.4479s

小建议:用result贮存100000个数,占用内存过大,可改进。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 20:29:31 | 显示全部楼层
这是 @wei_Y 版主的答案。
  1. import random


  2. def ran_result():
  3.     # 生成结果。
  4.     for i in range(100000):
  5.         yield random.randint(1, 100)

  6. def run():
  7.     guess_result = []
  8.     def guess(init, i, init_max=100, init_min=1, count=1):
  9.         # 猜测。
  10.         if init == i:
  11.             guess_result.append(count)
  12.             return
  13.         elif init < i:
  14.             init_min = init
  15.         elif init > i:
  16.             init_max = init
  17.         # 纯随机。
  18.         init = random.randint(init_min, init_max)
  19.         guess(init, i, init_max=init_max, init_min=init_min, count=count+1)
  20.    
  21.     for x in ran_result():
  22.         guess(random.randint(1, 100), x)

  23.     return guess_result

  24. def count_result():
  25.     # 统计。
  26.     result = run()
  27.     # 效率低,可修改最大值。
  28.     count = [0 for i in range(max(result))]
  29.     for x in result:
  30.         count[x-1] += 1
  31.     for i in range(len(count)):
  32.         print("尝试 %d  次猜中的有 %d 轮" % (i+1, count[i]))
  33.     print("平均需要: %.5f次" % (sum(map(lambda x: x*int(count.index(x))+1, count)) / 100000))
  34.    
  35. count_result()
复制代码


也是用随机数作为猜数,并根据比较大小调整随机数的边界。
实际运行结果:
尝试 1  次猜中的有 1038 轮
尝试 2  次猜中的有 1889 轮
尝试 3  次猜中的有 3242 轮
尝试 4  次猜中的有 4943 轮
尝试 5  次猜中的有 6807 轮
尝试 6  次猜中的有 8348 轮
尝试 7  次猜中的有 9482 轮
尝试 8  次猜中的有 9911 轮
尝试 9  次猜中的有 9730 轮
尝试 10  次猜中的有 8977 轮
尝试 11  次猜中的有 7908 轮
尝试 12  次猜中的有 6614 轮
尝试 13  次猜中的有 5286 轮
尝试 14  次猜中的有 4259 轮
尝试 15  次猜中的有 3221 轮
尝试 16  次猜中的有 2469 轮
尝试 17  次猜中的有 1727 轮
尝试 18  次猜中的有 1333 轮
尝试 19  次猜中的有 904 轮
尝试 20  次猜中的有 603 轮
尝试 21  次猜中的有 427 轮
尝试 22  次猜中的有 278 轮
尝试 23  次猜中的有 184 轮
尝试 24  次猜中的有 144 轮
尝试 25  次猜中的有 95 轮
尝试 26  次猜中的有 59 轮
尝试 27  次猜中的有 46 轮
尝试 28  次猜中的有 24 轮
尝试 29  次猜中的有 15 轮
尝试 30  次猜中的有 13 轮
尝试 31  次猜中的有 9 轮
尝试 32  次猜中的有 4 轮
尝试 33  次猜中的有 6 轮
尝试 34  次猜中的有 1 轮
尝试 35  次猜中的有 1 轮
尝试 36  次猜中的有 0 轮
尝试 37  次猜中的有 1 轮
尝试 38  次猜中的有 0 轮
尝试 39  次猜中的有 1 轮
尝试 40  次猜中的有 1 轮
平均需要: 8.36781次
用时:2.1650s
@wei_Y 设计了多个函数,是整个程序更易调整和修改,增强了可读性。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 20:39:10 | 显示全部楼层
这是 @Lnan95 的答案。
她给出了2个答案。
采用2分法的。
  1. #二分法猜数字
  2. import random
  3. lis = {}
  4. for i in range(100000):
  5.     times = 0
  6.     y = random.randint(1,100)
  7.     x = random.randint(1,100)
  8.     rangex = [1,100]
  9.     result = 0
  10.     while True:
  11.         if x == y:
  12.             result += 1
  13.             lis.setdefault(result,0)
  14.             lis[result] += 1
  15.             break
  16.         elif x < y:
  17.             result += 1            
  18.             rangex[0] = x
  19.             x = (1/2*(x+rangex[1]+1))//1
  20.         elif  x > y:
  21.             result += 1
  22.             rangex[1] = x
  23.             x = (1/2*(x+rangex[0]))//1
  24. for item in lis.items():
  25.     print("尝试 %-1d 次猜中的有%6d" % item,"轮")
  26. #加权平均
  27. summary =sum(lis.values())
  28. sumvalues  = sum([key*lis[key] for key in lis.keys()])
  29. jq = sumvalues/summary
  30. print("平均 %5f 次猜中" % jq)
复制代码


实际运行结果:
尝试 1 次猜中的有  1000 轮
尝试 2 次猜中的有  1972 轮
尝试 3 次猜中的有  3918 轮
尝试 4 次猜中的有  7549 轮
尝试 5 次猜中的有 14206 轮
尝试 6 次猜中的有 24428 轮
尝试 7 次猜中的有 33587 轮
尝试 8 次猜中的有 13340 轮
平均 6.063210 次猜中
用时:0.9540s

采用普通方法:
  1. import random
  2. lis = {}
  3. for i in range(1000):
  4.     times = 0
  5.     y = random.randint(1,100)
  6.     x = random.randint(1,100)
  7.     rangex = [1,100]
  8.     result = 0
  9.     while True:
  10.         if x == y:
  11.             result += 1
  12.             lis.setdefault(result,0)
  13.             lis[result] += 1
  14.             break
  15.         elif x < y:
  16.             result += 1
  17.             rangex[0] = x + 1
  18.             x = random.randint(rangex[0],rangex[1])
  19.         elif  x > y:
  20.             result += 1
  21.             rangex[1] = x -1
  22.             x = random.randint(rangex[0],rangex[1])
  23. for item in lis.items():
  24.     print("尝试 %-2d 次猜中的有%6d" % item,"轮")
  25. #加权平均
  26. summary =sum(lis.values())
  27. sumvalues  = sum([key*lis[key] for key in lis.keys()])
  28. jq = sumvalues/summary
  29. print("平均 %5f 次猜中" % jq)
复制代码


总局数不对,我修改了一下。实际运行结果如下:
尝试 1  次猜中的有  1002 轮
尝试 2  次猜中的有  1994 轮
尝试 3  次猜中的有  3841 轮
尝试 4  次猜中的有  6411 轮
尝试 5  次猜中的有  9908 轮
尝试 6  次猜中的有 13362 轮
尝试 7  次猜中的有 14940 轮
尝试 8  次猜中的有 14422 轮
尝试 9  次猜中的有 12214 轮
尝试 10 次猜中的有  9061 轮
尝试 11 次猜中的有  5953 轮
尝试 12 次猜中的有  3570 轮
尝试 13 次猜中的有  1814 轮
尝试 14 次猜中的有   893 轮
尝试 15 次猜中的有   367 轮
尝试 16 次猜中的有   157 轮
尝试 17 次猜中的有    68 轮
尝试 18 次猜中的有    16 轮
尝试 19 次猜中的有     4 轮
尝试 20 次猜中的有     3 轮
平均 7.463650 次猜中
用时:1.877s

从两个对比可以看出2分法效率要高得多。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-2-1 20:53:52 | 显示全部楼层
楼主真是python大神。。我想用C写来着 不过发现C语言for到100000一运行就出了结果
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 20:59:11 | 显示全部楼层
这是 @USTC-ssj 是答案。
  1. import random
  2. secret = random.randint(1, 100)
  3. result = [0]*100
  4. for i in range(0,100000):
  5.     count = 0
  6.     guess = 0
  7.     num_max = 100
  8.     num_min = 0
  9.     while guess != secret:
  10.         if guess < secret:
  11.             num_min = guess
  12.             guess = random.randint(guess+1, num_max)
  13.         else:
  14.             num_max = guess
  15.             guess = random.randint(num_min+1, guess)
  16.         count += 1
  17.     result[count] += 1
  18. for j in range(1,100):
  19.     if result[j] != 0:
  20.         print('尝试 %2d 次猜中的有 %7d 轮'%(j, result[j]))
复制代码


也是使用随机数作为猜数并调整范围。程序很简练。
实际运行结果:
尝试  1 次猜中的有    1060 轮
尝试  2 次猜中的有    3760 轮
尝试  3 次猜中的有    7545 轮
尝试  4 次猜中的有   11286 轮
尝试  5 次猜中的有   13761 轮
尝试  6 次猜中的有   14342 轮
尝试  7 次猜中的有   13287 轮
尝试  8 次猜中的有   11224 轮
尝试  9 次猜中的有    8493 轮
尝试 10 次猜中的有    5807 轮
尝试 11 次猜中的有    3847 轮
尝试 12 次猜中的有    2369 轮
尝试 13 次猜中的有    1440 轮
尝试 14 次猜中的有     856 轮
尝试 15 次猜中的有     406 轮
尝试 16 次猜中的有     237 轮
尝试 17 次猜中的有     124 轮
尝试 18 次猜中的有      87 轮
尝试 19 次猜中的有      37 轮
尝试 20 次猜中的有      13 轮
尝试 21 次猜中的有       9 轮
尝试 22 次猜中的有       6 轮
尝试 23 次猜中的有       3 轮
尝试 24 次猜中的有       1 轮
用时:1.495s
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:02:24 | 显示全部楼层
本帖最后由 冬雪雪冬 于 2016-2-2 10:16 编辑

这是 @零度非安全 的答案。
  1. import random
  2. TryCount = [] #首先设一个空列表,用来放尝试的次数
  3. Sumnumber = 0 #用来存放所有轮尝试的次数

  4. def BinarySearch(answer,number): #定义一个函数,用来记录每轮猜测的次数
  5.     count = 0 #统计尝试的次数
  6.     low = 1
  7.     height = 100
  8.     while low < height: #利用折半查找法进行查找,折半查找的效率更高些
  9.         count += 1 #每次进行判断完count的次数自增1
  10.         number = (low + height) // 2
  11.         if number == answer:
  12.             break #若相等,则break终止循环并将count值返回
  13.         elif number < answer:
  14.             low = number + 1 #若小于,则在右半部分查找
  15.         else:
  16.             height = number - 1 #若大于,则在左半部分查找
  17.     return count

  18. for i in range(1,100001): #题目要求进行100000轮猜测游戏
  19.     number = 0
  20.     answer = random.randint(1,100) #在1~100之间取随机数
  21.     TryCount.append(BinarySearch(answer,number)) #调用BinarySearch()函数,并将返回值依次压入列表中

  22. for j in range(1,10): #经过多次测试,每次都是10次之内
  23.     while j in TryCount:
  24.         Sumnumber += j * TryCount.count(j)
  25.         print('尝试%d次猜中的有%5d轮'%(j,TryCount.count(j)))
  26.         break

  27. print('平均%.3f次猜中'%(Sumnumber/100000))
复制代码


也是采用2分法。写了详尽的注释。
有个小BUG,作者后来也注意到了,就是 while low < height 应改为 while low <= height,这样就得到了预期的答案了。其实while循环有两处跳出循环的地方,这容易出现小错误,我认为改为 while True 可能更好。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:11:22 | 显示全部楼层
这是 @落殇飞羽 的答案:
  1. #取得中位数
  2. def two_split(first, last):

  3.     mid = (first + last) // 2

  4.     return mid
  5.    



  6.   
  7. def compare(answer, guess, count1, count2, first1, last1):

  8.     #得到每轮猜中的次数,并放入列表
  9.     if guess == answer:
  10.         count1 += 1
  11.         #print(count2)
  12.         list2.append(count2)
  13.         
  14.         
  15.         
  16.         
  17.     #传入两个交换变量first1,last1以保存上一轮的列表中间数
  18.     elif guess > answer:
  19.         count2 += 1
  20.         if first1 == 0:
  21.             first1 = first
  22.             last1 = guess
  23.         else:
  24.             first1 = first1
  25.             last1 = guess
  26.             

  27.            
  28.         guess = two_split(first1, last1)
  29.         #print(guess)
  30.         compare(answer, guess, count1, count2, first1, last1)

  31.     else:
  32.         count2 += 1
  33.         if last1 == 0:
  34.             first1 = guess
  35.             last1 = last
  36.         else:
  37.             first1 = guess
  38.             last1 = last1


  39.         guess = two_split(first1, last1)
  40.         #print(guess)
  41.         compare(answer, guess, count1, count2, first1, last1)

  42.    

  43. import random

  44. sum1 = sum0 = 0
  45. i = 0
  46. first = 1
  47. last = 100

  48. first1 = 0
  49. last1 = 0

  50. count1 = 0 #记录一轮猜中的次数
  51. count2 = 1 #记录猜中的轮数



  52. list1 = [1,100]
  53. global list2
  54. list2 = []


  55. dic1 = {}

  56. while i < 100000:

  57.    
  58.     answer = random.randint(1,100)
  59.     if answer in list1:
  60.         guess = random.randint(1,2)
  61.         list2.append(guess)
  62.         #print(answer, guess)
  63.     else:
  64.         guess = two_split(first, last)
  65.         #print(answer, guess)
  66.         compare(answer, guess, count1, count2, first1, last1)
  67.     i += 1


  68. #把次数和轮数对应起来
  69. for each_1 in list2:
  70.    
  71.     if each_1 not in dic1:
  72.         dic1[each_1] = 1
  73.     else:
  74.         dic1[each_1] += 1
  75.         
  76. #print(list2)
  77. #按照key的从小到大排列输出次数与对应轮数
  78. list3 = list(dic1)
  79. list3.sort()

  80. for each_2 in list3:
  81.     print('尝试%d次实验猜对的有%d轮'%(each_2, dic1[each_2]))
  82.     sum0 = each_2 * dic1[each_2]
  83.     sum1 += int(sum0)

  84. print('平均%f次猜中'%(sum1/100000))
  85.    
复制代码


也是采用2分法。并使用了函数。
实际运行结果:
尝试1次实验猜对的有1991轮
尝试2次实验猜对的有2980轮
尝试3次实验猜对的有3996轮
尝试4次实验猜对的有8040轮
尝试5次实验猜对的有16034轮
尝试6次实验猜对的有32101轮
尝试7次实验猜对的有34858轮
平均5.688810次猜中
用时:0.5527s
这它的第二个程序。
  1. import random

  2. answer = random.randint(1,100)

  3. count = 0

  4. count1 = 0 #count1统计每一轮出现所有猜对的次数
  5. count2 = 1 #count2统计每轮猜对之前所实验的次数
  6. count3 = 1 #count3统计实验次数相等的轮数
  7. count4 = 0 #count4统计所有猜对的轮数
  8. count5 = 0 #count5统计所有猜的次数之和

  9. list1 = []#列表放置10000个所猜的数
  10. list2 = []#列表放置每次猜中之前的次数
  11. list3 = []#列表放置排序后的key值


  12. #形成一个100000所猜数的列表
  13. while count < 100000:
  14.     number = random.randint(1,100)
  15.     list1.append(number)
  16.     count += 1

  17. #将实验次数与猜中的轮数对应放入一个字典
  18. dic1 = {}

  19. i = 0
  20. while i < 100000:
  21.     if list1[i] == answer:
  22.         
  23.         count4 += 1
  24.         count1 += 1
  25.         count5 += count2
  26.         list2.append(count2)
  27.         count1 = 0
  28.         count2 = 0
  29.         
  30.     else:
  31.         count2 += 1
  32.     i += 1

  33. for each_1 in list2:
  34.     if each_1 not in dic1:
  35.         dic1[each_1] = 1
  36.         
  37.     else:
  38.         count3 += 1
  39.         dic1[each_1] = count3


  40. #按照key的从小到大排列输出次数与对应轮数
  41. list3 = list(dic1)
  42. list3.sort()

  43. for each_2 in list3:
  44.     print('尝试%d次实验猜对的有%d轮'%(each_2, dic1[each_2]))



  45. print('共猜对%d轮'%count4)
  46. if count4 != 0:
  47.     print('平均每轮猜中需要%d次'%(count5/count4))

  48. #print(list1)
  49. print(answer)
复制代码

这个我没太看懂,不过实际运行效果不理想。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:19:23 | 显示全部楼层
这是 @shuofxz 的第一个程序。
  1. import random
  2. N = 0
  3. guess = 0
  4. G1 = G2 = G3 = G4 = G5 = G6 = G7 = G8 = G9 = 0
  5. SUM = 0

  6. while N < 100000:
  7.     AAA = random.randint(1,10)
  8.     N += 1
  9.     i =0
  10.    
  11.     while guess != AAA:
  12.         SUM += 1
  13.         i += 1
  14.         guess = random.randint(1,10)
  15.         
  16.     if i == 1:
  17.         G1 += 1
  18.         
  19.     elif i == 2:
  20.         G2 += 1
  21.         
  22.     elif i == 3:
  23.         G3 += 1
  24.         
  25.     elif i == 4:
  26.         G4 += 1
  27.         
  28.     elif i == 5:
  29.         G5 += 1
  30.         
  31.     elif i == 6:
  32.         G6 += 1
  33.         
  34.     elif i == 7:
  35.         G7 += 1
  36.         
  37.     elif i == 8:
  38.         G8 += 1
  39.         
  40.     elif i == 9:
  41.         G9 += 1

  42. print('尝试1次猜中的有', G1, '轮')
  43. print('尝试2次猜中的有', G2, '轮')
  44. print('尝试3次猜中的有', G3, '轮')
  45. print('尝试4次猜中的有', G4, '轮')
  46. print('尝试5次猜中的有', G5, '轮')
  47. print('尝试6次猜中的有', G6, '轮')
  48. print('尝试7次猜中的有', G7, '轮')
  49. print('尝试8次猜中的有', G8, '轮')
  50. print('尝试9次猜中的有', G9, '轮')

  51. print('平均', round(SUM/100000, 3), '次猜中')
复制代码

也是用随机数作为猜数。
实际运行结果:
尝试1次猜中的有 8973 轮
尝试2次猜中的有 8158 轮
尝试3次猜中的有 7293 轮
尝试4次猜中的有 6585 轮
尝试5次猜中的有 5935 轮
尝试6次猜中的有 5256 轮
尝试7次猜中的有 4798 轮
尝试8次猜中的有 4317 轮
尝试9次猜中的有 3951 轮
平均 8.989 次猜中
用时:1.973s

第二个程序。
  1. import random
  2. SUM = 0
  3. result = [0,0,0,0,0,0,0,0,0,0]
  4. N = 0

  5. while N < 100001:
  6.     N += 1
  7.     AAA = random.randint(1,100)
  8.     i =0
  9.     MIN = 1
  10.     MAX = 100
  11.    
  12.     while (MIN+MAX)//2 != AAA:
  13.         SUM += 1
  14.         i += 1
  15.         if (MIN+MAX)//2 < AAA:
  16.             MIN = (MIN+MAX)//2
  17.         else:
  18.             MAX = (MIN+MAX)//2
  19.     result[i] += 1

  20.         
  21. for i in range(0,10):
  22.     print('尝试%d次猜中的有 %3d 轮'%(i+1,result[i]))

  23. print('平均', round(SUM/100000, 3), '次猜中')
复制代码

采用2分法,但有时会死循环,需修改。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:21:50 | 显示全部楼层
这是 @房间里的大象 的答案。
  1. import random
  2. x=random.randint(1,100)
  3. n=100000
  4. a=0
  5. while n:
  6.         import random
  7.         y=random.randint(1,100)
  8.         if x==y:
  9.                 a=a+1
  10.         n=n-1
  11. print ('尝试1次猜测的有  '+a' 轮')
复制代码

也是用随机数作为猜数。可惜程序没有完成,建议参考其他人的答案自己再做一遍。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:26:16 | 显示全部楼层
这是 @FDMa 的答案。
  1. def guess(sre = 10):
  2.         time = 0
  3.         low = 0
  4.         high = 100
  5.         ges = (low + high) // 2
  6.         while ges != sre:
  7.                 if ges == 99:
  8.                         ges = 100
  9.                 elif ges > sre:
  10.                         high = ges
  11.                         ges = (low + ges) // 2
  12.                 else:
  13.                         low = ges
  14.                         ges = (high + ges) // 2
  15.                 time += 1
  16.         return time

  17. result_time = [0] * 8
  18. for i in range(100000):
  19.     sre = random.randint(1,100)
  20.     result_time[guess(sre)] += 1
  21. out = '''尝试 1 次猜中的有 {num1} 轮
  22. 尝试 2 次猜中的有 {num2} 轮
  23. 尝试 3 次猜中的有 {num3} 轮
  24. 尝试 4 次猜中的有 {num4} 轮
  25. 尝试 5 次猜中的有 {num5} 轮
  26. 尝试 6 次猜中的有 {num6} 轮
  27. 尝试 7 次猜中的有 {num7} 轮
  28. 尝试 8 次猜中的有 {num8} 轮
  29. 平均 {avg} 次猜中'''.format(num1=result_time[0], num2=result_time[1], num3=result_time[2], num4=result_time[3],
  30.                        num5=result_time[4], num6=result_time[5], num7=result_time[6], num8=result_time[7],
  31.                        avg=round(sum((i[0]+1)*i[1] for i in enumerate(result_time))/100000 , 3))
  32. print(out)
复制代码

也是2分法,比较巧妙的是加入 if ges == 99: ges = 100避免死循环。比较遗憾的是没有 import random语句。
实际运行结果:
尝试 1 次猜中的有 909 轮
尝试 2 次猜中的有 2029 轮
尝试 3 次猜中的有 4019 轮
尝试 4 次猜中的有 8058 轮
尝试 5 次猜中的有 16218 轮
尝试 6 次猜中的有 31851 轮
尝试 7 次猜中的有 35947 轮
尝试 8 次猜中的有 969 轮
平均 5.808 次猜中
用时:0.4063s
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:27:35 | 显示全部楼层
本帖最后由 冬雪雪冬 于 2016-2-1 21:29 编辑

这是 @不爱穿内裤 的答案。
  1. import random as r

  2. def one_round():
  3.     '''
  4.     输出一个数:计算机猜中需要尝试的次数
  5.     '''
  6.     ans = r.randint(0, 100)
  7.     guess = r.randint(0, 100)
  8.     try_time = 0

  9.     while 1:
  10.         try_time += 1
  11.         
  12.         if guess == ans:
  13.             return try_time
  14.             
  15.         elif guess > ans:
  16.             guess = r.randint(ans, guess)
  17.         
  18.         elif guess < ans:
  19.             guess = r.randint(guess, ans)
  20.            
  21. def computer_play_game():
  22.     d = dict()

  23.     for i in range(100000):
  24.         try_time = one_round()
  25.         try:
  26.             d[try_time] += 1
  27.         except:
  28.             d[try_time] = 1
  29.             
  30.     for key in d:
  31.         print('小机机尝试了 %d 次猜中的有 %d 轮' %(key, d[key]))
复制代码


也是采用随机数作为猜数,但很遗憾光有函数没有主程序。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:31:44 | 显示全部楼层
这是 @kunaiai 的答案。
  1. import random
  2. secret = random.randint(1,100)
  3. time = 1
  4. time1 = 0
  5. res = []
  6. while time <= 100000:
  7.     guess = random.randint(1,100)
  8.     time1 += 1
  9.     if guess == secret:
  10.         res.append(time1);
  11.         time1 = 0
  12.         secret = random.randint(1,100)
  13.      
  14.     time += 1

  15. allRes = 0
  16. for i in res:
  17.     allRes += i

  18. count = len(res)
  19. print('共猜中%d,平均%.3f轮猜中'%(count,allRes/count))
复制代码


也是随机数作为猜数,但并没有得到完全符合题意的结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:34:48 | 显示全部楼层
这是 @swsfly 的答案。
  1. import random
  2. secret = random.randint(1,100)
  3. count1 = count2 = count3 = count4 = count5 = count6 = count7 = count8 = count9 =0
  4. for i in range (100000):
  5.     temp1 = random.randint(1,100)
  6.     guess1 = int(temp1)
  7.     if guess1 == secret:
  8.         count1 =count1 +1
  9.     else:
  10.         temp2 = random.randint(1,100)
  11.         guess2 = int(temp2)
  12.         if guess2 == secret:
  13.             count2 = count2 + 1
  14.         else:
  15.             temp3 = random.randint(1,100)
  16.             guess3 = int(temp3)
  17.             if guess3 == secret:
  18.                 count3 = count3 + 1
  19.             else:
  20.                 temp4 = random.randint(1,100)
  21.                 guess4 = int(temp4)
  22.                 if guess4 == secret:
  23.                     count4 = count4 + 1
  24.                 else:
  25.                     temp5 = random.randint(1,100)
  26.                     guess5 = int(temp5)
  27.                     if guess5 == secret:
  28.                         count5 = count5 + 1
  29.                     else:
  30.                         temp6 = random.randint(1,100)
  31.                         guess6 = int(temp6)
  32.                         if guess6 == secret:
  33.                             count6 = count6 + 1
  34.                         else:
  35.                             temp7 = random.randint(1,100)
  36.                             guess7 = int(temp7)
  37.                             if guess7 == secret:
  38.                                 count7 = count7 + 1
  39.                             else:
  40.                                  temp8 = random.randint(1,100)
  41.                                  guess8 = int(temp8)
  42.                                  if guess8 == secret:
  43.                                       count8 = count8 + 1
  44.                                  else:
  45.                                       temp9 = random.randint(1,100)
  46.                                       guess9 = int(temp9)
  47.                                       if guess9 == secret:
  48.                                          count9 = count9 + 1

  49. a=100000/(count1+count2+count3+count4+count5+count6+count7+count8+count9)
  50. print("尝试1次猜中的有 ",count1,'轮')
  51. print("尝试2次猜中的有 ",count2,'轮')
  52. print("尝试3次猜中的有 ",count3,'轮')
  53. print("尝试4次猜中的有 ",count4,'轮')
  54. print("尝试5次猜中的有 ",count5,'轮')
  55. print("尝试6次猜中的有 ",count6,'轮')
  56. print("尝试7次猜中的有 ",count7,'轮')
  57. print("尝试8次猜中的有 ",count8,'轮')
  58. print("尝试9次猜中的有 ",count9,'轮')
  59. print("平均",a,'次猜中')
复制代码

也是采用随机数作为猜数,并使用了多级的if语句,但很遗憾只写到temp9没有给出全部答案。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 21:55:46 | 显示全部楼层
黑龍 发表于 2016-2-1 20:53
楼主真是python大神。。我想用C写来着 不过发现C语言for到100000一运行就出了结果

黑龍 版主,我还不会C语言,以后有机会向你学习。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-2-1 22:02:39 | 显示全部楼层
看来运行的速度也是个大学问啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 22:04:53 | 显示全部楼层
Lnan95 发表于 2016-2-1 22:02
看来运行的速度也是个大学问啊

是的,算法优化可以使用最少的步骤最短的时间完成任务。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-2-1 22:29:24 | 显示全部楼层
发现我的第9行忘记用地板除了,影响了不少效率,优化程序中。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-1 22:39:21 | 显示全部楼层
zooo 发表于 2016-2-1 22:29
发现我的第9行忘记用地板除了,影响了不少效率,优化程序中。。。

嗯,就是在不断的学习,不断的挑战自我中提高的。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-26 03:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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