Just in case, someone will look for the same algorithm in python, here is an implementation in Python:
from itertools import combinations def compositions(s): n = len(s) for k in range(n): for c in combinations(range(1, n), k): yield tuple(s[i:j] for i, j in zip((0,) + c, c + (n,)))
An example of how this works:
>>> for x in compositions('abcd'): ... print(x) ('abcd',) ('a', 'bcd') ('ab', 'cd') ('abc', 'd') ('a', 'b', 'cd') ('a', 'bc', 'd') ('ab', 'c', 'd') ('a', 'b', 'c', 'd')
With a little modification, you can create compositions in a different order:
def compositions(s): n = len(s) for k in range(n): for c in itertools.combinations(range(n - 1, 0, -1), k): yield tuple(s[i:j] for i, j in zip((0,) + c[::-1], c[::-1] + (n,)))
This will give you the following:
>>> for x in compositions('abcd'): ... print(x) ('abcd',) ('abc', 'd') ('ab', 'cd') ('a', 'bcd') ('ab', 'c', 'd') ('a', 'bc', 'd') ('a', 'b', 'cd') ('a', 'b', 'c', 'd')
And with one more small addition, you can only generate the specified number of partitions:
def compositions(s, r=None): n = len(s) r = range(n) if r is None else [r - 1] for k in r: for c in itertools.combinations(range(n - 1, 0, -1), k): yield tuple(s[i:j] for i, j in zip((0,) + c[::-1], c[::-1] + (n,)))
>>> for x in compositions('abcd', 3): ... print(x) ('ab', 'c', 'd') ('a', 'bc', 'd') ('a', 'b', 'cd')