This is a homework question (sorry, I know these are frowned upon), but neither I nor the teacher actually knows how to solve it efficiently, so I wanted to put it up here to see if the wonderful brains on SO could help us out.
An array of unspecified size is given, containing random numbers. It must be sorted into increasing order. Each element can be either moved to an adjacent empty space, or moved on top of an adjacent larger element. I need to write a method that returns the minimum number of moves needed to sort the given array.
The question has been labeled 'optional', since the teacher realized the problem was far too difficult, but I'm curious how it might be solved. Any suggestions for arrays of any size (it can be for arrays of length 3 for all I care) are appreciated.
EDIT: Thanks for pointing out that this was unclear. I'm using the array to represent a hypothetical real world situation. Let's use the example of coins: they are all laid out on a table in a row, and there are only a specified number of 'spaces' they can be put in. But they can be put on top of adjacent larger coins, or slide to an adjacent empty space (which has been vacated by a coin that had presumably moved on top of a pile).
I decided to examine the problem with a few assumptions/changes, because it made it a more interesting problem to me:
1) You can move elements left or right from any part of a pile.
2) You can stack an element onto a pile no matter if it's bigger, smaller or the same size.
3) The array is considered sorted as long as you never encounter a bigger number before a smaller number no matter how you go through stacks. So _ 11 2 3 is sorted but _ _ 12 3 is not because you could interpret the 2 as being before the 1.
This leads to a very interesting problem, in spite of this axiom:
Axiom A: The order in which you make moves is irrelevant, and can be re-arranged in any way to still achieve the same final result.
Axiom Ab: If the array has no repeats in it, then simply move every element towards its final position.
In particular, I developed a strategy hoping that you could solve it with only local examination and no recursiveness/backtracking, but I've proven that this is fruitless and will show it later.
My strategy is:
1) Proceed from left to right looking for pairs that are flipped the wrong way (a higher number before a lower number).
2a) When you find one, if there is an empty spot or a stack that the right hand value could immediately fill, move it left until it does fill it.
2b) Else, move the left value right one. This creates a situation where you have a stack of indifferent numbers - first, compare the value you moved right to the value on its new right according to the logic of 1) before comparing downwards.
2bii) Treat a downwards comparison the same way as a pair comparison - move the lower value left if it can fit an empty spot or stack, else move the higher value right and continue.
Examples:
1231 -> we shift 1b left because it will fit onto a stack. 11 2 3 _
1321 -> we shift 3 right because 2 will not fit into an empty spot/onto a stack. we shift 1b left twice because it will fit into an empty spot/fit onto a stack, then we shift 3 right because 2 will not fit into an empty spot/onto a stack. 1 1 2 3
1132 -> we shift 3 right as 2 can't go left. we shift 2 left because it will fit in an empty spot. 1 1 2 3
2311 -> we shift 3 right as 1a can't go left. we shift 1b left twice because it will fit in an empty spot. we shift 1a left because it will stack. we shift 2 right because 1a1b can't go left. we shift 1a2b left as it will fill an empty spot. 11 2 3 _
However, we run into a problem with these two starting arrays:
23411 10 moves optimal, 2r 3r 4r 1al*3 1bl*4 to make 11 2 3 4 _.
23111 9 moves optimal, 2r*3 3r*3 1bl 1cl*2 to make _ _ 111 2 3 - the opposite of the 23411 strategy! We move the 1s less and the 23 more because there are more 1s and so we save moves moving them as little as possible.
Which shows that we can't JUST do a simple local comparison to solve this new problem.
I'm still thinking about this problem, it seems non-trivial in an intriguing way, and I hope some of you enjoy contemplating this with me :)
I assume:
"sorted" means there is a single stack left
we can only move a stack onto another stack if the largest number in the source stack is smaller than the smallest number in the destination stack (or equivalently: stacks must be sorted with smaller numbers on top, and moving a stack onto another moves the entire stack on top of the other)
Then, there is obviosly no solution if the array contains a number more than once. Also, the magnitude of the numbers doesn't matter, only their rank does. Without loss of generality, we can therefore assume that the array contains the numbers 1..n in arbitrary order. Also, to determine the possible moves, only the top of bottom of the stacks matter. It is therefore sufficient to store:
int[] bottom;
int[] top;
Since we can not take stacks apart, we may only move stack i onto stack j if bottom[i] + 1 == top[j], or we'll end up in an unsolvable state. If however, we are in a game state where such a move is possible, it is optimal to perform it immediately, because eventually we'll have to combine these stacks, and moving an individual stack around is cheaper than moving two stacks around.
The only degree of freedom therefore is how to move the stacks into position with the least number of moves. At this time, I don't see an obvious greedy algorithm for that, so finding the optimal solution may require encoding the positions of the game into a graph, and apply a shortest path algorithm to that graph to find the shortest sequences of moves.
EDIT: Given that everyone seems to be solving a different problem, I'll state the problem I'm solving (which I believe to be the correct one (don't we all?)): (using disks to hopefully make things easier to understand)
Given n piles, each containing exactly 1 disk each, order these disks in increasing order of size. The end result must have each pile containing 1 disk each. The only allowed operation is to move a single disk from the top of one pile to the top of an adjacent pile, subject to the constraint that no disk may be placed on top of a smaller disk. Moving a disk to an empty pile or moving the last disk from a pile is allowed. There are always n piles, thus: (1) New piles may not be created, so a disk may not be moved outside the bounds of the original sequence. (2) Empty piles remain, so if the adjacent position is empty, the disk may not be moved over that position without first being moved onto that position.
Note:
A disk with a diameter of x = a number x.
This may not be the most efficient solution, but it should work and may give someone something to work off of.
It's a purely iterative process - after every step we end with all stacks having size 1; this may be a fundamental inefficiency with this approach.
Solution:
I'll use 1, 2 and 5 to illustrate the below, but this is just to indicate size ordering, it holds the same for any other numbers with the same ordering.
Repeat until sorted:
Find the biggest element not already in the correct position (5 in this case)
(Actually it doesn't have to be the biggest, just anything in the below form, but be careful not to move elements past where they should be)
We have 2 cases:
It's at the left-most position, we have 2 cases:
512... - move 1 right, move 5 right, move 1 2 left, end with 152
521... - move 1 2 left, move 2 right, move 1 2 right, move 5 right, move 1 2 left, end with 152
It's not at the left-most position, we have 2 cases:
...251... - move 1 2 left, move 5 right, move 1 right, end with 215
...152... - move 2 left, move 1 right, move 1 right, move 2 left, end with 251 (after which we do steps from previous case)
EDIT 2:
A more efficient solution:
Find the smallest disk not in the right position
Put it on top of the disk to the right
Shift all disks to the left of that disk 1 position right
Shift the smallest disk all the way to the left (until you encounter a smaller disk which would already be in the right place)
Possible preprocessing step: Sort to a separate list to efficiently find smallest elements
Optimization: If you were going to move a disk to the right past its target position, instead, don't shift the disk on the right to the right in the previous step, but simply put this disk on that disk. How to do this at the right time efficiently may be a bit complex. It may also be helpful to not perform certain moves to increase efficiency.
Example:
52413
// put smallest disk (1) on disk to the right
1
524_3
// shift disks to the left 1 position right (3 moves - moved 4, then 2, then 5)
1
_5243
// move 1 all the way left (4 moves)
15243
// same as above for 2
2
15_43
2
1_543
12543
When the smallest disk is on the right-most position (as is now the case with 3), this is a bit of a problem. 2 ways of resolving it:
Swap 1 and 2 and put 1 on 2 (1 2 positions right, 2 left, 1 2 positions left). Then you'd have an open spot onto which to move 3. Not an option if there's less than 2 smaller elements. These elements shouldn't be fixed until we've sorted a few more elements, in case we run into the same situation.
If we had 12453, we could simply put 4 on 5 to open a slot for 3 (which sort of delays the problem). If the first non-sorted disk (5 in this case) is bigger than the second one (4) we could use some strategy like I described for my previous solution above to move elements to satisfy this condition.
Related
I'm working on a problem where I'm trying to get from the top left corner, i.e. (0,0), to the bottom right, or (m - 1, n - 1), of an input m x n 2D array. Additionally, each element of the array represents what kind of jumps can be made from that square.
For example, a table that looks like:
1 2 1
1 1 1
1 1 1
Would have a minimum path of 3, since you can go from (0,0), jump 1 square right to (0,1), jump 2 squares down to (2, 1), then jump 1 square right to the destination of (2, 2).
My current implementation uses BFS, where I push each unvisited connected square into a queue, going through until I reach the corner or am unable to proceed; along the way, I update a seperate 2D array that contains the number of moves it takes to reach that particular coordinate on the actual board from the starting square.
My code works for many of the tests I throw at it, but for a few seemingly random test cases, it returns the wrong number of moves (higher than the actual number by quite a bit). I have no idea why this might be the case! Any suggestions on where I might have gone wrong would be really appreciated.
I think the problem is that you are updating the distanceArray without setting that square as visited (which normally would prevent overwriting that square in distanceArray), and only mark it as visited once that square reaches the top of the queue. This means that it's possible for another path ahead in the queue to overwrite that distance before it gets marked as visited.
Here's an example of this problem
Board:
1 1 1 1
1 2 1 1
1 1 1 1
1 2 1 1
Queue: 0,0 1,0 0,1 2,0 1,1 1,1 0,2 3,0 2,1 *3,1* 1,3 1,2 0,3 *3,1*
Distance: 0 1 1 2 2 2 2 3 3 *3* 3 3 3 *4*
As you can see visiting 1,1 enqueues 3,1 with distance 3, but then visiting 3,0 also enqueues 3,1 and overwrites its distance to 4, because 3,1 hasn't reached the top of the queue and isn't considered visited yet.
There are multiple ways of fixing this. The simplest is probably to just set it as visited as you enqueue it. However this isn't quite viable in your exact situation since you use the board to mark visited. So instead you'll probably want to store the visited information elsewhere. You could change the board squares from ints to an object that also holds their visited information as well as their step value (and while you're at it add their shortest path distance).
Alternatively if you don't want to rewrite a lot of your previous code you could just make another 2D array to store visited information, similar to your distanceArray.
You are also adding east to the queue twice. This shouldn't cause any problems but is worth addressing anyways
Blue-Walls
Green highlighted cells = open list
Red Highlighted cells = closed list
Hello, can anyone tell me how can i implement backtracking in a a star search algorithm?
I've implemented the a star search according to wiki, but it does not backtrack, what i mean by backtrack is that the open list(green cells) contains 2,0 and 3,3 as shown in the picture, upon reaching 2,0 the current node would "jump" to 3,3 since the cost is now more than 3,3 and continue the search from there, how can it be done so that it would backtrack from 2,0->2,1->2,2... all the way back to 3,3 and start the search from there?
your image is like 2d grid map
But your text suggest graph approach which is a bit confusing.
For 2D grid map the costs must be different between cells on path
You got too much of cost=100 in there and therefore you can not backtrack the path. You have to increase or decrease cost on each step and fill only cells that are near last filled cells. That can be done by recursion on big maps or by scanning whole map or bounding box for last filled number on small maps.
Look here for mine C++ A* implementation
The backtracking
Can be done by scanning neighbors of start/end cells after A* filling moving always to the smallest/biggest cost
In this example start filling from (2,0) until (3,3) is hit and then backtrack from (3,2) cost=8 to the smallest cost (always cost-1 for incremental filling). If you need the path in reverse order then start filling from (3,3) instead ...
speedup
Sometimes double filling speed up the process so: Start filling from both ends and stop when they join. To recognize which cell is filled from which point you can use positive and negative values, or some big enough ranges for costs.
You can follow backpointers from the two nodes until you reach the common ancestor (0,2), then print the nodes you visited when following from (2,0), followed by the the nodes you visited when following from (3,3), printed in reverse.
To find the common ancestor of two nodes in an A* search tree, just maintain the two "current nodes", and follow the backpointer of whichever has the higher g-cost, until the two current nodes are in the same place.
It bears mentioning that this is a weird thing to do, though. A* is not a stack-based traversal, so it doesn't backtrack.
A 2D array of size m X n. Imagine a cat in first slot (0,0). The elements of the the array indicate the longest possible jump from that slot. For Example: the current slot contains 3, the cat can jump to the 3rd slot/2nd slot/1st slot, horizontally or vertically. The cat cannot jump diagonally. The cat cannot land on the slot containing 0. From a '0 slot' the cat cannot move anywhere. I must write a java program to find the minimum possible jumps from (0,0) to (m-1,n-1).
What data structure should I use ?
I guess a data structure which can store multiple paths with nodes between starting & ending nodes, like graph.
What algorithm should I follow ?
I guess shortest path algorithm like dijkstra's shouls be modified according to this problem.
From what I got from your question, you can only move horizontally or vertically.
"the current slot contains 3, the cat can jump to the 3rd slot, horizontally or vertically.
Since it can not move diagonally, the shortest path is the either path. One way or another, from (1,3), to get to (2,5) you still end up going down one and over 2, the order doesn't matter.
If you CAN move diagonally, have you tried using the Pythagorean Theorem? a^2 + b^2 = c^2.
//A = amount of vertical jumps, B = amount of horizonal jumps, C = the distance in-between.
//Prior to this, you'd have to know the point you are going to.
From there, take the square root of c^2 and remove the decimal part.
i.e. Math.sqrt(2) = 1.414 //just keep the 1
To keep the 1, you could set it to round down if there is a decimal, this will ensure that you always get the correct number of diagonal jumps.
That will take you as far diagonally as you can go, then just complete the jump with whatever you can do (i.e. horizontal or vertical).
I am dealing with what amounts to squares on a grid. The grid if of a more or less infinite size. Grid squares can have one of two states, either claimed or unclaimed. The coordinates of the squares are stored as squares in an R tree for fast access. Before a square is unclaimed however, I want to iterate through the nearby claimed squares to ensure that by unclaiming this square, I am not splitting the claimed squares into 2 distinct regions. It's important to note, that squares are already currently claimable only if they are touching an already claimed square.
So if I have something like
+++++++++
And if a player wants to remove the square to create
++++ ++++
Then I want to be able to detect and reject this action. Of course this needs to be able to handle the full 2 dimensional space as well ( I tried, but found it difficult to get this across in ascii art via the formatting available to me here). This must also be fairly efficient. Any pointers as to the name of an algorithm to look up or a description on how to do this would be wonderful <3
Do breadth-first searches on the neighbors of the removed grid point and see that the searches all meet each other.
Search on the components without the removed grid point until either you exhaust it (the original claimed territory) or meet the other breadth first searches in another location.
For example, if you have the region on the left, and removal results on the right:
+++ + +
+ + + +
+ + -> + +
+++ +++
(the middle of the top is removed)
now do two breadth first parallel searches: (numbers or letters show number of squares traveled from removed piece)
1 a
2 b
3 c
4xd
The connection at x is going to be reached in the 5th step of both breadth first searches, indicating removing the top middle grid does not create two separate regions.
I think that what you want is Connected Component Labeling (the Wikipedia page has pseudocode of algorithms). Count the regions before and after removing the square: if the number changes you know that the move is not allowed.
I am trying to code a Gomoku (five in a row) game in Java as an individual project. For the AI, I understand that the use of a Minimax function with Alpha-beta Pruning is a good way to approach this. However, I'm having a little trouble envisioning how this would work.
My question is this: what is a good representation for a node in a minimax tree?
I'm thinking my evaluation function will "weight" all the empty spaces on the board. It will then take the best value from that board as the node of the minmax decision tree. Am I on the right direction?
And any other tips are also welcome!
Thanks in advance!
The state space search is through the different states of the board. There are a lot of moves, since you can place a stone anywhere unoccupied. Each state can be represented as a e.g. 9x9 matrix, with 3 values -- white, black, or unoccupied. With a 9x9 board, there are therefore 3 ^ 81 possible board states.
From any board state, the number of moves is the number of unoccupied vertices. You can place a stone on any of these vertices. You can only play your own color. So, at most there are 81 possible moves .. 81 for the first move, 80 for the second, and so on. So you can search to depth 5 reasonably, and possibly more .. not too bad.
The proper representation is, as mentioned, a 2D matrix -- this can just be a 2D array of ints, with values e.g. 0 for unoccupied, 1 for white, 2 for black. ... int[9,9].
Your evaluation function doesn't sound very good. Instead, I would give points for the following:
-- get 5 in a row -- basically give it the max score for this one, since it's a win
-- 4 in a row with 2 open ends -- also max score, since opponent can't block you from getting 5.
-- 4 in a row with 1 open end -- still a very threatenning position, since opponent has to play
in one spot to block.
-- 3 in a row with 2 open ends -- very high score again
--- 4, 3, 2, 1 with both closed ends -- 0, since can't ever make 5 in a row.
and so on.
Then, you just apply the standard minimax algorithm -- i.e. alpha beta pruning -- it would be exactly the same as chess, but you have a different state space generator and evaluation function.
I'd consider an evaluation function of the following form: consider each set of, say, 6 positions in a line. (On a 19x19 board there are 14 along each line and varying numbers from 0 to 14 along each diagonal; I think that comes to 742 of these on the whole board. My arithmetic may be wrong.) For each set there are 729 possible arrangements of black, white and empty spaces. Or, er, 378 if you take end-to-end symmetry into account. Or, er, um, fewer than that but I can't be bothered to work out how many fewer if you take black/white symmetry into account too.
So now your evaluation function will consist of a table-lookup for each block of 6 stones, in a 378-or-however-many-element table (or perhaps two of them, one for horizontal and vertical lines, one for diagonal ones). Add up the results and that's your evaluation of the position.
It may turn out that actually a larger table (derived from a longer row of positions) works better.
But what goes in the table? Let your program work that out. Start with arbitrary values in the table (you might, e.g., take eval(line) = #black(line)-#white(line) or something). Let your program play itself, using alpha-beta search. Now update the table entries according to what happens. There are many different ways of doing this; here are a (sketchily-described) few.
During each game, keep track of how many times each pattern occurred in each player's positions. When the game's over, adjust each pattern's score so that patterns seen more often by the winning player look better.
Each time you do a search, adjust the scores for the patterns in the current position to bring the current static score nearer to the score obtained by search.
Each time a move is made, adjust the scores for each pattern in the "before" position to make the "before" score match the "after" score better.
Have lots of different tables (hence lots of different variants of the evaluation function). Let them play against one another. Apply some sort of evolution (e.g., play all against all, then throw out the worst performers and replace them with mutants derived from the better performers).
For a more sophisticated version of these ideas (applied to chess, but the same ideas would work fine for gomoku), take a look at http://cs.anu.edu.au/~Lex.Weaver/pub_sem/publications/knightcap.pdf .