I'm having trouble with my homework assignment(C++). I'm not asking for the complete solution, but tilt in the right direction could be helpful. :)
I have a NxN board (max N = 100) and a 1x2 figure (cube) on that board. The cube is painted red on the one side and blue on the other. Default position for the cube is left upper angle of the board, blue side up:
B B . .
. . . .
. . . .
. . . .
(4x4 example, B stands for blue)
There could be stones (obstacles) on the blackboard.
Moves I can make with my figure:
rotating it for 90/180/270 degrees clockwise
you can flip the cube around its right/left/upper/lower edge, changing its ''upward color''
For an example, using flip right on the default position:
. . R R
. . . .
. . . .
. . . .
and then using rotate 90:
. . R .
. . R .
. . . .
. . . .
and then using flip left:
. B . .
. B . .
. . . .
. . . .
Of course, when rotating or flipping, you cannot land on the stone.
So, the problem is - for any given configuration of the board (figure position and stone positions) write a program that will ''bring the cube home'' in the default position (blue side upwards!) using minimal number of moves and return 1 if that's possible or return 0 if that's impossible.
I find this problem interesting, but I have to admit I'm slightly confused with it. Especially the blue side/red side part. I can't really figure out how to ''translate'' those moves I can use in the language of usual shortest path algorithms (and I never used any of these).
So, I would be grateful for every piece of advice you can give! :)
First, since you are asked to find the exact optimal path, I would go with Dijksta's algorithm.
For this algorithm, you'll need:
A function which gives the next
possible move.
A function which tell you if a position was already
visited.
A function which tell you the total cost of each path.
And of course a function which tell you when you've reached the final
position
Given an initial position, your cube can reach exactly 7 new positions. It's easy to pick which ones are possible.
G is simply the number of moves you've made so far + 1 for the next move :)
I would use a hashtable to keep track of the visited position. (This is probably the most difficult function to write), but you don't need to over think it right now. A simple vector and a term-by-term comparison would do. You can optimize this once your code is running.
And finally, you need to check if the cube is in its initial position blue side upwards.
You can interpret each possible 1x2 block and a color (red or blue) combination as a vertex and moves as edges. If it is possible to reach a particular 1x2 block and color combination (vertex) from some other combination in one move then there is a connection (edge) between those two combinations. Then you have to find shortest path between the given configuration and "home" configuration in the resulting graph (probably Breadth-first search since cost of the move is the same no matter what move you perform).
And if want to go further you can use advanced graph search algorithms that use heuristics during the graph traversal (heuristic being the minimum amount of moves needed to reach destination assuming there are no obstacles on the blackboard). For example you can use A* algorithm.
When dealing with this kind of problems, the first thing to do is to find a representation of the state of your problem.
In this case, you need:
Two integers which represents the top-left position of your figure
One boolean which represents the color of the figure (red/blue)
One boolean which represents the orientation of the figure (horizontal/vertical)
If you are familiar with bitmasks, you should use just a 32 bit integer to do this (8 bits for x position, 8 bits for y position, 2 bits for the rest).
In this way you don't need to implement a comparison operator.
OR
You define a simple struct (call it state) with these 3 information and a strict-ordering comparison on this (this is only needed to put state in std::set.
After this, you can solve this problem using a BFS.
To do that, you need:
An std::map<state,state> to store the position you already visited in the key, and the position you came from in the value (replace map with unordered_map if you can use c++11 and you use a bitmask to store your state)
A std::queue<state> in which push and pop up the states to be processed.
Some code to determine every possible state reachable from a given one (i.e. implements all the possible moves, taking care of the board dimension)
Pseudo code:
map<state,state> visited;
queue<state> to_be_processed;
visited.insert( initial_state,initial_state); //you are not coming from anywhere
to_be_processed.push ( initial_state);
while(!to_be_processed.empty()) {
state cur = to_be_processed.pop();
if ( cur == end_state) //you are done
{
//to get the path from initial_state to end_state you have just to walk visited in the inverse order.
return 1;
}
for ( i = every possible state reachable from cur) {
if (visited.count(i) != 0) continue; //already visited
to_be_processed.push(i);
visited.insert(i,cur); //i has been visited, and you reached i from cur
}
}
return 0; //if you get here, no way
The presence of obstacles make just the problem more difficult to code, but is no conceptually different.
Note that in this case BFS works because the cost you pay for going from one state to another is always the same.
Related
An "elbow connector" in MS-Word is a 3-segment line with a control point in the middle as shown
where if I move the yellow control point sideways, then the length of the two lines on either side change accordingly while the end points remain the same. (Please ignore the "2" in the picture)
I am trying to understand how this works so that I can re-create this. Is there a "line equation" for such a line? I have some points (x,y) that are already in the shape of this elbow connector but I would like to incorporate the functionality of changing the lines on either side by controlling the control point. How would I go about re-creating this?
By dissecting the lines like:
For moving the center(M) only sideways, length of lines 2 and 3 remains the same so the problem becomes how to calculate length (and direction) of the lines 1 and 4.
That can be calculated like:
line1_length = B.x - M.x;
line4_length = M.x - A.x;
For directions a comparison should first be made like:
if(B.x > M.x)...
.
.
.
if(M.x > A.x)...
.
.
.
Beginning points is already known as the position of A and the position of B. By knowing the lengths and directions of lines 1 and 4, the end points can be determined.
Good luck!
One can enter the matrix from any cell, and each cell contains some clue regarding the position of the cell needed to be found like
Total 8 types of clues can be present:
Exactly Above it
Exactly Below it
Exactly To the Right
Exactly To the Left
In the Top Right Region
In the Bottom Right Region
In the Top Left Region
In the Bottom Left Region
In each step he can move to one adjacent cell as per the above eight movements.
My question is minimum no. of steps he needs to take to reach that cell in the worst case.
Test Case :
2 2 : 1
3 3 : 1
My solution looked like this :
I thought If I start from the middle region of the matrix , then I would have to take the minimum no. of steps.
cin >> n >> m ;
ans = max ( n/2 , m/2 ) ;
But obviously it was wrong.
The correct solution looked like this
cin >> n >> m ;
ans = log( max(n,m) , 2) ; //base 2
Can anyone explain this ?
The question can be found here : http://www.codechef.com/TRNT2014/problems/TR001
These two items:
In each step he can move to one adjacent cell as per the above eight movements.
The correct solution looked like this:
ans = log( max(n,m) , 2) ; //base 2
are in contradiction. If the first is true, then your solution is correct. If the second is true, then the first must be false, and he can jump to any cell (or at least a cell (n/4,m/4) away).
Contrary to the description above, the linked description does not seem to limit which box you can check at any time.
As such, the correct approach seems to be basically a 2D binary search. Start at the middle box. If (for example) the clue says the correct box is up and to the right, move half the distance toward that corner. At that point, it might say (for example) that the correct box is up and to the left. If so, you move half the distance that direction.
In short, it's a binary search, except that the result at each point is a vector--a direction and a distance--rather than just a distance as you'd have in a typical 1D binary search.
I'm writing a program that is supposed
to sort a number of square tiles (of which
each side is colored in one of five colors—red, orange,
blue, green and yellow), that are laying next to each other
(eg 8 rows and 12 columns) in a way that as many sides with
the same color connect as possible.
So, for instance, a tile with right side colored
red should have a tile on the right that has a red left-side.)
The result is evaluated by counting how many non-matching pairs
of sides exist on the board. I'm pretty much done with the actual program;
I just have some trouble with my sorting algorithm. Right now I'm using
Bubble-sort based algorithm, that compares every piece on the board
with every other piece, and if switching those two reduces the amount of
non-matching pairs of sides on the board, it switches them. Here a
abstracted version of the sorting function, as it is now:
for(int i = 0 ; i < DimensionOfBoard.cx * DimensionOfBoard.cy ; i++)
for(int j = 0 ; j < DimensionOfBoard.cx * DiemsionOfBoard.cy ; j++)
{
// Comparing a piece with itself is useless
if(i == j)
continue;
// v1 is the amount of the nonmatching sides of both pieces
// (max is 8, since we have 2 pieces with 4 sides each (duh))
int v1 = Board[i].GetNonmatchingSides() + Board[j].GetNonmatchingSides();
// Switching the pieces, if this decreases the value of the board
// (increases the amount of nonmatching sides) we'll switch back)
SwitchPieces(Board[i], Board[j]);
// If switching worsened the situation ...
if(v1 < Board[i].GetNonmathcingSides() + Board[j].GetNonmatchingSides())
// ... we switch back to the initial state
SwitchPieces(Board[i], Board[j]);
}
As an explanation: Board is a pointer to an array of Piece Object. Each Piece has
four Piece-pointers that point to the four adjacent pieces (or NULL, if the Piece is
a side/corner piece.) And switching actually doesn't switch the pieces itself, but
rather switches the colors. (Instead of exchanging the pieces it scrapes off the color
of both and switches that.)
This algorithm doesn't work too bad, it significantly improves the value of the
board, but it doesn't optimize it as it should. I assume it's because side and corner
pieces can't have move than three/two wrong adjacent pieces, since one/two side(s)
are empty. I tried to compensate for that (by multiplying Board[i].GetMatchingPieces()
with Board[i].GetHowManyNonemptySides() before comparing), but that didn't help a bit.
And that's where I need help. I don't know very many sorting algorithms, let alone
those that work with two-dimensional arrays. So can anyone of you know about
an algorithmic concept that might help me to improve my work? Or can anyone see a
problem that I haven't found yet? Any help is appreciated. Thank you.
if there was a switch you have to re-evaluate a board, because there might be previous positions where now you could find an enhancement.
Note that you are going to find only a local minimum with those swappings. You might won't be able to find any enhancements but that doesn't mean that's the best board configuration.
One way to find a better configuration is to shuffle a board and search for a new local minumum, or use an algorithm-skeleten that allows you to make bigger jumps in the state, eg: Simulated annealing.
Firstly I would like to accept that it is a homework question , but then I know how to code AB-pruning from the algorithm of it . The problem is how to apply it on a grid of numbers where the game can go on in any direction (right , left , up and down ) , thus how will be the tree formed .
Sorry for being a bit vague here , if more info is required then do inquire , I will provide it .
You question is very vague so I can only guess what you are asking:
Are you talking about a game where the player can only move in one of those 4 directions on each turn? If that is the case, your Node will be an (x, y) position of your player on the grid, and each node will branch 4 times (once for each direction) plus maybe 1 if you can stay still.
You say you already know how to code AB-pruning, so is that enough?
The problem is as follows: A wanderer begins on the grid coordinates (x,y) and wants to reach the coordinates (0,0). From every gridpoint, the wanderer can go 8 steps north OR 3 steps south OR 5 steps east OR 6 steps west (8N/3S/5E/6W).
How can I find the shortest route from (X,Y) to (0,0) using breadth-first search?
Clarifications:
Unlimited grid
Negative coordinates are allowed
A queue (linked list or array) must be used
No obstacles present
The algorithm for this problem would be:
For each axis, step towards it until your position on the other axis is 0.
Pseudocode:
while (x!=0) {
if (x>0) x-=6;
else x+=5;
}
while (y!=0) {
if (y>0) y-=8;
else y+=3;
}
However, I don't understand why you need to search for a route - it's not that complicated.
As "thejh" remarked there's no need for a search, but your assignment calls for one.
A reasonable approach is
Analyze. Is it all possible for arbitrary (x, y) starting position? Checking the allowed moves you see that they can be combined to yield 1-step horizontal moves, and 1-step vertical moves, so the answer to that is yes (for your hand-in provide the details of this).
Figure out what "breadth-first search" is. Wikipedia is your friend (although, if you have access to a university library, I really do recommend Patrick Henry Winston's old Artifical Intelligence, it's really good, very lucid explanations). Try it out with some simpler problem.
Do the assignment's problem in just about the same way. Ask here if you encounter any technical C++ problem.
Cheers & hth.,
Here's my answer (really based off of thejh's answer) that uses a queue:
//set x to start position
//set y to start position
do {
if (x<0) Queue.Push(8N);
if (x>0) Queue.Push(3S);
if (y<0) Queue.Push(5E);
if (y>0) Queue.Push(6W);
while (!Queue.Empty())
{
Move(Queue.Pop());
}
} while (x && y);
It's convoluted, but follows the directions.
I'm going to go ahead and answer my own question for future reference.
Psuedocode:
while (true) {
if (destination reached)
break;
addToQueue(go north);
addToQueue(go south);
addToQueue(go east);
addToQueue(go west);
getNextFromQueue;
}
It should also be noted that the execution time for this application grows very, very fast, so test it out with small coordinate values. For example, the coordinates (1,1) gives 7 levels of breadth and requires 16384 iterations.