定义一个用于需求模式的函数。

huangapple go评论66阅读模式
英文:

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//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)

英文:

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)

huangapple
  • 本文由 发表于 2023年6月6日 02:29:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76409108.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定