dynamic programming approach in a non-specific direction calculation - algorithm

I am trying to solve Ball Removal problem on topcoder, pasting the problem statement here as login is required to access this link.
Problem Statement
You have N balls, where N is odd. The balls are numbered from 0 to N-1. In that order, they are arranged into a row going from the left to the right.
In addition to the number, each ball has either the word "left" or the word "right" written on it. For simplicity, we will use the character '<' instead of "left", and the character '>' instead of "right". You are given the labels on all balls as the String label. For each i, character i of label represents the word on ball i.
You will now repeat the following procedure:
Choose a ball that is not at either end of the row of balls.
If the chosen ball has the label '<', remove the chosen ball and also the ball immediately to the left of it. Otherwise, remove the chosen ball and also the ball to the right of it.
Without reordering the remaining balls, push them together to get rid of the gap created in the previous step.
The process ends when only one ball remains in the row. That ball is called the survivor. Note that the numbers on the balls do not change during the process.
Find all possible survivors. Your method must return a String containing exactly N characters. If ball i can be the survivor, character i of the return value must be 'o' (lowercase oh). Otherwise, the corresponding character must be '.' (a period).
Constraints
label will contain between 3 and 49 characters, inclusive.
label will contain an odd number of characters.
Each character of label will be either '>' or '<'.
Examples
"<<>"
Returns: "..o"
Initially, you have three balls. Since you cannot choose balls at the ends of the row, you have to choose ball 1. As its label is '<', you remove balls 0 and 1. Hence the only possible survivor is ball 2.
1)
">>><<"
Returns: "o...o"
If you choose ball 2 or ball 3 first, you have to choose ball 1 next, and the survivor will be ball 0. If you choose ball 1 first, you have to choose ball 3 next, and the survivor will be ball 4.
2)
"<<><<"
Returns: "....o"
3)
"<><<><>"
Returns: "o.....o"
4)
">>><<<>>>>><<<>"
Returns: "o.....o.o.....o"
I am thinking of a dynamic programming approach to this problem, I am thinking of having an boolean array to mark which of the characters have been deleted and then find which is next left and next right but that makes the approach quite inefficient and I have to write a recursive method. For implementing a dynamic programming approach I need to maintain a state. But I am not able to figure out what I should keep as state, in my thinking a state is combination of both current string and current index, but maintaining a string for state doesn't seem correct to me.
One more problem I am facing is that in this case I don't have a particular direction if I change direction result changes also if I move left to right I might need to move right to left also.
Please help me in finding a proper approach to this problem.

The state can be boolean - DP[left][right][isLeftBoundary][isRightBoundary].
This means if the substring starting at left and finishing at right can be fully eliminated.
isLeftBoundary is just a boolean flag if the left symbol is the leftmost of the string.
isRightBoundary is just a boolean flag if the right symbol is the rightmost of the string.
if DP[0][i - 1][1][0] and DP[i + 1][N][0][1] are true, it means the ball at position i can remain.
int canDelete(int l, int r, int st, int en)
{
if (l > r) return 1; //we succeeded in removing the whole string
if (DP[l][r][st][en] != -1)
return DP[l][r][st][en];
int ans = 0;
//i is the last removed ball, which will eliminate the whole string[l, r]
for (int i = l + st; i <= r - en; i++)
{
if (inp[i] == '<') //it will remove a ball to the left, but which one?
{
for (int j = l; j < i; j++) //ball i will remove ball j
{
if (canDelete(l, j - 1, st, 0)
&& canDelete(j + 1, i - 1, 0, 0)
&& canDelete(i + 1, r, 0, en))
ans = 1;
}
}
else
if (inp[i] == '>') //it will remove a ball to the right, but which one?
{
for (int j = i + 1; j <= r; j++) //ball i will remove ball j
{
if (canDelete(l, i - 1, st, 0)
&& canDelete(i + 1, j - 1, 0, 0)
&& canDelete(j + 1, r, 0, en))
ans = 1;
}
}
}
return ans;
}

Related

Winner of the game

I came across this question in recent hiring challenge :
Given N strings, each of '0'-'9' digits and an integer K. Two players A and B play a game as follows :
A plays first and picks any string of first K strings.
Next player, B is allowed to pick string starting with digit equal to last digit in string A picked in his last turn and among next K strings to last picked string by A. e.g. if A picked "045679" indexed i, then B can only pick string starting with digit '9' from strings from indices i+1 to i+K.
The one who can't pick a string loses
Both players play optimally.
We need to tell the winner and the least index of string picked up by winner.
I have seen such problems before and need a suggestion to how to think of such problems. Thanks in advance.
This is similar to the game of nim. You have to go from a winning position into a losing position in order to still win.
We can go backwards: if the last player took the last string, then the player to move now is losing, if the 2nd last string was picked, then the player to move is losing, unless the last digit of 2nd last string and starting digit of last string match, and so on.
With correct implementation you can get O(n) time complexity and O(k) space complexity, because you only need to keep track of a window of size k. Something like this:
// return a winning first move or -1 if there is none
public int solve(String[] strings, int k) {
Queue<Boolean> q = new Deque<>();
int[] lossCount = new int[10];
for (int i = strings.length - 1; i >= 0; i--) {
int start = strings[i].charAt(0) - '0';
int end = strings[i].charAt(strings[i].length() - 1) - '0';
if (i + k + 1 < strings.length && !q.remove())
lossCount[strings[i + k + 1].charAt(0) - '0']--;
boolean win = lossCount[end] == 0;
if (!win)
lossCount[start]++;
else if (i < k)
return i;
q.add(win);
}
return -1;
}

How to go through the elements of a matrix, layer by layer

