sharing/swapping items between lists

Aaron Brady castironpi at gmail.com
Wed Apr 15 13:57:10 EDT 2009


On Apr 15, 11:29 am, samwyse <samw... at gmail.com> wrote:
> On Apr 15, 8:56 am, Aaron Brady <castiro... at gmail.com> wrote:
>
>
>
> > The randomizing solution isn't quite suitable for 16 teams.  With 5
> > teams/1 court, and 5 teams/2 courts, 6 teams/2 courts, the solution
> > comes within seconds.  For 7 teams/3 courts, the solution takes a few
> > minutes.
>
> 7 teams/3 courts is the same as 8 teams/4 courts, where the extra
> player is named "bye".  In other words, it's an uncontrained problem.

For 9 teams, there are (9*8/2), or 36 pairs, so 36!, or
371993326789901217467999448150835200000000, or 3.7e+41 permutations of
arranging them.  (Thanks to Python's long ints.)  Many of them work on
2 courts.

There are 5x10^68 hydrogen atoms in a galaxy.

There was a discussion on python-ideas about whether ran.shuffle( ) is
even guaranteed to find a solution eventually.  I forget if 36! was
within its bounds.  It may run for years and fail.

On the 8 teams/3 courts trial, a depth-first search can improve your
results in a few seconds, but only by getting one team in one round
earlier.  That figure is interesting, because there are 28! or 3e+29
possible permutations.  It seems many of them work.

The rest of the combinations are impractical to try with a DFS, or
your algorithm does just as good.  Here is the DFS.  Mine is currently
tinkering around on the 25th place of 36 total slots.

The Pinewood Derby case doesn't show much more promise, though you can
eliminate more possibilities from your round, which may speed it up.

from itertools import combinations, permutations
import string
from copy import deepcopy
def circulate( num_players, num_courts ):
    ''' 2 players per court '''
    assert num_players<= 26, '26 players max'
    player_set= sorted( string.ascii_lowercase[ :num_players ] )
    combs= sorted( ''.join( x ) for x in combinations( player_set,
2 ) )
    print( combs )

    obs= [ [ x, 0 ] for x in combs ]
    # obs[ 1 ]-- 0: not used, 1: one player of combination
    #            used in round, 2: combination used
    stack= [ None ]* len( combs )
    def rec( obs, dep ):
        if dep< len( combs )- 12:
            print( '%i teams %i courts dep %i\nobs %r\nstack %r\n'%
( num_players, num_courts, dep, obs, stack ) )
        if all( [ x[ 1 ]== 2 for x in obs ] ):
            return True
        if ( dep+ 1 )% num_courts== 0:
            for x in obs: # new round, clear 'obs'
                if x[ 1 ]== 1:
                    x[ 1 ]= 0
        else:
            for x in obs: # mark 'obs' so player not tried again
                if x[ 1 ]!= 0:
                    continue
                for y in stack[ dep ]:
                    if y in x[ 0 ]:
                        x[ 1 ]= 1
        for i in range( len( combs ) ):
            if obs[ i ][ 1 ]== 0:
                obs[ i ][ 1 ]= 2
                stack[ dep+ 1 ]= obs[ i ][ 0 ]
                res= rec( deepcopy( obs ), dep+ 1 )
                if res: return True
                obs[ i ][ 1 ]= 0
        stack[ dep+ 1 ]= None
        return False
    rec( deepcopy( obs ), -1 )
    return [ stack[ i: i+ num_courts ] for i in range( 0, len
( stack ), num_courts ) ]



More information about the Python-list mailing list