鱼C论坛

 找回密码
 立即注册
查看: 1323|回复: 26

[技术交流] Python:每日一题 137

[复制链接]
最佳答案
853 
发表于 2018-1-11 08:55:43 | 显示全部楼层 |阅读模式

马上注册加入鱼C,享用更多服务吧^_^

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

x
本帖最后由 冬雪雪冬 于 2018-1-13 21:10 编辑

我们的玩法做了一下改变:

1. 楼主不再提供答案。
2. 请大家先独立思考”,再参考其他鱼油的解答,这样才有助于自己编程水平的提高。
3. 鼓励大家积极答题,奖励的期限为出题后24小时内。
4. 根据答案的质量给予1~3鱼币的奖励。

题目:
0.jpg

小球从最高处逐层落下,每个节点都有可能向左下或右下方向下落,且几率相同,各占50%,共有10万个小球依次落下,当都从第0层落至第9层时图中0~9的10个位置各有多少个小球(这里为了与python一致,都是从0开始的)。
由于是用随机数测算的,所以大家的结果不会相同,主要看一个趋势。

本帖被以下淘专辑推荐:

最佳答案
13 
发表于 2018-1-11 09:26:48 | 显示全部楼层
本帖最后由 shigure_takimi 于 2018-1-15 12:28 编辑
  1. def f(n):
  2.     if n == 0:
  3.         return [1]
  4.     elif n == 1:
  5.         return [0.5, 0.5] # 1/(2**1)
  6.     elif n > 1:
  7.         a = [1/(2**n),1/(2**n)]
  8.         b = f(n-1)
  9.         for i in range(1, n):
  10.             a.insert(i, (b[i-1]+b[i])/2)
  11.         return a


  12. probability = f(9)
  13. for i, p in enumerate(probability):
  14.     print('Position',i,'-->',int(100000*p+0.5))
  15.    
  16. ##    Position 0 --> 195
  17. ##    Position 1 --> 1758
  18. ##    Position 2 --> 7031
  19. ##    Position 3 --> 16406
  20. ##    Position 4 --> 24609
  21. ##    Position 5 --> 24609
  22. ##    Position 6 --> 16406
  23. ##    Position 7 --> 7031
  24. ##    Position 8 --> 1758
  25. ##    Position 9 --> 195

  26. #  2018-01-15 12:26更新,看了别人的代码,明白了怎么搞随机掉落。random.random()<0.5掉在左边,否则掉在右边。
  27. #  试着写了下,结果符合预期。
  28. import random
  29. def drop():
  30.     a = [[0 for i in range(10)] for j in range(10)]
  31.     for i in range(10):
  32.         if i == 0:
  33.             index = 0
  34.             a[i][index] = 1
  35.         elif i > 0:
  36.             index = a[i-1].index(1) if random.random() < 0.5 else a[i-1].index(1)+1
  37.             a[i][index] = 1
  38.     return a[9].index(1)

  39. result = {}
  40. for i in range(10):
  41.     result[i] = 0

  42. n = 100000
  43. for i in range(n):
  44.     result[drop()] += 1

  45. for k in result:
  46.     print(k, '-->', result[k])

  47. ##    0 --> 204
  48. ##    1 --> 1680
  49. ##    2 --> 7027
  50. ##    3 --> 16255
  51. ##    4 --> 24737
  52. ##    5 --> 24709
  53. ##    6 --> 16488
  54. ##    7 --> 7008
  55. ##    8 --> 1680
  56. ##    9 --> 212
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
65 
发表于 2018-1-11 09:38:08 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2018-1-11 09:51 编辑

模拟10万次小球滚落的结果
[206, 1751, 7050, 16500, 24807, 24407, 16317, 7073, 1700, 189]
  1. class balls: #定义类
  2.         def __init__(self): #初始化测试环境
  3.                 self.matrix = [[0]*i for i in range(1,11)]
  4.                 self.matrix[0][0] = 1 #把小球放在最顶上
  5.         def roll(self,row,col): #定义一次小球从row行滚落到row+1行的动作
  6.                 if row>=9: return
  7.                 import random
  8.                 if random.random()>=0.5:
  9.                         self.matrix[row][col] = 0
  10.                         self.matrix[row+1][col+1] = 1
  11.                 else:
  12.                         self.matrix[row][col] = 0
  13.                         self.matrix[row+1][col] = 1
  14.         def start(self): #定义小球从顶层滚落到底层的动作
  15.                 for r in range(10):
  16.                         for c in range(r+1):
  17.                                 if self.matrix[r][c]==1:
  18.                                         self.roll(r,c)
  19.                                         break
  20.                 return sum(k*v for k,v in enumerate(self.matrix[9])) #返回小球在最底层的哪一格
  21. result = [0]*10 #存放结果
  22. for repeat in range(100000): #重复10万次
  23.         test = balls()
  24.         result[test.start()] += 1
  25. print(result)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
7 
发表于 2018-1-11 10:00:54 | 显示全部楼层
  1. result = [0 for _ in range(10)]
  2. for _ in range(100000):
  3.     temp = 0
  4.     for i in range(9):
  5.         n = random.randint(0, 1)
  6.         temp += n
  7.     result[temp] += 1
  8. print(result)
复制代码

输出是:
  1. [198, 1665, 7066, 16466, 24626, 24444, 16412, 7215, 1692, 216]
复制代码


多次都是集中在4,5,因为Python的random模块默认是均匀分布,所以也可以想到中间的数值大两边下

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
0 
发表于 2018-1-11 10:32:47 | 显示全部楼层
  1. import random
  2. layer_list = [ ]
  3. for i in range(0,9):
  4.         temp = list(range(0,i+2))
  5.         layer_list.append(temp)
  6. print(layer_list)

  7. num = list(range(0,10))
  8. out = [0] * 10
  9. for x in range(0,100000):
  10.         layer = [0] * 9         #一个小球落下的结果
  11.         layer[0] = random.randint(0,1)
  12.         for i in range(0,8) :
  13.                 for j in range(0,i+2):
  14.                         if layer[i] == layer_list[i][j]:
  15.                                 layer[i+1] = random.randint(j,j+1)
  16.         for y in range(0,10):      #输出结果
  17.                 if layer[8] == num[y]:
  18.                         out[y] += 1
  19. print(out)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
3 
发表于 2018-1-11 11:14:38 | 显示全部楼层
本帖最后由 776667 于 2018-1-11 17:13 编辑
  1. from random import randint

  2. def fun137(x):
  3.     result = {0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0}
  4.     for times in range(x):
  5.         hole = 0
  6.         for i in range(9):
  7.             if randint(0,1) == 1:
  8.                 hole += 1
  9.         result[hole] += 1
  10.     return result

  11. if __name__ == '__main__':
  12.     print(fun137(100000))
复制代码

{0: 224, 1: 1790, 2: 6897, 3: 16358, 4: 24622, 5: 24753, 6: 16423, 7: 6974, 8: 1751, 9: 208}
{0: 189, 1: 1718, 2: 7046, 3: 16608, 4: 24345, 5: 24643, 6: 16507, 7: 6956, 8: 1769, 9: 219}
{0: 180, 1: 1700, 2: 7106, 3: 16365, 4: 24617, 5: 24708, 6: 16400, 7: 7027, 8: 1725, 9: 172}
{0: 189, 1: 1719, 2: 6916, 3: 16421, 4: 24604, 5: 24726, 6: 16416, 7: 7072, 8: 1764, 9: 173}
{0: 220, 1: 1773, 2: 6990, 3: 16272, 4: 24659, 5: 24591, 6: 16525, 7: 7040, 8: 1722, 9: 208}
{0: 187, 1: 1759, 2: 6942, 3: 16450, 4: 24865, 5: 24324, 6: 16457, 7: 7036, 8: 1776, 9: 204}
{0: 172, 1: 1738, 2: 7012, 3: 16445, 4: 24551, 5: 24713, 6: 16463, 7: 6946, 8: 1768, 9: 192}
{0: 184, 1: 1789, 2: 7057, 3: 16403, 4: 24435, 5: 24776, 6: 16250, 7: 7120, 8: 1801, 9: 185}
{0: 191, 1: 1779, 2: 7024, 3: 16348, 4: 24784, 5: 24610, 6: 16195, 7: 7119, 8: 1740, 9: 210}
{0: 200, 1: 1742, 2: 6891, 3: 16534, 4: 24599, 5: 24800, 6: 16262, 7: 7063, 8: 1719, 9: 190}

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
12 
发表于 2018-1-11 11:17:32 | 显示全部楼层
import random
print("Let's play a ball game")
ball_num = int(input('ball number:'))
list1=[-1,1]

