简体   繁体   中英

Recursively calculate the number of permutations that have a maximal displacement

I created a recursive function called permutations_dist(s, dist).

It's supposed to return the number of the permutations of a string, while the distance between every 2 letters in the permutations doesn't exceed a given number.

A few examples:

permutations_dist("abc", 1) --> 2
permutations_dist("abc", 1000) --> 6
permutations_dist("abcz", 23) --> 4

How can I make the following code more efficient? I want to use backtracking.

It reaches maximum recursion depth pretty quickly. For instance - permutations_dist("abcdefghijkm", 3)) .

The CODE:

def permutations_dist(s, dist):
    return len(permutations_dist_helper(s, dist))

def permutations_dist_helper(s, dist):
   if len(s) == 1:
       return [s]

   perm_list = []  # resulting list
   for a in s:
       remaining_elements = [x for x in s if x != a]
       z = permutations_dist_helper(remaining_elements, dist)

       for t in z:
           if abs(ord(a) - ord(t[0])) <= dist:
               perm_list.append([a] + t)

    return perm_list

It's better to use stack to avoid exceeding max recursion depth. The code below generates all string permutations having max distance between two any adjacent characters not more than dist :

def permutations(s, dist):
    result = set()
    stack = [("", s, 0)]

    while stack:
        cur, remaining, cur_distance = stack.pop(0)

        if remaining:
            candidates = set()
            for i in range(0, len(remaining)):
                m = remaining[i]
                diff = abs(ord(m) - ord(cur[-1])) if cur else 0
                new_distance = max(cur_distance, diff)
                if new_distance <= dist:
                    head = cur + m
                    candidates.add((head, remaining[:i] + remaining[i+1:], new_distance))
            for c in candidates:
                stack.append(c)
        else:
            result.add(cur)

    return result

Let's check how long it takes to calculate permutations("abcdefghijk", 3) :

from time import time
start = time()
dist = len(permutations("abcdefghijk", 3))
end = time()
print("Premutations: {}, execution time: {:05f}".format(dist, end - start))

On my MacBook it displays

Premutations: 13592, execution time: 0.663339

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM