O(nk) greedy solution (n = input size, k = radix of your digits), based on Stefan Kendall's answer above, but with the insight that you should probably be greedy and use the integer you have the most of first. I'm not positive it works for all inputs, but I racked my brain trying to think of a counter example where the greed would fail here, and haven't found one yet. Warning: cruddy python ahead - I did this to be quick and dirty, not pretty.
Check whether a digit may be used given the current state:
def ok(s, n, v):
l = len(s)
if l < n:
n = l
if n < 1:
return True
if str(v) in s[-n:]:
return False
return True
Helper which does all the work - loop through the counts, find the one with maximum number of repetitions left which is usable, and select it. Repeat.
def go(counts, n):
output = ""
max = 0
more = True
while max >= 0:
max = -1
pos = -1
more = False
for i in range(10):
if counts[i] > 0:
more = True
if counts[i] > max and counts[i] > 0 and ok(output, n, i):
max = counts[i]
pos = i
if max < 0:
if more:
return "No solution"
return output
counts[pos] = counts[pos] - 1
output = output + str(pos)
Main function:
def blockify(s, fold):
counts = [0,0,0,0,0,0,0,0,0,0]
for letter in s:
counts[int(letter)] = counts[int(letter)] +1
return go(counts, fold)
I feel like there's probably a counterexample that this fails on, but I can't think of one.