ddsprasad
ddsprasad

Reputation: 82

combinations with python

I am trying to generate combination of ID's

Input: cid = SPARK

oupout: list of all the comibnations as below, position of each element should be constant. I am a beginner in python any help here is much appreciated.

'S****'
'S***K'
'S**R*'
'S**RK'
'S*A**'
'S*A*K'
'S*AR*'
'S*ARK'
'SP***'
'SP**K'
'SP*R*'
'SP*RK'
'SPA**'
'SPA*K'
'SPAR*'
'SPARK'

I tried below, I need a dynamic code:

cid = 'SPARK'

# print(cid.replace(cid[1],'*'))
# cu_len = lenth of cid [SPARK] here which is 5
# com_stars = how many stars i.e '*' or '**'
def cubiod_combo_gen(cu_len, com_stars, j_ite, i_ite):
    cubiodList = []
    crange = cu_len
    i = i_ite #2 #3
    j = j_ite #1
    # com_stars = ['*','**','***','****']

    while( i <= crange):
    # print(j,i)
        if len(com_stars) == 1:
            x = len(com_stars)
            n_cid = cid.replace(cid[j:i],com_stars)
            i += x
            j += x
            cubiodList.append(n_cid)
        elif len(com_stars) == 2:
            x = len(com_stars)
            n_cid = cid.replace(cid[j:i],com_stars)
            i += x
            j += x
            cubiodList.append(n_cid)
        elif len(com_stars) == 3:
            x = len(com_stars)
            n_cid = cid.replace(cid[j:i],com_stars)
            i += x
            j += x
            cubiodList.append(n_cid)
    return cubiodList
    #print(i)
    #print(n_cid)
    # for item in cubiodList:
    #     print(item)

print(cubiod_combo_gen(5,'*',1,2))

print(cubiod_combo_gen(5,'**',1,3))

Upvotes: 1

Views: 159

Answers (2)

Chris Charley
Chris Charley

Reputation: 6573

I am not sure what com_stars does, but to produce your sample output, the following code does.

def cuboid_combo(cid):
    fill_len = len(cid)-1

    items = []

    for i in range(2 ** fill_len):
        binary = f'{i:0{fill_len}b}'
        #print(binary, 'binary', 'num', i)

        s = cid[0]
        for idx, bit in enumerate(binary,start=1):
            if bit == '0':
                s += '*'
            else: # 'bit' == 1
                s += cid[idx]

        items.append(s)

    return items


#cid = 'ABCDEFGHI'
cid = 'DPSCT'

result = cuboid_combo(cid)

for item in result:
    print(item)

Prints:

D****
D***T
D**C*
D**CT
D*S**
D*S*T
D*SC*
D*SCT
DP***
DP**T
DP*C*
DP*CT
DPS**
DPS*T
DPSC*
DPSCT

Upvotes: 0

Eric Jin
Eric Jin

Reputation: 3924

For every character in your given string, you can represent it as a binary string, using a 1 for a character that stays the same and a 0 for a character to replace with an asterisk.

def cubiod_combo_gen(string, count_star):
    str_list = [char0 for char0 in string] # a list with the characters of the string
    itercount = 2 ** (len(str_list)) # 2 to the power of the length of the input string
    results = []

    for config in range(itercount):

        # return a string of i in binary representation
        binary_repr = bin(config)[2:]
        while len(binary_repr) < len(str_list):
            binary_repr = '0' + binary_repr # add padding

        # construct a list with asterisks
        i = -1
        result_list = str_list.copy() # soft copy, this made me spend like 10 minutes debugging lol
        for char in binary_repr:
            i += 1
            if char == '0':
                result_list[i] = '*'
            if char == '1':
                result_list[i] = str_list[i]

        # now we have a possible string value
        if result_list.count('*') == count_star:
            # convert back to string and add to list of accepted strings
            result = ''
            for i in result_list:
                result = result + i
            results.append(result)

    return results


# this function returns the value, so you have to use `print(cubiod_combo_gen(args))`
# comment this stuff out if you don't want an interactive user prompt
string = input('Enter a string : ')
count_star = input('Enter number of stars : ')
print(cubiod_combo_gen(string, int(count_star)))

It iterates through 16 characters in about 4 seconds and 18 characters in about 17 seconds. Also you made a typo on "cuboid" but I left the original spelling

Enter a string : DPSCT
Enter number of stars : 2
['**SCT', '*P*CT', '*PS*T', '*PSC*', 'D**CT', 'D*S*T', 'D*SC*', 'DP**T', 'DP*C*', 'DPS**']

As a side effect of this binary counting, the list is ordered by the asterisks, where the earliest asterisk takes precedence, with next earliest asterisks breaking ties.

If you want a cumulative count like 1, 4, 5, and 6 asterisks from for example "ABCDEFG", you can use something like

star_counts = (1, 4, 5, 6)
string = 'ABCDEFG'
for i in star_counts:
    print(cubiod_combo_gen(string, star_counts))

If you want the nice formatting you have in your answer, try adding this block at the end of your code:

def formatted_cuboid(string, count_star):
    values = cubiod_combo_gen(string, count_star)
    for i in values:
        print(values[i])

I honestly do not know what your j_ite and i_ite are, but it seems like they have no use so this should work. If you still want to pass these arguments, change the first line to def cubiod_combo_gen(string, count_star, *args, **kwargs):

Upvotes: 1

Related Questions