英文:
Defining a function for demand pattern
问题
import random
def generate_cost(num_days):
cost = {}
shifts = [1, 2, 3]
for worker in range(1, num_days + 1):
for shift in shifts:
cost[(worker, shift)] = 0
for day in range(1, num_days + 1):
available_shifts = shifts.copy()
num_costs = 3
for _ in range(num_costs):
if len(available_shifts) > 0:
shift = random.choice(available_shifts)
cost[(day, shift)] += 1
available_shifts.remove(shift)
else:
break
return cost
num_days = 14
demand = generate_cost(num_days)
print(demand)
这个修改后的代码会生成一个与你描述的格式相匹配的字典,不再包含额外的 {1: {}, 2: {}}
。
英文:
I'm trying to create a function that creates a list like this (so in the same form) and does the following.
d = {
(1, 1): 1, (1, 2): 1, (1, 3): 1,
(2, 1): 0, (2, 2): 2, (2, 3): 1,
(3, 1): 1, (3, 2): 0, (3, 3): 2,
(4, 1): 0, (4, 2): 1, (4, 3): 2,
(5, 1): 2, (5, 2): 0, (5, 3): 1,
(6, 1): 1, (6, 2): 1, (6, 3): 1,
(7, 1): 1, (7, 2): 0, (7, 3): 2,
(8, 1): 2, (8, 2): 1, (8, 3): 0
}
In the brackets is the (worker,shift) combination. There should be any combination. In addition, on all possible (worker,shift)-combinations 3 are to be divided arbitrarily. Since there are only three combinations per worker (3 shifts) thus e.g. (worker 1,shift 1) u. (worker 1,shift 2) u. (worker 1,shift 3) shall be distributed on these three shifts randomly three thus e.g. (worker 1,shift 1): 1, (worker 1,shift 2): 0, (worker 1,shift 3): 2.
I also want to pass a value to the function that indicates how many workers there are.
My code so far looks like this:
import random
import random
def generate_cost(num_days):
cost = {}
shifts = [1, 2, 3]
for day in range(1, num_days+1):
cost[day] = {}
available_shifts = shifts.copy()
for shift in shifts:
cost[(day, shift)] = 0
num_costs = 3
for _ in range(num_costs):
if len(available_shifts) > 0:
shift = random.choice(available_shifts)
cost[(day, shift)] += 1
available_shifts.remove(shift)
else:
break
return cost
num_days = 14
demand = generate_cost(num_days)
print(demand)
It almost works, unfortunately there is always a
1: {}, or 2: {}
before each worker. How do I get rid of this?
答案1
得分: 2
只需删除 cost[day] = {}
这一无用的部分
然后你的代码不会按照你的要求运行,因为你是随机从一个列表中选择,直到该列表为空,你的做法与迭代它并给每个元素赋值为 1
是相同的。
shift = random.choice(available_shifts)
cost[(day, shift)] += 1
available_shifts.remove(shift)
这将导致每个工人的结果都是 (1, 1): 1, (1, 2): 1, (1, 3): 1
我建议你为第一个班次选择一个介于0和3之间的值,然后在剩余的班次中选择介于0和剩余班次之间的值,最后一个班次只选择剩余的值。
def generate_cost(num_days):
cost = {}
shifts = [1, 2, 3]
for day in range(1, num_days + 1):
num_costs = 3
for shift in shifts[:-1]:
shift_cost = random.randrange(0, num_costs) # 选择0、1或2
cost[(day, shift)] = shift_cost
num_costs -= shift_cost
# 最后一个班次取剩余的值
cost[(day, shifts[-1])] = num_costs
return cost
英文:
Just remove cost[day] = {}
that is useless
Then your code doesn't do what you asked, as you are randomly picking from a list until that list is empty, you're doing the same as iterating on it, and giving 1
to each
shift = random.choice(available_shifts)
cost[(day, shift)] += 1
available_shifts.remove(shift)
Resulting in (1, 1): 1, (1, 2): 1, (1, 3): 1
for every worker
I suggest you pick a value between 0 and 3 for the first shift, then between 0 and the remaining, and for the final shift just the remaining
def generate_cost(num_days):
cost = {}
shifts = [1, 2, 3]
for day in range(1, num_days + 1):
num_costs = 3
for shift in shifts[:-1]:
shift_cost = random.randrange(0, num_costs) # pick 0, 1 or 2
cost[(day, shift)] = shift_cost
num_costs -= shift_cost
# latest shift has the remaining
cost[(day, shifts[-1])] = num_costs
return cost
答案2
得分: 0
The cost[day] = {}
line is the one adding the extraneous items.
这一行 cost[day] = {}
是添加了多余的项。
The whole thing could be simplified by generating the random spreads using the sum of 3 values selected randomly from [100, 10, 1]. This would produce 3 digit numbers with a sum of digits that is always equal to 3.
整个过程可以通过生成从 [100, 10, 1] 中随机选择的 3 个值的和来简化。这将产生三位数,其数字之和始终等于 3。
Then break down these numbers (using division and modulo) to use each digit as the value for the 3 shifts of the corresponding day.
然后分解这些数字(使用除法和取模),以便将每个数字用作相应日期的 3 个班次的值。
num_days = 5
spreads = (sum(random.choices([100,10,1],k=3)) for _ in range(num_days))
demand = { (d,s+1):v//10**s%10 for d,v in enumerate(spreads,1)
for s in range(3) }
print(*demand.items(),sep="\n")
num_days = 5
spreads = (sum(random.choices([100,10,1],k=3)) for _ in range(num_days))
demand = { (d,s+1):v//10**s%10 for d,v in enumerate(spreads,1)
for s in range(3) }
print(*demand.items(),sep="\n")
((1, 1), 1)
((1, 2), 2)
((1, 3), 0)
((2, 1), 0)
((2, 2), 3)
((2, 3), 0)
((3, 1), 2)
((3, 2), 0)
((3, 3), 1)
((4, 1), 1)
((4, 2), 1)
((4, 3), 1)
((5, 1), 2)
((5, 2), 0)
((5, 3), 1)
If you have different numbers of shifts or a different total to spread, you could generalize this by writing a function to generate the random spread:
如果你有不同数量的班次或不同的总数需要分配,你可以通过编写一个生成随机分配的函数来泛化这个过程:
def randSpread(total,count):
base = total + 1
spread = sum(random.choices([basei for i in range(count)],k=total))
return [spread//basei%base for i in range(count)]
which you can use directly in the dictionary comprehension:
然后你可以直接在字典解析中使用它:
num_days = 5
demand = { (d,s):int(v) for d in range(1,num_days+1)
for s,v in enumerate(randSpread(13,4),1) }
((1, 1), 3)
((1, 2), 4)
((1, 3), 2)
((1, 4), 4)
((2, 1), 2)
((2, 2), 5)
((2, 3), 5)
((2, 4), 1)
((3, 1), 3)
((3, 2), 4)
((3, 3), 3)
((3, 4), 3)
((4, 1), 2)
((4, 2), 4)
((4, 3), 3)
((4, 4), 4)
((5, 1), 4)
((5, 2), 2)
((5, 3), 2)
((5, 4), 5)
英文:
The cost[day] = {}
line is the one adding the extraneous items.
The whole thing could be simplified by generating the random spreads using the sum of 3 values selected randomly from [100, 10, 1]. This would produce 3 digit numbers with a sum of digits that is always equal to 3.
Then break down these numbers (using division and modulo) to use each digit as the value for the 3 shifts of the corresponding day.
num_days = 5
spreads = (sum(random.choices([100,10,1],k=3)) for _ in range(num_days))
demand = { (d,s+1):v//10**s%10 for d,v in enumerate(spreads,1)
for s in range(3) }
print(*demand.items(),sep="\n")
((1, 1), 1)
((1, 2), 2)
((1, 3), 0)
((2, 1), 0)
((2, 2), 3)
((2, 3), 0)
((3, 1), 2)
((3, 2), 0)
((3, 3), 1)
((4, 1), 1)
((4, 2), 1)
((4, 3), 1)
((5, 1), 2)
((5, 2), 0)
((5, 3), 1)
If you have different numbers of shifts or a different total to spread, you could generalize this by writing a function to generate the random spread:
def randSpread(total,count):
base = total + 1
spread = sum(random.choices([base**i for i in range(count)],k=total))
return [spread//base**i%base for i in range(count)]
which you can use directly in the dictionary comprehension:
num_days = 5
demand = { (d,s):int(v) for d in range(1,num_days+1)
for s,v in enumerate(randSpread(13,4),1) }
((1, 1), 3)
((1, 2), 4)
((1, 3), 2)
((1, 4), 4)
((2, 1), 2)
((2, 2), 5)
((2, 3), 5)
((2, 4), 1)
((3, 1), 3)
((3, 2), 4)
((3, 3), 3)
((3, 4), 3)
((4, 1), 2)
((4, 2), 4)
((4, 3), 3)
((4, 4), 4)
((5, 1), 4)
((5, 2), 2)
((5, 3), 2)
((5, 4), 5)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论