鱼C论坛

 找回密码
 立即注册
查看: 8295|回复: 64

[技术交流] Python:每日一题 96(答题领鱼币)

[复制链接]
发表于 2017-9-8 23:15:48 | 显示全部楼层 |阅读模式

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

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

x
我们都知道微信红包,把一个红包随机分成n份,每人拿到的钱数不尽相同。
现在模拟这个算法,把100块钱,随机分成10份,为了简化每个人的钱数都是整数。
例如:
  1. 7
  2. 1
  3. 9
  4. 11
  5. 3
  6. 13
  7. 10
  8. 11
  9. 2
  10. 9
  11. 24
复制代码


我的解法:
游客,如果您要查看本帖隐藏内容请回复

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-9-8 23:47:16 | 显示全部楼层
  1. from random import randint
  2. n=100
  3. k=10
  4. while n:
  5.     if k:
  6.         hb = randint(1,n-k+1)
  7.         n -= hb
  8.         k -= 1
  9.         print("第%d个红包是%d元,红包剩余%d元" % (abs(k-10), hb, n))
复制代码


#运行结果
第1个红包是6元,红包剩余94元
第2个红包是5元,红包剩余89元
第3个红包是18元,红包剩余71元
第4个红包是26元,红包剩余45元
第5个红包是11元,红包剩余34元
第6个红包是29元,红包剩余5元
第7个红包是2元,红包剩余3元
第8个红包是1元,红包剩余2元
第9个红包是1元,红包剩余1元
第10个红包是1元,红包剩余0元

点评

红包的大小是递减的,最好考虑对前后的人都是公平的。  发表于 2017-9-9 11:55

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 01:05:50 | 显示全部楼层
  1. import random
  2. money = [0]*10
  3. while(100 != money[0] + money[1] + money[2] + money[3] + money[4] + money[5] + money[6] + money[7] + money[8] + money[9]):
  4.     for i in range(10):
  5.         money[i] = random.randint(1,50) #缺点:当randint第二个参数过大时,python会很慢,所以目前调成50,我微信抢红包从不过50...
  6. for i in money:
  7.     print(i)
复制代码

其中一个结果:
1
12
4
25
1
4
8
4
9
32

点评

反复凑100,效率的确很低  发表于 2017-9-9 11:56

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-9-9 01:23:15 | 显示全部楼层
  1. def hongbao(money,number):
  2.     import random
  3.     while money:
  4.         if number:
  5.             bb = random.randint(1,money - number +1)
  6.             print(bb)
  7.             money -= bb
  8.             number -= 1
  9. hongbao(100,10)
复制代码

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 10:02:34 From FishC Mobile | 显示全部楼层
import random
def hongbao(a,b):
    x=[]
    for i in range(b-1):
        c =random.randint(1,a-b+i)   
        a = a-c
        x.append(c)
    x.append(a)
    return(x)
a=100
b=10
h=hongbao(a,b)
print(h)
这是刚开始的想法 第一个随机拿 后面的人 挨个从剩下的随机拿 后来发现 后面拿的钱都很少 如果是分红包 显得不公平
import random
def hongbao1(a,b):
    x=[]
    y=[]
   
    for i in range(b-1):
        x.append(random.randint(1,b))         
    for i in x:      
        y.append(int(i/sum(x)*a))
    y.append(a-sum(y))
    return(y)
a=100
b=10
g=hongbao1(a,b)
print(g)
这是后来写的  先随机 生成9个数 然后 每个数除以 他们的和 最后一个人拿 零头(为了凑够100块) 虽然最后一个人不算公平 但谁叫他抢的慢呢
我觉得自己掌握的代码太少了 来看看大神都是怎么做的

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 10:16:30 From FishC Mobile | 显示全部楼层
楼主 思维强大
看楼上的  突然有个 想法 10个人  每次 随机发给一个人 一块钱  发100次   就完事了
import random
def hongbao2(a,b):
    x=[0]*b
    for i in range(a):
        x[random.randint(0,9)] += 1
    return(x)
g=hongbao2(a,b)
print(g)

点评

这个办法也挺好  发表于 2017-9-9 11:57

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 4 反对 0

使用道具 举报

发表于 2017-9-9 10:48:24 | 显示全部楼层
look  and study
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 11:46:34 | 显示全部楼层
  1. from random import randint
  2. def hongbao(money, size):
  3.     t = []
  4.     t.append(money)
  5.     for i in range(1,size+1): # size+1 为了最后一个红包不为0.
  6.         if i == size-1:
  7.             t.append(money - sum(t))
  8.         else:
  9.             t.append(max(t) - randint(1, max(t)-1))
  10.             t[t.index(max(t))] = max(t) - t[-1]
  11.     t.remove(0)
  12.     return t
