In [1]:
def transpose(tile):
    '''Transposes a tile'''
    return (tile[::-1])

def multiply(tile1, tile2):
    '''Multiplies two tiles'''
    return (tile1 + tile2)

def operate(canvas, max_op_count):
    '''Runs all operations (transposition and multiplication) once over each of the tiles, respecting the maximum operation count threshold'''
    new_tiles = set()
    for (tile, op_count) in canvas:
        if op_count < max_op_count:
            new_tiles.add((transpose(tile), op_count + 1))
        for (other_tile, other_op_count) in canvas:
            if op_count + other_op_count < max_op_count:
                if tile[-1] == other_tile[0]:
                    new_tiles.add((multiply(tile, other_tile), op_count + other_op_count + 1))
                if other_tile[-1] == tile[0]:
                    new_tiles.add((multiply(other_tile, tile), op_count + other_op_count + 1))
    canvas.update(new_tiles)
    
def filter_duplicates(canvas):
    thresh = set()
    for (tile, op_count) in canvas:
        for (other_tile, other_op_count) in canvas:
            if tile == other_tile and op_count != other_op_count:
                thresh.add((tile, max(op_count, other_op_count)))
    return canvas.difference(thresh)
    
def filter_op_count(max_count, canvas):
    thresh = set()
    for (tile, op_count) in canvas:
        if op_count > max_count:
            thresh.add((tile, op_count))
    return canvas.difference(thresh)    
    
def filter_template(template, canvas):
    thresh = set()
    for (tile, op_count) in canvas:
        if tile[0] != template[0] or tile[-1] != template[-1]:
            thresh.add((tile,op_count))
    return canvas.difference(thresh)

def sort(canvas):
    return [x[0] for x in sorted(canvas, key=lambda x: x[1])]

def simulate(template, max_operations, BASIC_TILES):
    canvas = set()
    for tile in BASIC_TILES:
        canvas.add((tile,0))

    for i in range(max_operations):
        operate(canvas, i + 1)

    canvas = filter_duplicates(canvas)
    canvas = filter_op_count(max_operations, canvas)
    print('Total number of possible tiles after', max_operations, 'operations:', len(canvas))
    
    canvas = filter_template(template, canvas)
    print('Ranking of the correct answer in the suggestions compatible with [' + template[0] + '|' + template[-1] + ']:', len(canvas))

    print('Rank of possible compatible answers:', sort(canvas))

In [2]:
# Cl = 'class'
# M = 'method'
# F = 'file'
# C = 'commit'
# D = 'developer'
# P = 'package'
# I = 'issue'
BASIC_TILES = {('Cl','M'), ('F','Cl'), ('C','F'), ('C','M'), ('D','C'), ('P','F'), ('I','C')}

Scenario 1: [D|D] = [D|C] x [C|M] x ([C|M] x [D|C])T


In [3]:
template = ('D','D')
max_operations = 4

simulate(template, max_operations, BASIC_TILES)


Total number of possible tiles after 4 operations: 231
Ranking of the correct answer in the suggestions compatible with [D|D]: 3
Rank of possible compatible answers: [('D', 'C', 'C', 'D'), ('D', 'C', 'C', 'F', 'F', 'C', 'C', 'D'), ('D', 'C', 'C', 'M', 'M', 'C', 'C', 'D')]

Scenario 2: [D|D] = [D|C] x [I|C]T x [I|C] x [D|C]T


In [4]:
template = ('D','D')
max_operations = 5

simulate(template, max_operations, BASIC_TILES)


Total number of possible tiles after 5 operations: 450
Ranking of the correct answer in the suggestions compatible with [D|D]: 5
Rank of possible compatible answers: [('D', 'C', 'C', 'D'), ('D', 'C', 'C', 'F', 'F', 'C', 'C', 'D'), ('D', 'C', 'C', 'M', 'M', 'C', 'C', 'D'), ('D', 'C', 'C', 'D', 'D', 'C', 'C', 'D'), ('D', 'C', 'C', 'I', 'I', 'C', 'C', 'D')]

Scenario 3: [D|Cl] = [D|C] x [C|M] x [Cl|M]T


In [5]:
template = ('D','Cl')
max_operations = 3

simulate(template, max_operations, BASIC_TILES)


Total number of possible tiles after 3 operations: 117
Ranking of the correct answer in the suggestions compatible with [D|Cl]: 2
Rank of possible compatible answers: [('D', 'C', 'C', 'F', 'F', 'Cl'), ('D', 'C', 'C', 'M', 'M', 'Cl')]

Scenario 4: [C|Cl] = [C|M] x [Cl|M]T


In [6]:
template = ('C','Cl')
max_operations = 2

simulate(template, max_operations, BASIC_TILES)


Total number of possible tiles after 2 operations: 54
Ranking of the correct answer in the suggestions compatible with [C|Cl]: 2
Rank of possible compatible answers: [('C', 'F', 'F', 'Cl'), ('C', 'M', 'M', 'Cl')]