十几行完成大学中宿舍的特色餐分配问题

Hello! 这里是GIS宇宙,最近在当志愿者。

最近这几天,上海疫情有所好转,学校为了给我们更大的自由度,新增特色餐券发到每个楼宇,问题在于特色餐有限,如何楼内分配是一个问题。部分楼是放回抽签,这个方法简单方便,问题就在于有些小倒霉蛋可能一次都抽不到。

因此我们采取不放回抽样,问题现有小程序没有这个功能,于是本宇宙就花了点时间写了个程序解决不放回抽样问题。

1 先说一下基本思路

  • 第一次初始化,生成随机数即可,并保存抽中和没抽中的人员名单
  • 第二次优先在没抽中名单里抽,如果没抽够则将不再这个名单内的人里抽
  • 由此往复

什么?太绕了,听不懂?上流程图:

当剩余人数不足以满足特色餐份数的时候,这一次就是完成了所有人都吃上的任务,然后开启下次的轮回。

2 代码环节

2.1 初始化

第一次的话没有剩余人数,所以整个随机数抽人就行,然后保存一下抽中的和这次没抽中的人数,供下一次使用。

totalArr = pd.read_excel(listDir).values
selectNum = random.sample(range(0, len(totalArr)),dinnerNum)
theChosen = pd.DataFrame(totalArr[selectNum])
theLeft = pd.DataFrame(np.delete(totalArr, selectNum, axis=0))

totalArr是每层的人员名单,根据特色餐份数,生成多少个随机数,然后根据数组索引取值就行,然后保存为excel
名单格式:

id宿舍姓名
06xx张三

2.2 下一次计算

首先判断一下剩余人数是否小于特色餐,是的话,先把剩余人数的id获取,然后再在排除剩余人数里抽取,获取id整合到一个selectNum数组里,然后用selectNum获取人员就行。

selectNum = theOldLeft['id'].values.tolist()
leftDinnerNum = dinnerNum - len(selectNum)  #计算还需要抽多少个人
#排除了少于特色餐数的人的数组
totalArr2 = np.delete(totalArr, selectNum, axis=0)
randomNum2 = random.sample(range(0, len(totalArr2)),leftDinnerNum)
for i in  randomNum2:
  selectNum.append(totalArr2[i][0])
        
theChosen = pd.DataFrame(totalArr[selectNum])
theLeft = pd.DataFrame(np.delete(totalArr, selectNum, axis=0))

如果是大于等于特色餐的话,就直接在剩余人数里面选就行。

selectNum = random.sample(range(0, len(theOldLeft)),dinnerNum)   
theChosen = pd.DataFrame(theOldLeft.values[selectNum])
theLeft = pd.DataFrame(np.delete(theOldLeft.values, selectNum, axis=0))

好了今天就分享到这里,疫情期间祝大家都能身体健康、平安喜乐~

GIS宇宙公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GIS_宇宙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值