复制代码

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 13:16:38 | 显示全部楼层
本帖最后由 solomonxian 于 2017-9-9 14:34 编辑

用正态分布吧,可能比较符合现实
标准差对应分散程度,按循环次数上取u-3σ>= 0下最大比较好,

但是如果分散一点貌似更好玩,取 u/2, 小数点保留1位好了
有 2.5% 概率出现负数,那就递归再来一遍,钱一定要比人数多大
  1. import random, math
  2. def fun(money, people):
  3.     lst = sorted(round(random.gauss(money//people, money//people//2),1) for _ in range(people))
  4.     temp = round(money - math.fsum(lst),1)
  5.    
  6.     num = sorted([(temp,0),(temp+0.1,-1)], key=lambda x :abs(x[0]))[0][1] # 因为精度是0.1
  7.     lst[num] = round(lst[num] + temp, 1)
  8.     random.shuffle(lst)
  9.     return fun(money, people) if sorted(lst)[0]<=0 else lst
复制代码

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-9-9 13:55:50 | 显示全部楼层
from random import randint

def hb(n):
    money =100
    k =1
    while n:
        person_money = randint(0,money)
        #为保证公平,设置范围且金额不能为0.否则重新随机
        if n>1:
            while person_money > money/(n-1) or person_money ==0:
                person_money = randint(0,money)
        
        else :
            person_money = money
            
        print('第%d个人的红包是%d元'%(k,person_money))
        money -= person_money
        n -=1
        k +=1
         
hb(10)

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 14:35:18 | 显示全部楼层
学习一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 15:06:10 From FishC Mobile | 显示全部楼层
微信红包的分配策略是随机数取1~剩余均值的2倍,倒数第二个人取1~剩余总数,最后一个人全收。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 18:08:20 | 显示全部楼层
  1. import random
  2. N=100
  3. num = 10
  4. while(N>1):
  5.    money = random.randint(1,N-num+1)
  6.    print(money)
  7.    N-=money
  8.    num-=1
  9. print(N)
复制代码

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 19:10:17 | 显示全部楼层
from random import randint as r

i=0
def f(n):
    global i
    while i<10:
        a=r(1,n-9+i)
        print(a)
        i+=1
        return f(n-a)
f(100)
————————————————
运行结果
58
3
10
23
1
1
1
1
1
1
>>>
===================== RESTART: D:\Python36-32\caogao.py =====================
56
15
7
5
2
10
1
1
1
2
>>>

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 22:50:02 | 显示全部楼层
本帖最后由 schweinfan 于 2017-9-9 22:51 编辑
  1. import random as r
  2. rest_money = 100
  3. rest_num = 10
  4. for i in range(1,10):
  5.     current = r.randint(1, rest_money - rest_num + 1)
  6.     print('第%d个红包,金额为%d元' % (i, current))
  7.     rest_num  -= 1
  8.     rest_money = rest_money - current
  9. print('第10个红包,金额为%d元,红包已抢完' % rest_money)
复制代码

输出为:
  1. 第1个红包,金额为16元
  2. 第2个红包,金额为10元
  3. 第3个红包,金额为33元
  4. 第4个红包,金额为13元
  5. 第5个红包,金额为9元
  6. 第6个红包,金额为5元
  7. 第7个红包,金额为3元
  8. 第8个红包,金额为3元
  9. 第9个红包,金额为4元
  10. 第10个红包,金额为4元,红包已抢完
复制代码

应该是符合题意的,但结果基本都是前面抢到的金额大。。所以还是微信的算法更合理吧

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-10 15:29:55 | 显示全部楼层
  1. from random import randint


  2. list1 = []
  3. for each in range(10):
  4.     list1.append(randint(1,101))

  5. total = sum(list1)

  6. for i in range(10):
  7.     list1[i] = int(100 * list1[i] / total + 0.5)
  8.    
  9. print(list1)
  10. print(sum(list1))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-11 00:07:23 | 显示全部楼层
没思路。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-11 15:48:33 | 显示全部楼层
6666666666666666
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-11 17:19:24 | 显示全部楼层
```python
import random

num = [random.random() for _ in range(10)]
summ = sum(num)
a=[]
for i in num:
    temp = i / summ * 100
    print('天了噜!发财了抽中%s元'%int(temp+0.5))

```

评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-11 21:12:07 | 显示全部楼层
100
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-28 17:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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