You can use dynamic programming, as in the following pseudo-code sketch (for simplicity, this code assumes that the threshold is 3 Xs or Ys per line, not 4):
min_switch(s): n = len(s) optx = array(4, n, infinity) // initialize all values to infinity opty = array(4, n, infinity) // initialize all values to infinity if s[0] == 'X': optx[1][0] = 0 opty[1][0] = 1 else: optx[1][0] = 1 opty[1][0] = 0 for i in {1, n - 1}: x = s[i] if x == 'X': optx[1][i] = opty[3][i - 1] optx[2][i] = optx[1][i - 1] optx[3][i] = min(optx[2][i - 1], optx[3][i - 1]) opty[1][i] = 1 + min(optx[1][i - 1], optx[2][i - 1], optx[3][i - 1]) opty[2][i] = 1 + opty[1][i - 1] opty[3][i] = 1 + min(opty[2][i - 1], opty[3][i - 1]) else: optx[1][i] = 1 + min(opty[1][i - 1], opty[2][i - 1], opty[3][i - 1]) optx[2][i] = 1 + opty[1][i - 1] optx[3][i] = 1 + min(opty[2][i - 1], opty[3][i - 1]) opty[1][i] = optx[3][i - 1] opty[2][i] = opty[1][i - 1] opty[3][i] = min(opty[2][i - 1], opty[3][i - 1]) return min(optx[3][n - 1], opty[3][n - 1])
The above code essentially calculates the lowest cost to create a smooth sequence up to the i-th character, while maintaining the optimal value for all the corresponding numbers of consecutive Xs or Ys in a line (1, 2 or 3 lines). More formally
opt[i][0][k] stores the lowest cost of converting the string s[0...k] into a smooth sequence, then i consecutive Xs ends. Runs of 3 or more are counted in opt[3][0][k] .opt[0][j][k] stores the lowest cost of converting the string s[0...k] into a smooth sequence, then j consecutive Ys ends. Runs of 3 or more are counted in opt[0][3][k] .
Directly convert this to an algorithm that returns the sequence as well as the optimal cost.
Please note that some of the cases in the above code are probably not needed, it's just a direct repetition derived from restrictions.
source share