h0=0
h1=0
h2=0
h3=0
h4=0
h5=0
h6=0
h7=0
h8=0
h9=0
for x in range(1,ball_num):
        n=0
        for i in range(1,10):
                hole=random.choice(list1)
                n=n+hole
        if n==-9:
                h0+=1
        elif n==-7:
                h1+=1
        elif n==-5:
                h2+=1
        elif n==-3:
                h3+=1
        elif n==-1:
                h4+=1
        elif n==1:
                h5+=1
        elif n==3:
                h6+=1
        elif n==5:
                h7+=1
        elif n==7:
                h8+=1
        elif n==9:
                h9+=1
results=[h0,h1,h2,h3,h4,h5,h6,h7,h8,h9]
print(results)

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
20 
发表于 2018-1-11 12:05:06 | 显示全部楼层
本帖最后由 久疤K 于 2018-1-11 12:11 编辑
  1. import random as r

  2. # 定义一个球从上一层到下一层的随机选择
  3. def fun(n):
  4.     return r.choice([True,False]) + n

  5. # 定义一个球从最顶端到最低端的选择
  6. def one_loop(n) :
  7.     now = 0
  8.     for i in range(n-1):
  9.         now = fun(now)
  10.     return now

  11. # 定义count个球从最顶端到最低端floor层的选择
  12. def loop(floor, count):   
  13.     mdict = {}.fromkeys(range(floor), 0)

  14.     for i in range( count ):
  15.         mdict[ one_loop(floor) ] += 1
  16.         
  17.     return mdict

  18. # 主函数测试
  19. def main():
  20.     floor = 10
  21.     count = 100000

  22.     mdict = loop(floor, count)

  23.     for key in mdict:
  24.         print(key, mdict[key])

  25.     print("result: ", sum(mdict.values()) == count)
  26.         

  27. if __name__ == "__main__":
  28.     main()
复制代码


结果:
  1. 0 182
  2. 1 1794
  3. 2 6899
  4. 3 16522
  5. 4 24497
  6. 5 24844
  7. 6 16272
  8. 7 7047
  9. 8 1737
  10. 9 206
  11. result:  True
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
0 
发表于 2018-1-11 12:21:37 | 显示全部楼层
  1. import random
  2. number = [x for x in range (19)] #最后需要减去对应的数值,放大两倍来算
  3. def everytime ():
  4.     n = 9
  5.     x = 9
  6.     def  func ():
  7.         nonlocal x,n
  8.         while n :
  9.             x = x+ random.choice ((1,-1))
  10.             n =n - 1
  11.             return (func())
  12.     func()
  13.     number [x] +=1
  14. for i in range (100000):
  15.     everytime ()
  16. numbers = [y-x for x,y in enumerate (number)] #减去对应值
  17. finnumbers = [x for i,x in enumerate (numbers) if i%2 == 0] #取出最终存放数据
  18. print (numbers,'\n最终答案\n',finnumbers)
复制代码

捕获.PNG

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
0 
发表于 2018-1-11 13:31:10 | 显示全部楼层
  1. import random as r
  2. count=0   

  3. num=0
  4. i=0
  5. list1=[0,1,2,3,4,5,6,7,8,9]
  6. list2=[0,0,0,0,0,0,0,0,0,0]

  7. while count < 100000:
  8.     n=0
  9.     for i in range (10):
  10.         if i==0:
  11.             n=0
  12.         else:
  13.             n=r.randint(n,n+1)
  14.         
  15.         
  16.         
  17.    
  18.     list2[n]=list2[n]+1
  19.     count =count +1
  20. print(list2)   

  21.    
  22.         




