1
I am generating all possible combinations within a list, but I have not found any that would satisfy all my needs, being them:
- Result in list format;
- Lists with repeated items are valid;
- Completely equal lists are not valid;
- There should be a maximum size limiter for list generation;
- The sum of the list items cannot be greater than tamax;
- Code execution time is important;
I made the code below, but would like to know if there is a more refined/pythonic way of writing this same code.
OBS: I used limiters to decrease the number of generator iterations, because I had to make combinations with a list of 30 numbers, and without the limiters the code never finished running.
import numpy as np
from math import floor
from itertools import product
tamax = 12 #valor máximo da soma dos itens na lista
tamin = tamax * 0.95 #valor mínimo da soma dos itens na lista
tamanhos = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = lista para combinações
tamanhos.sort()
limites = [] #armazena os limites para cada número de iterações
iteracoes = [] #armazena o número máximo de iterações que os elementos da lista vão gerar se combinados. É pareado com a lista limites
check = [] #usado como checagem para adicionar itens na lista limites
tamcomb = [] #armazena todas as combinações de tamanhos
comb = () #combinação do gerador aleatório
def sumall(tupla): #retorna o somatório do itens da tupla gerada
tam = len(tupla)
lista1 = list(tupla[0:tam])
return np.sum(lista1)
def cresc(tupla): #transforma a tupla em uma lista em ordem crescente
tam = len(tupla)
lista = list(tupla[0:tam])
lista.sort()
return lista
for i in tamanhos:
iteracao = floor(((tamax-i)/min(tamanhos))+1) #retorna o número máximo de iterações que podem ocorrer nas combinações entre os itens da lista
if iteracao not in iteracoes: #adicionar o número à lista iteracoes
iteracoes.append(iteracao)
for j in range(0, (max(iteracoes)+1)): #adiciona na lista limites o tamanho referente ao número de iterações calculado
if j == iteracao:
if iteracao not in check:
limites.append(i)
check.append(iteracao)
limites.sort(reverse=True)
iteracoes.sort()
print("iteracoes = ", iteracoes)
print("limites = ", limites)
for i in range(1, (max(iteracoes)+1))):
limite = 0
for j in iteracoes:
if i <= j:
if limites[iteracoes.index(j)] > limite:
limite = limites[iteracoes.index(j)]
tamanhos_validos = [tamanho for tamanho in tamanhos if tamanho <= limite] # gera a lista com os tamanhos que serão utilizados de acordo com o número de iterações
gerador = product(tamanhos_validos, repeat=i) # repeat é utilizado para especificar o numero de item que as combinações irão possuir
for comb in gerador: #gera as combinações com base no tamax e tamin
if tamax >= sumall(comb) >= tamin:
comb = cresc(comb)
if comb not in tamcomb: #se a combinação ainda não existe em tambcom, é adicionada na lista
tamcomb.append(comb)
print("combinações validas = "tamcomb)
Output:
iteracoes = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
limites = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
combinações validas = [[2, 10], [3, 9], [4, 8], [5, 7], [6, 6], [1, 1, 10], [1, 2, 9], [1, 3, 8], [1, 4, 7], [1, 5, 6], [2, 2, 8], [2, 3, 7], [2, 4, 6], [2, 5, 5], [3, 3, 6], [3, 4, 5], [4, 4, 4], [1, 1, 1, 9], [1, 1, 2, 8], [1, 1, 3, 7], [1, 1, 4, 6], [1, 1, 5, 5], [1, 2, 2, 7], [1, 2, 3, 6], [1, 2, 4, 5], [1, 3, 3, 5], [1, 3, 4, 4], [2, 2, 2, 6], [2, 2, 3, 5], [2, 2, 4, 4], [2, 3, 3, 4], [3, 3, 3, 3], [1, 1, 1, 1, 8], [1, 1, 1, 2, 7], [1, 1, 1, 3, 6], [1, 1, 1, 4, 5], [1, 1, 2, 2, 6], [1, 1, 2, 3, 5], [1, 1, 2, 4, 4], [1, 1, 3, 3, 4], [1, 2, 2, 2, 5], [1, 2, 2, 3, 4], [1, 2, 3, 3, 3], [2, 2, 2, 2, 4], [2, 2, 2, 3, 3], [1, 1, 1, 1, 1, 7], [1, 1, 1, 1, 2, 6], [1, 1, 1, 1, 3, 5], [1, 1, 1, 1, 4, 4], [1, 1, 1, 2, 2, 5], [1, 1, 1, 2, 3, 4], [1, 1, 1, 3, 3, 3], [1, 1, 2, 2, 2, 4], [1, 1, 2, 2, 3, 3], [1, 2, 2, 2, 2, 3], [2, 2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 6], [1, 1, 1, 1, 1, 2, 5], [1, 1, 1, 1, 1, 3, 4], [1, 1, 1, 1, 2, 2, 4], [1, 1, 1, 1, 2, 3, 3], [1, 1, 1, 2, 2, 2, 3], [1, 1, 2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 5], [1, 1, 1, 1, 1, 1, 2, 4], [1, 1, 1, 1, 1, 1, 3, 3], [1, 1, 1, 1, 1, 2, 2, 3], [1, 1, 1, 1, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 1, 4], [1, 1, 1, 1, 1, 1, 1, 2, 3], [1, 1, 1, 1, 1, 1, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
This code took about 9s to run on Google Colab.
I don’t know if I understood all the criteria exactly, but finally, a suggestion: https://ideone.com/0NXpxz
– hkotsubo
Thanks for the help, I updated to try to explain better, I hope I got it. I’ve already updated some parts according to what I saw in your code, thank you.
– Gustavo Domingos Garcia