I have three lists: word
, occurrence
, and alphabet
:
occurrence = [2, 1, 3, 10] # but can be initialized differently
k = len(occurrence)
alphabet = [range(k)]
N = sum(occurrence)
word = [0]*N # initially
word
is a list that will contain a certain combination of values pulled from alphabet
, as decided by occurrence
. In the example above, word
must contain two 0
, one 1
, three 2
, and ten 3
in some combination. alphabet
can be used to index occurrence
.
I have an algorithm (see List-Fixed-Content by Sawada) that recursively adds/removes "letters" in alphabet
to/from word
, decrementing the value in the corresponding index of occurrence
when a letter is added, and incrementing that same value when a letter is removed.
The algorithm starts at the highest letter (3
when first initialized in this case) where the corresponding index in occurrence
is still greater than zero, then as the algorithm proceeds, goes to the NEXT highest letter that is still greater than zero.
I am currently handling this by removing a letter
when its occurrence reaches 0, via word.remove(letter)
, then adding it back in the correct position using word.insert(i,letter)
when its occurrence increases again. This makes both finding the maximum value in the alphabet
stepping down alphabet very easy.
The full code as requested:
occurrence = [2, 5, 3, 5] # example occurrence
k = len(occurrence)
alphabet = [range(k)]
N = sum(occurrence)
word = [0]*N
def algorithm(t, p):
if t > N:
if N % p == 0:
yield word.copy()
else:
letter = max(alphabet)
i = len(alphabet)-1
while letter >= word[t-p-1]:
word[t-1] = letter
occurrence[letter] -= 1
if not occurrence[letter]: # <<<<
i_removed = remove(letter)
if letter == word[t-p-1]:
yield from algorithm(t+1, p)
else:
yield from algorithm(t+1, t)
if not occurrence[letter]: # <<<<
add(i_removed, letter)
occurrence[letter] += 1
i -= 1
letter = get(i) # <<<<
def remove(letter):
i = alphabet.index(letter)
alphabet.remove(letter)
return i
def add(i, letter):
alphabet.insert(i,letter)
def get(i):
if i < 0:
return -1
else:
return alphabet[i]
def execute()
yield from algorithm(1, 1)
# Example usage of function
print(list(execute()))
I've found this to be VERY slow, and I suspect it's because of list.insert
. What is a better way of finding the highest and next-highest letters of alphabet
whose corresponding values in occurrence
are non-zero, without adding and removing letters from alphabet
?
Something like assigning the lists as numpy arrays and the following code?
...
letter = max(alphabet[occurrence > 0])
while letter >= limit: # some limit
...
while True: # <<<< replaces remove(), add(), and get()
letter -= 1
if letter < 0 or occurrence[letter] > 0:
break