Distribute an integer amount by a set of slots as evenly as possible

前端 未结 5 502
逝去的感伤
逝去的感伤 2021-02-02 09:47

I am trying to figure an elegant way of implementing the distribution of an amount into a given set of slots in python.

For example:

7 oranges distributed onto 4

5条回答
  •  清歌不尽
    2021-02-02 10:06

    See also more_itertools.distribute, a third-party tool and its source code.

    Code

    Here we distributes m items into n bins, one-by-one, and count each bin.

    import more_itertools as mit
    
    
    def sum_distrib(m, n):
        """Return an iterable of m items distributed across n spaces."""
        return [sum(x) for x in mit.distribute(n, [1]*m)]
    

    Demo

    sum_distrib(10, 4)
    # [3, 3, 2, 2]
    
    sum_distrib(7, 4)
    # [2, 2, 2, 1]
    
    sum_distrib(23, 17)
    # [2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    

    Example

    This idea is akin to distributing a deck of cards among players. Here is an initial game of Slapjack

    import random
    import itertools as it
    
    
    players = 8
    suits = list("♠♡♢♣")
    ranks = list(range(2, 11)) + list("JQKA")
    deck = list(it.product(ranks, suits))
    random.shuffle(deck)
    
    hands = [list(hand) for hand in mit.distribute(players, deck)]
    hands
    # [[('A', '♣'), (9, '♠'), ('K', '♣'), (7, '♢'), ('A', '♠'), (5, '♠'), (2, '♠')],
    #  [(6, '♣'), ('Q', '♠'), (5, '♢'), (5, '♡'), (3, '♡'), (8, '♡'), (7, '♣')],
    #  [(7, '♡'), (9, '♢'), (2, '♢'), (9, '♡'), (7, '♠'), ('K', '♠')],
    #   ...]
    

    where the cards are distributed "as equally as possible between all [8] players":

    [len(hand) for hand in hands]
    # [7, 7, 7, 7, 6, 6, 6, 6]
    

提交回复
热议问题