复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
5 
发表于 2018-1-11 20:46:27 | 显示全部楼层
重复9次的伯努利试验,二项分布
每次0-1两种选择,均值是0.5,9次之后将所得加起来,就是最终位置
概率依次是C(0,9)*0.5**9, C(1,9)*0.5**9, C(2,9)*0.5**9, ..., C(9,9)*0.5**9
最终期望值就是E(x)= 9*0.5*100000  ,即sum(索引*个数)
  1. import random

  2. def fun(n=100000):
  3.     result = [0]*10
  4.     for i in range(n):
  5.         temp = 0
  6.         for j in range(9):
  7.             temp += random.choice([0, 1])
  8.         result[temp] += 1
  9.     return result
复制代码

画出来是这样的钟形曲线
  1. import matplotlib.pyplot as plt
  2. import numpy as np

  3. def fun2(n=100000):
  4.     a = np.random.randint(0, 2, (9, n))
  5.     b = np.add.reduce(a, 0)
  6.     n, bins, patches = plt.hist(b, 10, range=(-0.5, 9.5), label='Binomial')
  7.     plt.plot(range(0,10), n)
  8.     plt.xticks(np.arange(-1,10,1))
  9.     plt.legend()
  10.     plt.show()
复制代码
figure_1.png

评分

参与人数 2荣誉 +6 鱼币 +6 收起 理由
8306最硬 + 3 + 3
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
18 
发表于 2018-1-11 21:40:22 | 显示全部楼层
本帖最后由 8306最硬 于 2018-1-12 12:32 编辑
  1. import random

  2. def put_one_ball(layer):
  3.     return [True if random.randint(0,1) else False for i in range(layer)].count(True)

  4. def put_balls(num):
  5.     return [put_one_ball(9) for i in range(num)]

  6. balls = put_balls(100000)
  7. for i in range(10):
  8.     print(i,balls.count(i))
复制代码

结果表明,中产阶级的数目庞大

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
1 
发表于 2018-1-11 22:43:28 | 显示全部楼层
  1. from random import choice
  2. from time import perf_counter

  3. def random_drop(n):
  4.     tiers = []
  5.     for i in range(10):
  6.         tiers.append([0 for j in range(i + 1)])
  7.     tiers[0][0] = n
  8.     for i in range(9):
  9.         for j in range(len(tiers[i])):
  10.             if tiers[i][j]:
  11.                 for k in range(tiers[i][j]):
  12.                     tiers[i+1][choice([j, j+1])] += 1
  13.     return tiers[-1]


  14. if __name__ == '__main__':
  15.     start = perf_counter()
  16.     print(random_drop(100000))
  17.     stop = perf_counter()
  18.     print("time used:%f s" %(stop - start))
复制代码


结果:[182, 1804, 6889, 16440, 24706, 24728, 16387, 6911, 1761, 192]

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
0 
发表于 2018-1-12 08:42:23 | 显示全部楼层
本帖最后由 空巷无人故人叹 于 2018-1-12 08:47 编辑
  1. import random
  2. ball = 100000
  3. dict_ball = {0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0}
  4. probability = []
  5. def game():
  6.     b = 0
  7.     for i in range(0,9):
  8.         a = random.randint(0,1)
  9.         b = b + a
  10.     return b

  11. for i in range(0,ball+1):
  12.     c = game()
  13.     dict_ball[c] += 1

  14. for k in range(0,10):
  15.     print('编号为%d的位置有%d个球' %(k,dict_ball[k]))
  16.    
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
2 
发表于 2018-1-12 10:24:16 | 显示全部楼层
本帖最后由 aegis1417 于 2018-1-12 10:40 编辑

不太確定..機率不太好,是呈現類常態(高斯)分佈嗎?

  1. import random
  2. import matplotlib.pyplot as plt

  3. def num(x):
  4.     c=[]
  5.     y=[]
  6.     z=[i for i in range(1,10)]
  7.     for i in range(x):
  8.         a=1
  9.         for j in range(8):
  10.             b=random.randint(0,1)
  11.             a=a+b
  12.         c.append(a)
  13.     for x in range(1,10):
  14.         y.append(c.count(x))
  15.     print(z,y)
  16.     plt.plot(z, y)
  17.     plt.show()

  18. num(100000)
复制代码


[1, 2, 3, 4, 5, 6, 7, 8, 9] [376, 3130, 10962, 21784, 27491, 21868, 10813, 3197, 379]
every137.jpg

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 是呈高斯分布

查看全部评分

最佳答案
42 
发表于 2018-1-12 13:22:58 | 显示全部楼层
  1. from random import randint
  2. d = dict.fromkeys([x for x in range(10)], 0)

  3. def ball_fall():
  4.     ball = 0
  5.     for x in range(9):
  6.         choice = randint(0,1)
  7.         if choice == 1:
  8.             ball += 1
  9.     d[ball] += 1

  10. for x in range(100000):
  11.     ball_fall()

  12. print(d)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
2 
发表于 2018-1-12 15:15:00 | 显示全部楼层
几乎没怎么写过代码的人刚学习python,看到这个题目完全没有思路。就计算了一下各个位置的概率,欢迎批评指正。我也想学习一下正确的写法。

l1=[0.5, 0.5]
def cacu(list1):
        list2=list(range(len(list1)+1))
        for i in range(len(list1)+1):
                if i==0:
                        list2[i]=list1[i]*0.5
                elif i==len(list1):
                        list2[i]=list1[i-1]*0.5
                else:
                        list2[i]=(list1[i-1]+list1[i])*0.5
        return list2

l9=cacu(cacu(cacu(cacu(cacu(cacu(cacu(cacu(l1))))))))
count=[]
for i in l9:
        count.append(round(i*100000))
print("0~9位置的小球数量分别为:" + str(count))

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3

查看全部评分

最佳答案
2 
发表于 2018-1-12 19:13:42 | 显示全部楼层
这一题不太会啊,所以呢,我把所有可能性列出来了,共有1024种状况,每一种的概率都不一样,生产随机数看看在哪个范围再把它分配,程序如下:(感觉会被嘲笑,就不可以匿名嘛!)
import random
list0=[]
list1=[]
list2=[]
list3=[]
list4=[]
list5=[]
list6=[]
list7=[]
list8=[]
list9=[]

for i in range(1, 100000):
    temp = random.randint(1,1024)
    if temp == 1:
        list0.append(i)
    elif temp in range(2,12):
        list1.append(i)
    elif temp in range(12,57):
        list2.append(i)
    elif temp in range(57,177):
        list3.append(i)
    elif temp in range(177,387):
        list4.append(i)
    elif temp in range(387,639):
        list5.append(i)
    elif temp in range(639,849):
        list5.append(i)
    elif temp in range(850,969):
        list6.append(i)
    elif temp in range(969,1014):
        list7.append(i)
    elif temp in range(1014,1024):
        list8.append(i)
    else:
        list9.append(i)

print("在0号圈的数字有:",list0)
print("在1号圈的数字有:",list1)
print("在2号圈的数字有:",list2)
print("在3号圈的数字有:",list3)
print("在4号圈的数字有:",list4)
print("在5号圈的数字有:",list5)
print("在6号圈的数字有:",list6)
print("在7号圈的数字有:",list7)
print("在8号圈的数字有:",list8)
print("在9号圈的数字有:",list9)

点评

算法应该有误,我用len看了每个圈的数量,与大家的答案不相符  发表于 2018-1-13 21:27
最佳答案
13 
发表于 2018-1-13 21:30:45 | 显示全部楼层


我这个代码就是纯粹计算概率了,至于怎么模拟当时没有搞明白。
(现在也不是很明白,还在研究别人的代码。)
最佳答案
20 
发表于 2018-1-13 22:54:45 | 显示全部楼层

显然这不是模拟出来的,这是算概率后计算出来的,而且最终的球数目不对。
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

小甲鱼强烈推荐上一条 /1 下一条

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号 )

GMT+8, 2018-7-17 17:52

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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