I was working on something this week that made me wonder how many permutations break up all consecutive elements. For example, if we’re looking at permutations of abcde then acebd counts, but acdbe does not. I’d like to count the number of such permutations, and estimate for large N the number of permutations of N elements with no consecutive terms.
A brief search lead to OEIS sequence A000255 which gives a recursive formula for the answer. Before looking at that, let’s define some terms and do some brute force calculation to get a feel for the problem.
Brute force calculation
Given a positive integer n, define Q(n) to be the number of partitions p of 1, 2, 3, …, n + 1 such that for no k does p(k + 1) = p(k) + 1.
from itertools import permutations def no_consec(perm): for k in range(len(perm) - 1): if perm[k+1] == perm[k] + 1: return False return True def Q(n): count = 0 for p in permutations(range(n+1)): if no_consec(p): count += 1 return count
We could use this code to compute Q(n) for moderate-sized n, but the time required to compute Q(n) this way is proportional to n! and so that won’t scale well.
Recurrence relation
OEIS sequence A000255 gives the values of what we’re calling Q(n), and the first few values match the output of the code above. But OEIS does better, giving a recursive solution for Q:
Q(n) = n Q(n − 1) + (n − 1) Q(n − 2)
for n > 1 with initial conditions Q(0) = Q(1) = 1.
As with Fibonacci numbers, you could implement this easily as a recursive function
def Q2(n): if n in[0, 1]: return 1 return n*Q2(n-1) + (n-1)*Q2(n-2)
but it is much faster to implement iteratively.
def Q3(n): q = [1]*(n+2) for k in range(2, n+1): q[k] = k*q[k-1] + (k-1)*q[k-2] return q[n]
You could make the recursive implementation faster with memoization, using lru_cache
from functools
. However, memoization does not prevent recursion; it just speeds up recursion using a cache, and you can still get an error saying maximum recursion depth exceeded.
Asymptotics
We can calculate Q(n) for large n, but we don’t have an analytic expression that will let us find the asymptotic behavior. I intended to work that out in my next post.
Empirically, it seems Q(n) approaches (n + 1)!/e as n goes to infinity, but I don’t have a proof of that at the time of writing. If this is correct, this means that in the limit the probability of a permutation having no fixed point equals the probability of it having no consecutive values.
Update: Proof