Here's the exercise:
Given a string of X's and O's and a maximum number of swaps, determine the longest possible sequence of X's after swaps.
Here's my solution using itertools.
import itertools as iter
def swaps_gen(s):
'''This generator yields all the possible outcome of applying one swap
to the input string'''
X_positions = [i[0] for i in enumerate(s) if i[1] == "X"]
O_positions = [i[0] for i in enumerate(s) if i[1] == "O"]
for x in X_positions:
tmp_x = X_positions[:]
tmp_o = O_positions[:]
tmp_x.remove(x)
tmp_o.append(x)
for o in O_positions:
ttmp_x = tmp_x[:]
ttmp_o = tmp_o[:]
ttmp_o.remove(o)
ttmp_x.append(o)
s = []
for i in ttmp_x: s.insert(i, "X")
for i in ttmp_o: s.insert(i, "O")
yield "".join(s)
def flatten(l):
'''flatten one level. [[a], [b, c]] --> [a, b, c]'''
return iter.chain.from_iterable(l)
def max_x_after_swap(s, n):
'''repeat the generate swap_gen n times.
I used a set() to avoid duplicates.
Then returns the highest number of consecutive "X"s it finds.'''
outcomes = [s]
while n > 0:
outcomes = set(flatten([list(swaps_gen(x)) for x in outcomes]))
n -= 1
return max(map(nbr_of_consecutive_x, outcomes))
def nbr_of_consecutive_x(s):
'''return the number of consecutive "X" '''
return max([len(list(v)) for k, v in iter.groupby(s) if k == "X"])
def main():
input = "XXOXOXOXO"
swaps_nbr = 2
print(max_x_after_swap(input, swaps_nbr))
main()
Any criticism is welcome. It'd be great if you could point out any anti-pattern I may present, or show me better (by better I mean more pythonic) way to do things. I am more interested in improving my Python style than improving my algorithm.
I used Python3.1 to run the above.