Search code examples
pythoncombinationsgame-developmentpython-itertoolstile

Writing combinations from a list of strings where output is longer than input


What I'm trying to do is to take a list like this:

['WS','SB'...]

And write a python program that will produce an output like this for each string in the list:

['WWWW','WWWS','WWSS','WSSS','SSSS','SSSW','SSWW','SWWW','WSSW','SWWS','WSWS,'SWSW']

Essentially, I want all possible 4-character strings that can be written with those 2 characters. The order of the characters in the input doesn't really matter, but the order in the output does. These strings are meant to represent a 2x2 grid in which each quadrant is tagged with one of the two characters.

I do NOT want the output strings to include combinations of characters that do not exist as a single item in the input. So, in this example I would not want 'WWBB' as an output, B should only be paired with itself or S.

I also do NOT want output strings of a length shorter than 4, so 'WWW' should not be included in the output.

My program is in python so I have attempted to use several different methods from itertools to do this including combinations, permutations, and combinations_with_replacement. I have also tried formatting the inputs as lists, sets, and tuples but have not been successful.

Of these, combinations_with_replacement has come the closest to producing my desired output. However, none of these methods has returned all of the possible combinations as I have laid them out above. Specifically, these strings are being excluded from the outputs for all of these methods:

'WSSW','SWWS','WSWS,'SWSW'

Here is my best attempt at this. Note that for the input I ended up listing 'WS' and 'SW' as separate items to ensure that I got combinations in both directions, but in reality these two inputs should mean the same thing and the program should return all possible 4-character strings regardless of the order of the characters in the input.

import itertools

# define all texture pairs that can be in the same tile
texture_pairs = ['WS','SW','SB','BS','GW','WG','Gb','bG','gB','Bg']
tilesets = []

#determine all possible tiles for each texture pair & create a string in the form 'TTTT' representing the texture for each of the 4 tile quadrants, clockwise from the top left quadrant

def generate_tileset(texture_pair):
    return list(itertools.combinations_with_replacement(texture_pair,4))

for texture_pair in texture_pairs:
    tileset = generate_tileset(texture_pair)
    tilesets.append(tileset)
    print(tileset)

Solution

  • If you use itertools.product, the output gives all of the possible combinations:

    import itertools
        
    # Define all texture pairs that can be in the same tile
    texture_pairs = ['WS','SW'] # Deleted some of the pairs.
    tilesets = []
        
    # Determine all possible tiles for each texture pair 
    # and create a string in the form 'TTTT' representing the texture
    # for each of the 4 tile quadrants, clockwise from the top left quadrant    
    def generate_tileset(texture_pair):
        return list(itertools.product(texture_pair, repeat=4))
        
    for texture_pair in texture_pairs:
        tileset = generate_tileset(texture_pair)
        tilesets.append(tileset)
        print(tileset)
    

    This yields:

    [('W', 'W', 'W', 'W'), ('W', 'W', 'W', 'S'), ('W', 'W', 'S', 'W'), ('W', 'W', 'S', 'S'), ('W', 'S', 'W', 'W'), ('W', 'S', 'W', 'S'), ('W', 'S', 'S', 'W'), ('W', 'S', 'S', 'S'), ('S', 'W', 'W', 'W'), ('S', 'W', 'W', 'S'), ('S', 'W', 'S', 'W'), ('S', 'W', 'S', 'S'), ('S', 'S', 'W', 'W'), ('S', 'S', 'W', 'S'), ('S', 'S', 'S', 'W'), ('S', 'S', 'S', 'S')]
    [('S', 'S', 'S', 'S'), ('S', 'S', 'S', 'W'), ('S', 'S', 'W', 'S'), ('S', 'S', 'W', 'W'), ('S', 'W', 'S', 'S'), ('S', 'W', 'S', 'W'), ('S', 'W', 'W', 'S'), ('S', 'W', 'W', 'W'), ('W', 'S', 'S', 'S'), ('W', 'S', 'S', 'W'), ('W', 'S', 'W', 'S'), ('W', 'S', 'W', 'W'), ('W', 'W', 'S', 'S'), ('W', 'W', 'S', 'W'), ('W', 'W', 'W', 'S'), ('W', 'W', 'W', 'W')]