Complete solution to today's problem in one line of python
def gen(univ, n=5): return univ if n == 1 else [x+y for y in gen(univ,n-1) for x in univ if all([(x+y)[start:start+upto] != (x+y)[start+upto:start+upto*2] for start in range(len(x+y)) for upto in range(1,(len(x+y)-start+2)/2)])]
sub solutions {
my ( $target_length, $alphabet, $head ) = @_;
$head //= '';
# Base Case our head is the right length
return $head if (length $head) == $target_length;
# General Case
return
map { generate( $target_length, $alphabet, $_ ) }
grep { ! /(.{2})\1/ }
map { $head . $_ }
@$alphabet;
}
Or if the regexp engine manages to do that automatically.
[UPDATE: it is slower to provide your own max length. the perl regexp engine is badass. repeating timings on my mac pro with a target_length of 12 show the plain {2,} version is 15% quicker].
(also, you've a minor typo as you recurse into "generate" instead of "solutions", I assume b/c you renamed the function at the very end to make the eg: code scan better).
Here is an ugly iterative solution, in one lambda:
from itertools import product
f = lambda n: [
s for s in
map(''.join, product("abc", repeat=n))
if not any(a==b
for a,b in
[(s[a:b], s[b:c])
for a,b,c in
[(i,i+w,i+2*w)
for w in range(1,len(s)/2+1)
for i in range(len(s)-2*w+1)]])]
>>> f(5)
['abaca', 'abacb', 'abcab', 'abcac', 'abcba', 'acaba',
'acabc', 'acbab', 'acbac', 'acbca', 'babca', 'babcb',
'bacab', 'bacba', 'bacbc', 'bcaba', 'bcabc', 'bcacb',
'bcbab', 'bcbac', 'cabac', 'cabca', 'cabcb', 'cacba',
'cacbc', 'cbabc', 'cbaca', 'cbacb', 'cbcab', 'cbcac']
def gen(univ, n=5): return univ if n == 1 else [x+y for y in gen(univ,n-1) for x in univ if all([(x+y)[start:start+upto] != (x+y)[start+upto:start+upto*2] for start in range(len(x+y)) for upto in range(1,(len(x+y)-start+2)/2)])]
... god that looks ugly. Call it with
>>> gen(["1", "2", "3"], 5) ['13121', '23121', '21321', '31321', '12321', '12131', '32131', '21231', '31231', '13231', '13212', '23212', '21312', '12312', '32312', '12132', '32132', '23132', '21232', '31232', '31213', '13213', '23213', '12313', '32313', '32123', '13123', '23123', '21323', '31323']