0

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
Rek
  • 45
  • 4
  • 1
    I haven't read your whole question, but from a skim, it looks like this code is working but not fast. So this would be a better question for [Code Review](https://codereview.stackexchange.com). – wjandrea Aug 06 '19 at 23:29
  • Where is your exit condition in the reccurence? From what i can see it starts with some value `t` then you loop and use `words[t]` then `recursive_function(t+1)`. At some point `words[t]`will throw `IndexError` :| – Artog Aug 07 '19 at 09:34
  • Also Im not sure what is trying to be accomplished here.. do you want an `occurence = [2,1,3,10]` to result in `word = [0,0,1,2,2,2,3,3,3,3,3,3,3,3,3,3]`? Because there are way easier ways to accomplish that :) – Artog Aug 07 '19 at 09:49
  • Or maybe you want `word = [3,3,3,3,3,3,3,3,3,3,2,2,2,0,0,1]`? – Artog Aug 07 '19 at 12:20
  • 1
    @wjandrea should I delete this and repost to Code Review, then? – Rek Aug 07 '19 at 13:55
  • @Artog `recursive_function` will return a limited set of any `word` that contains any combination of the letters in `occurrence`, as specified by a `condition`. – Rek Aug 07 '19 at 13:58
  • @Rek You don't need to, but try checking out Code Review's [How to Ask](https://codereview.stackexchange.com/help/how-to-ask), [On topic](https://codereview.stackexchange.com/help/on-topic), and [Off topic](https://codereview.stackexchange.com/help/dont-ask) pages to see if your question would be well-received there. – wjandrea Aug 07 '19 at 14:04
  • Running your code yields an empty list for me. Can you give an example result, f.ex. with the given preconditions in your post? – Artog Aug 07 '19 at 14:27
  • @Artog, I've added the full code – Rek Aug 08 '19 at 03:02
  • From what i could gather the function yields all unique permutations by value, i.e. `occurence = [2]` gives `[[0,0]]` but `occurence = [1,1]` gives `[[0,1],[1,0]]`. You can maybe take a look at https://stackoverflow.com/questions/6284396/permutations-with-unique-values#6285203 – Artog Aug 08 '19 at 06:07

0 Answers0