简体   繁体   中英

Randomizing lists with set rules

I have a project where I want to make a list randomizer with a set of rules.

Let's say I have 1 list named guests with 9 items, 1 named hosts with 4 items, and one named meals with 3 items.

Now I want to randomize these guests across the hosts so every host get 3 guests, witch is fair enough. Now they will all be connected to the first item in meal. Problem arrives when I want to scramble them again across different hosts for meal 2, but so that none of the guests that have been together meet again for the next 2 meals.

I do in the end want to have it so I can have a dynamic list of hosts and guests that will solve itself after they've been typed in.

I don't want the code solved, just looking for the means to get there.

There are two things you will need to keep track of: a) Which hosts have already hosted which guests b) For each meal, which guests have already been assigned out.

Item a can be done with a dictionary that uses the name of each host as a key. Item b just needs to be a list that gets reset for each new meal.

Once you've started keeping track of that information, then right before choosing the guests that will be assigned to a host, you can use this information that you are keeping track of to create a second intermediary list that only includes guests that can be chosen and randomly choose one of them.

Below is my solution to this problem:

import random
import pprint

class Meal_Schedule:
    def __init__(self, guests, hosts):
        self.guests = guests
        self.hosts = hosts
        self.previously_assigned = {host:[] for host in hosts}

    def plan_next_meal(self, guests_per_host=None):
        # self.previously_assigned keeps track of who has been assigned to a host in the past
        # so we don't assign a guest to the same host twice
        # and assigned_this_round will keep track of which guests have already been given a seat this round
        # so we don't double book a guest to two different hosts

        if guests_per_host is None:
            if len(self.hosts) < 1:
                raise RuntimeException('Must have at least one host')
            guests_per_host = len(self.guests) // len(self.hosts)
            if guests_per_host < 1:
                guests_per_host = 1

        ret = {}
        assigned_this_round = []
        for host in self.hosts:
            # sets give us the super power of being able to use subtraction to remove guest that we don't want
            possible_guests = list( set(self.guests) - set(self.previously_assigned[host]) - set(assigned_this_round) )

            if not possible_guests:
                ret[host] = []
                break

            if len(possible_guests) <= guests_per_host:
                assignment = possible_guests
            else:
                assignment = random.sample(possible_guests, guests_per_host)

            assigned_this_round.extend(assignment)
            ret[host] = assignment
            self.previously_assigned[host].extend(assignment)

        return ret

guests = [f'Guest {x}' for x in 'ABCDEFGHI']
hosts = ['host1', 'host2', 'host3', 'host4']
scheduler = Meal_Schedule(guests, hosts)

for meal in ['Hamburger', 'Pizza', 'Eggs']:
    print(f'{meal} Meal Plan:')
    pprint.pprint(scheduler.plan_next_meal(3))
    print()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM