Code: Select all
/*
* which() -- determines the leftmost pair of characters, which can be
* multiplied, such that the character 'dst' still can be obtained from
* the resulting string.
*
* Returns the offset of the first character in the pair, or -1 if
* the character 'dst' can't be obtained from the initial string.
*/
int which(int src[], int n, int dst)
{
int can[16][16][4], first[16][16][4];
/*
* can[offs][len][chr] = can the substring src[offs .. offs+len-1] be
* morphed to character chr?
*
* If so, then first[offs][len][chr] = the smallest possible offset, at
* which the first multiplication may occur.
*/
for (int i = 0; i < n; i++)
for (int j = 0; j < 3; j++)
can[i][1][j] = (j == src[i]);
first[0][n][dst] = -1;
for (int offs = n - 1; offs >= 0; offs--)
for (int len = 2; offs + len <= n; len++) {
for (int c = 0; c < 3; c++)
can[offs][len][c] = 0;
for (int k=1;k<len;k++) for(int c1=0;c1<3;c1++) for(int c2=0;c2<3;c2++) {
if (!can[offs][k][c1] || !can[offs+k][len-k][c2])
continue;
int f, c = mul[c1][c2];
if (k > 1)
f = first[offs][k][c1];
else if (len - k > 1)
f = first[offs+k][len-k][c2];
else
f = offs;
if (!can[offs][len][c] || f < first[offs][len][c]) {
can[offs][len][c] = 1;
first[offs][len][c] = f;
}
}
}
return first[0][n][dst];
}