It is difficult to explain what I want. Lets say I have a matrix of 0 and 1
000000
000000
001100
000000
000000
I want to start from a certain group of ones (this is given in the beginning, and then I want to go outwards.
000000,,,,,,, 000000
011110 OR 001100
010010,,,,,,, 010010
011110,,,,,,, 001100
000000,,,,,,, 000000
The difference is not important, as long as I will go through everything, outwards.
The reason I want to do this is, this matrix of 1 and 0 corresponds to a matrix of some 2D function, and I want to examine the points in that function going outwards. I want to
If i understand the question correctly, basically what you want is to find a group of 1s inside a matrix and invert the group of 1s and all of it's surrounding. This is actually an image-processing problem, so my explanation will be accordingly. Sidenote: the term 'polygon' is here used for the group of 1s in the matrix. Some assumptions made: the polygon is always filled. The polygon doesn't contain any points that are directly at the outer bounds of the matrix (ex.: the point (0 , 2) is never part of the polygon). The solution can be easily found this way:
Step 1: search an arbitrary 1 that is part of the outer bound of the polygon represented by the 1s in the matrix. By starting from the upper left corner it's guaranteed that the returned coordinated will belong to a 1 that is either on the left side of the polygon, the upper-side or at a corner.
point searchArb1(int[][] matrix)
list search
search.add(point(0 , 0))
while NOT search.isEmpty()
point pt = search.remove(0)
//the point wasn't the searched one
if matrix[pt.x][pt.y] == 1
return pt
//continue search in 3 directions: down, right, and diagonally down/right
point tmp = pt.down()
if tmp.y < matrix.height
search.add(tmp)
tmp = pt.right()
if tmp.x < matrix.width
search.add(tmp)
tmp = pt.diagonal_r_d()
if tmp.x < matrix.width AND tmp.y < matrix.height
search.add(tmp)
return null
Step 2: now that the we have an arbitrary point in the outer bound of the polygon, we can simply proceed by searching the outer bound of the polygon. Due to the above mentioned assumptions, we only have to search for 1s in 3 directions (diagonals are always represented by 3 points forming a corner). This method will search the polygon bound clockwise.
int UP = 0
int RIGHT = 1
int DOWN = 2
int LEFT = 3
list searchOuterBound(int[][] matrix , point arbp)
list result
point pt = arbp
point ptprev
//at each point one direction can't be available (determined using the previous found 1
int dir_unav = LEFT
do
result.add(pt)
//generate all possible candidates for the next point in the polygon bounds
map candidates
for int i in [UP , LEFT]
if i == dir_unav
continue
point try
switch i
case UP:
try = pt.up()
break
case DOWN:
try = pt.down()
break
case RIGHT:
try = pt.right()
break
case LEFT:
try = pt.left()
break
candidates.store(i , try)
ptprev = pt
for int i in [0 , 2]
//the directions can be interpreted as cycle of length 4
//always start search for the next 1 at the clockwise next direction
//relatively to the direction we come from
//eg.: dir_unav = LEFT -> start with UP
int dir = (dir_unav + i + 1) % 4
point try = candidates.get(dir)
if matrix[pt.x][pt.y] == 1
//found the first match
pt = try
//direction we come from is the exact opposite of dir
dir_unav = (dir + 2) % 4
break
//no matching candidate was found
if pt == ptprev
return result
while pt != arbp
//algorithm has reached the starting point again
return result
Step 3: Now we've got a representation of the polygon. Next step: Inverting the points around the polygon aswell. Due to the fact that the polygon itself will be filled with 0s later on, we can simply fill up the surrounding of every point in the polygon with 1s. Since there are two options for generating this part of the matrix-state, i'll split up into two solutions:
Step 3.1: Fill points that are diagonal neighbours of points of the polygon with 1s aswell
void fillNeighbours_Diagonal_Included(int[][] matrix , list polygon)
for point p in polygon
for int x in [-1 , 1]
for int y in [-1 , 1]
matrix[p.x + x][p.y + y] = 1
Step 3.1: Don't fill points that are diagonal neighbours of points of the polygon
void fillNeighbours_Diagonal_Excluded(int[][] matrix , list polygon)
for point p in polygon
matrix[p.x - 1][p.y] = 1
matrix[p.x + 1][p.y] = 1
matrix[p.x][p.y - 1] = 1
matrix[p.x][p.y + 1] = 1
Step 4: Finally, last step: Invert all 1s in the polygon into 0s. Note: I'm too lazy to optimize this any further, so this part is implemented as brute-force.
void invertPolygon(int[][] matrix , list polybounds)
//go through each line of the matrix
for int i in [0 , matrix.height]
sortedlist cut_x
//search for all intersections of the line with the polygon
for point p in polybounds
if p.y == i
cut_x.add(p.x)
//remove ranges of points to only keep lines
int at = 0
while at < cut_x.size()
if cut_x.get(at - 1) + 1 == cut_x.get(at)
AND cut_x.get(at) == cut_x.get(at + 1) - 1
cut_x.remove(at)
--at
//set all points in the line that are part of the polygon to 0
for int j in [0 , cut_x.size()[ step = 2
for int x in [cut_x.get(j) , cut_x.get(j + 1)]
matrix[x][i] = 0
I hope you understand the basic idea behind this. Sry for the long answer.

Sort polygon's points for drawing

I have a matrix (0 means nothing, 1 means terrain) that represents a level in my game. The matrix corresponds to a grid that my screen is broken up into, and indicates where my terrain goes.
My terrain is actually composed of 4 points in the corners of each block within the grid. When you have multiple blocks that are connected, I use a merge-cell algorithm that removes the duplicate points and any interior points. The result is that I end up with a list of points representing only the outer edges of the polygon.
To draw this polygon, I need the points to be in some sort of order (either clockwise or counter-clockwise) such that each point is followed by it's neighboring point. Obviously the first and last points need to be neighbors. Since this is all in a grid, I know the exact distance between neighboring points.
The problem is that I am having trouble coming up with an algorithm that allows me to "walk" around the edge of the polygon while putting the points in order. I believe there should be a way to utilize the fact that I have the matrix representing the geometry, meaning there is only 1 possible way to draw the polygon (even if it is concave).
I have tried several approaches using greedy-type algorithms, but can't seem to find a way to know, in every case, which direction I want to travel in. Given that any particular point can have up to 3 neighbors (the fourth isn't included because it is the "starting" point, meaning that I have already sorted it) I need a way of knowing which way to move.
Update
Another approach that I have been trying is to sort the points by their X (with tiebreaker of Y) which gives me the topmost/leftmost edge. It also guarantees that I am starting on an outer edge. However, I'm still struggling to find an algorithm that guarantees that I stay on the outside without crossing over.
Here is an example matrix:
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0
Which corresponds to this (black dots represent my points):
First of all please consider that for a general matrix the output can be composed of more than one closed loop; for example boundaries of the matrix
form three distinct loops, one of them placed inside another.
To extract these loops the first step is to build a map of all "walls": you have a vertical wall each time the content of one cell is different from the next cell on the same row; you have instead an horizontal wall when the content is different from the same cell in the next row.
data = [[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 1, 0, 1, 1, 0, 0 ],
[ 0, 1, 0, 0, 1, 0, 1, 1, 1, 0 ],
[ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]]
rows = len(data)
cols = len(data[0])
walls = [[2*(data[r][c] != data[r][c+1]) + (data[r][c] != data[r+1][c])
for c in range(cols-1)]
for r in range(rows-1)]
In the example above I'm using two bits: 0x01 to mark horizontal walls and 0x02 to mark vertical walls. For a given (r, c) cell the walls are the right and bottom wall of the cell.
For simplicity I'm also assuming that the interesting areas are not touching the limits of the matrix; this can be solved by either adding extra rows and cols of zeros or by wrapping matrix access in a function that returns 0 for out-of-matrix virtual elements.
To build the list of boundaries you need to simply start from any point on a wall and move following walls, removing the walls from the map as you process them. When you cannot move any more a cycle has been completed (you're guaranteed to complete cycles because in a graph built in this way from a matrix of inside/outside flags the degree is guaranteed to be even in all vertices).
Filling all those cycles simultaneously using odd-even filling rules is also guaranteed to reproduce the original matrix.
In the code following I'm using r and c as row/col index and i and j instead to represent points on the boundary... for example for cell (r=3, c=2) the schema is:
where the red wall corresponds to bit 0x02 and the green wall to bit 0x01. The walls matrix has one row and one column less than the original data matrix because it's assumed that no walls can be present on last row or column.
result = []
for r in range(rows-1):
for c in range(cols-1):
if walls[r][c] & 1:
i, j = r+1, c
cycle = [(i, j)]
while True:
if i < rows-1 and walls[i][j-1] & 2:
ii, jj = i+1, j
walls[i][j-1] -= 2
elif i > 0 and walls[i-1][j-1] & 2:
ii, jj = i-1, j
walls[i-1][j-1] -= 2
elif j < cols-1 and walls[i-1][j] & 1:
ii, jj = i, j+1
walls[i-1][j] -= 1
elif j > 0 and walls[i-1][j-1] & 1:
ii, jj = i, j-1
walls[i-1][j-1] -= 1
else:
break
i, j = ii, jj
cycle.append((ii, jj))
result.append(cycle)
Basically the code starts from a point on a boundary and the checks if it can move on a wall going up, down, left or right. When it cannot move any more a cycle has been completed and can be added to the final result.
The complexity of the algorithm is O(rows*cols), i.e. it's proportional to the input size and it's optimal (in big-O sense) because you cannot compute the result without at least reading the input. This is easy to see because the body of the while cannot be entered more times than the total number of walls in the map (at each iteration a wall is removed).
Edit
The algorithm can be modified to generate as output only simple cycles (i.e. paths in which each vertex is visited only once).
result = []
index = [[-1] * cols for x in range(rows)]
for r in range(rows-1):
for c in range(cols-1):
if walls[r][c] & 1:
i, j = r+1, c
cycle = [(i, j)]
index[i][j] = 0
while True:
if i > 0 and walls[i-1][j-1] & 2:
ii, jj = i-1, j
walls[i-1][j-1] -= 2
elif j > 0 and walls[i-1][j-1] & 1:
ii, jj = i, j-1
walls[i-1][j-1] -= 1
elif i < rows-1 and walls[i][j-1] & 2:
ii, jj = i+1, j
walls[i][j-1] -= 2
elif j < cols-1 and walls[i-1][j] & 1:
ii, jj = i, j+1
walls[i-1][j] -= 1
else:
break
i, j = ii, jj
cycle.append((ii, jj))
ix = index[i][j]
if ix >= 0:
# closed a loop
result.append(cycle[ix:])
for i_, j_ in cycle[ix:]:
index[i_][j_] = -1
cycle = cycle[:ix+1]
index[i][j] = len(cycle)-1
This is implemented by adding to the output a separate cycle once the same vertex is met twice in the processing (the index table stores for a given i,j point the 0-based index in the current cycle being built).
This seems like it would work to me:
For every filled square, check which of its neighbours are filled. For those that aren't, add the appropriate edges to a list of edges. Generate those edges as directed, either clockwise or anticlockwise as you prefer.
To construct a full path, start by pulling any edge from the set and add it to the path. It has an order so look at the second vertex. Find the edge in the set with the first vertex that is equal to that second vertex. Pull that edge from the set and add it to the path. Continue until the path is closed.
Repeat to generate a list of paths. A simple polygon should end up as one path. A complex polygon — one with holes in the middle in this case — will be several.
I guess there are different ways to do this, I suppose there is quite simple one for case when diagonal connected cells counted as different contours:
You just need too keep cell and corner direction. For example you started from upper right corner of some earth cell (it supposed that either upper or right cell, or both are nothing if it is bourder) and want to go clockwise.
If cell to the right is earth, than you change current cell to it and change corner to upper left (it is the same point). Then you go to next iteration.
In other case, if you started from upper right corner of some earth cell and want to go clockwise. If cell to the right is NOT earth than you don't change current cell and change corner to bottom right, (it's next point)
So you also have symmetrical situation for other three possible corners, and you can go to next iteration until returning to start point.
So here is pseudo-code I wrote, it uses the same indexing as picture uses, and supposes that all cells along borders are free, otherwise you will need to check if index id not out of range.
I will also need additional array with almost the same dimensions as matrix to mark processed contours, it need to be 1 cell wider than matrix cause I'm going to mark vertical lines, and each vertical line is supposed to have coordinates of cell to the right of it. Note that there are only 2 cases midst 8 dwscribed above when you need to mark vertical line.
int mark[,] = new int[height,width+1]
start_i = i = 0;
start_j = j = 0;
direction = start_direction = top_left;
index = 0;
//outer cycle through different contours
while(true)
{
++index;
//scanning for contours through all the matrix
//continue from the same place, we stopped last time
for(/*i = i*/; i < n; i++)
{
for(/*j = j*/; j < n; j++)
{
//if we found earth
if(m[i,j] == 1)
{
//check if previous cell is nothing
//check if line between this and previous contour doesn't already added
if(m[i,j - 1] == 0 && mark[i,j] == 0)
{
direction = bottom_left;
break;
}
//the same for next cell
if(m[i,j + 1] == 0 && mark[i,j+1] == 0)
{
direction = top_right;
break;
}
}
}
//break if we found contour
if(i != start_i || j != start_j)
break;
}
//stop if we didn't find any contour
if(i == start_i && j == start_j)
{
break;
}
polygon = new polygon;
start_i = i;
start_j = j;
start_direction = direction;
//now the main part of algorithm described above
do
{
if(direction == top_left)
{
if(n(i-1,j) == 1)
{
direction = bottom_left;
position = (i-1,j)
}
else
{
direction = top_right;
polygon.Add(i,j+1);
}
}
if(direction == top_right;)
{
if(n[i,j + 1] == 1)
{
direction = top_left;
position = (i,j + 1)
}
else
{
direction = bottom_right;
mark[i, j + 1] = index;//don't forget to mark edges!
polygon.Add(i+1,j+1);
}
}
if(direction == bottom_right;
{
if(n[i+1,j] == 1)
{
direction = top_right;
position = (i+1,j)
}
else
{
direction = bottom_left;
polygon.Add(i+1,j);
}
}
if(direction == bottom_left)
{
if(n[i,j - 1] == 1)
{
direction = bottom_right;
position = [i,j - 1]
}
else
{
direction = top_left;
mark[i, j] = index;//don't forget to mark edges!
polygon.Add(i,j);
}
}
//and we can stop as we reached the starting state
}while(i != start_i || j != start_j || direction != start_direction);
//stop if it was last cell
if(i == n-1 && j == n- 1)
{
break;
}
}
Also you may need to know which contour is inside which, and you mat need a stack to keep what contours you are inside while you are scanning, so every time you are crossing the existing contour you need to add it to the stack or remove if it is already at the top of the stack.
It will cause the next changes in code:
...
//continue from the same place, we stopped last time
for(/*i = i*/; i < n; i++)
{
for(/*j = j*/; j < n; j++)
{
if(mark[i,j] != 0)
{
if(stack.top() == mark [i,j])
{
stack.pop();
}
else
{
stack.push(mark [i,j]);
}
}
//if we found earth
if(m[i,j] == 1)
{
...
If your matrix can contain random patterns, the answer is far more complicated than it seems.
For one thing they may be an arbitrary number of distinct polygons, and each of them might be hollow.
Besides, finding the contour of a region (even with no holes) is of little help for drawing the surface. Your GPU will eventually need triangles, which means you will need to decompose your polygons into rectangles.
Finding an optimal decomposition of a hollow bunch of squares (i.e. the smallest set of rectangles that will cover them all) is a well studied NP-complete problem with no known solution.
There exist algorithms to find an optimal decomposition of such shapes with no holes, but they are very complex.
A greedy algorithm is much easier to implement and usually yields acceptable results.
So I would do a greedy search on your matrix, collecting rectangles until all "1" values have been visited. Turning these rectangles into coordinates should be easy enough, since you know exactly where the top left and bottom right corners are.
The greedy scan will look like:
while your matrix is not empty
move to first "1" value. This is the rectangle top left corner
from this corner, extend the rectangle in x and y to maximize its surface
store the rectangle in a list and clear all corresponding "1" values

4x4 2D character matrix permutations

I have a 4x4 2D array of characters like this:
A B C D
U A L E
T S U G
N E Y I
Now, I would need to find all the permutations of 3 characters, 4 characters, etc till 10.
So, some words that one could "find" out of this are TEN, BALD, BLUE, GUYS.
I did search SO for this and Googled, but to no concrete help. Can you push me in the right direction in which algorithm I should learn (A* maybe?). Please be gentle as I'm no algorithms guy (aren't we all (well, at least a majority :)), but am willing to learn just don't know where exactly to start.
Ahhh, that's the game Boggle isn't it... You don't want permutations, you want a graph and you want to find words in the graph.
Well, I would start by arranging the characters as graph nodes, and join them to their immediate and diagonal neighbours.
Now you just want to search the graph. For each of the 16 starting nodes, you're going to do a recursion. As you move to a new node, you must flag it as being used so that you can't move to it again. When you leave a node (having completely searched it) you unflag it.
I hope you see where this is going...
For each node, you will visit each of its neighbours and add that character to a string. If you have built your dictionary with this search in mind, you will immediately be able to see whether the characters you have so far are the beginning of a word. This narrows the search nicely.
The kind of dictionary I'm talking about is where you have a tree whose nodes have one child for each letter of the alphabet. The beauty of these is that you only need to store which tree node you're currently up to in the search. If you decide you've found a word, you just backtrack via the parent nodes to work out which word it is.
Using this tree style along with a depth-first graph search, you can search ALL possible word lengths at the same time. That's about the most efficient way I can think of.
Let me just write a pseudocodish function for your graph search:
function FindWords( graphNode, dictNode, wordsList )
# can't use a letter twice
if graphNode.used then return
# don't continue if the letter not part of any word
if not dictNode.hasChild(graphNode.letter) then return
nextDictNode = dictNode.getChild(graphNode.letter)
# if this dictionary node is flagged as a word, add it to our list
nextDictNode.isWord()
wordsList.addWord( nextDictNode .getWord() )
end
# Now do a recursion on all our neighbours
graphNode.used = true
foreach nextGraphNode in graphNode.neighbours do
FindWords( nextGraphNode, nextDictNode, wordsList )
end
graphNode.used = false
end
And of course, to kick the whole thing off:
foreach graphNode in graph do
FindWords( graphNode, dictionary, wordsList )
end
All that remains is to build the graph and the dictionary. And I just remembered what that dictionary data structure is called! It's a Trie. If you need more space-efficient storage, you can compress into a Radix Tree or similar, but by far the easiest (and fastest) is to just use a straight Trie.
As you not define preferred language I implemented on C#:
private static readonly int[] dx = new int[] { 1, 1, 1, 0, 0, -1, -1, -1 };
private static readonly int[] dy = new int[] { -1, 0, 1, 1, -1, -1, 0, 1 };
private static List<string> words;
private static List<string> GetAllWords(char[,] matrix ,int d)
{
words = new List<string>();
bool[,] visited = new bool[4, 4];
char[] result = new char[d];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
Go(matrix, result, visited, d, i, j);
return words;
}
private static void Go(char[,] matrix, char[] result, bool[,] visited, int d, int x, int y)
{
if (x < 0 || x >= 4 || y < 0 || y >= 4 || visited[x, y])
return;
if (d == 0)
{
words.Add(new String(result));
return;
}
visited[x, y] = true;
result[d - 1] = matrix[x, y];
for (int i = 0; i < 8; i++)
{
Go(matrix, result, visited, d - 1, x + dx[i], y + dy[i]);
}
visited[x, y] = false;
}
Code to get results:
char[,] matrix = new char[,] { { 'A', 'B', 'C', 'D' }, { 'U', 'A', 'L', 'E' }, { 'T', 'S', 'U', 'G' }, { 'N', 'E', 'Y', 'I' } };
List<string> list = GetAllWords(matrix, 3);
Change parameter 3 to required text length.
It seems you just use the 4x4 matrix as an array of length 16. If it is the case, you can try the recursive approach to generate permutations up to length k as follows:
findPermutations(chars, i, highLim, downLim, candidate):
if (i > downLim):
print candidate
if (i == highLim): //stop clause
return
for j in range(i,length(chars)):
curr <- chars[i]
candidate.append(curr)
swap(chars,i,j) // make it unavailable for repicking
findPermutations(chars,i+1,highLim,downLim,candidate)
//clean up environment after recursive call:
candidate.removeLast()
swap(chars ,i, j)
The idea is to print each "candidate" that has more chars then downLim (3 in your case), and terminate when you reach the upper limit (highLim) - 10 in your case.
At each time, you "guess" which character is the next to put - and you append it to the candidate, and recursively invoke to find the next candidate.
Repeat the process for all possible guesses.
Note that there are choose(10,16)*10! + choose(9,16)*9! + ... + choose(3,16)*3! different such permutations, so it might be time consuming...
If you want meaningful words, you are going to need some kind of dictionary (or to statistically extract one from some context) in order to match the candidates with the "real words".

Minimum Window for the given numbers in an array

Saw this question recently:
Given 2 arrays, the 2nd array containing some of the elements of the 1st array, return the minimum window in the 1st array which contains all the elements of the 2nd array.
Eg :
Given A={1,3,5,2,3,1} and B={1,3,2}
Output : 3 , 5 (where 3 and 5 are indices in the array A)
Even though the range 1 to 4 also contains the elements of A, the range 3 to 5 is returned Since it contains since its length is lesser than the previous range ( ( 5 - 3 ) < ( 4 - 1 ) )
I had devised a solution but I am not sure if it works correctly and also not efficient.
Give an Efficient Solution for the problem. Thanks in Advance
A simple solution of iterating through the list.
Have a left and right pointer, initially both at zero
Move the right pointer forwards until [L..R] contains all the elements (or quit if right reaches the end).
Move the left pointer forwards until [L..R] doesn't contain all the elements. See if [L-1..R] is shorter than the current best.
This is obviously linear time. You'll simply need to keep track of how many of each element of B is in the subarray for checking whether the subarray is a potential solution.
Pseudocode of this algorithm.
size = bestL = A.length;
needed = B.length-1;
found = 0; left=0; right=0;
counts = {}; //counts is a map of (number, count)
for(i in B) counts.put(i, 0);
//Increase right bound
while(right < size) {
if(!counts.contains(right)) continue;
amt = count.get(right);
count.set(right, amt+1);
if(amt == 0) found++;
if(found == needed) {
while(found == needed) {
//Increase left bound
if(counts.contains(left)) {
amt = count.get(left);
count.set(left, amt-1);
if(amt == 1) found--;
}
left++;
}
if(right - left + 2 >= bestL) continue;
bestL = right - left + 2;
bestRange = [left-1, right] //inclusive
}
}

Resources