Reputation: 59
Ive learned that the solvability of a 8 puzzle can be checked via following certain rules. https://www.cs.bham.ac.uk/~mdr/teaching/modules04/java2/TilesSolvability.html
http://ldc.usb.ve/~gpalma/ci2693sd08/puzzleFactible.txt.
My question is whether this solvability check applies only when the goal state (solution) is in correct ascending order? Example:
Start state
3 1 5
6 0 4
2 7 8
Goal state1 Goal State2
3 1 5 1 2 3
6 4 8 4 5 6
2 0 7 7 8 0
Now my obeservation is that, the solvability check would work if the goal state is Goal State2 in the example. But it would not work if the goal state is Goal state1.
Upvotes: 1
Views: 2655
Reputation:
Yes, it does work. There's a pretty trivial way of showing this. Just map the values in the solution to the values of let's say your GoalState2, for which the check works:
state we want to reach Goal State2
3 1 5 1 2 3
6 4 8 4 5 6
2 0 7 7 8 0
map:
3 -> 1
1 -> 2
3 -> 5
...
Now apply this table to your start-state, by replacing each value with the one it's mapped to, solve the entire problem in the way you used to for GoalState2, and reverse the mapping for the final-state. And there you are with your desired result, if it exists. And the solvability-rule can be reused without changing a bit of it, just by using that simple remapping.
An illustration of how this works:
state we want to reach Goal State2
3 1 5 1 2 3
6 4 8 4 5 6
2 0 7 7 8 0
build map
map:
3 -> 1
1 -> 2
3 -> 5
...
Start state
3 1 5 apply map 1 2 3 solve for 1 2 3 apply 3 1 5
6 0 4 --------> 4 8 5 --------> 4 5 6 ---------> 6 4 8
2 7 8 7 0 6 GoalS2 7 8 0 reverse map 2 0 7
That's the most trivial way of solving it. Just consider the numbers as labels without any meaning and you're already halve way done.
For a more complex answer that gives you a better understanding of the rule itself, take a look at @trincots answer.
Upvotes: 1
Reputation: 350232
The inversion count can be odd or even, and in short we can call a state even or odd. This is called a state's parity. If the start state is even, then it is solvable. In the referenced articles this does indeed mean that the target must be the one with the incremental order.
But since there are in fact two classes of states (based on parity) and you can only stay within one of those two classes by making legal moves -- i.e. the parity is invariable when you make legal moves -- this principle can be extended to any target state:
If the parity of the starting state is the same as the parity of the target state, then it is reachable (solvable).
In the example states you give, the starting state is odd, and also the first target state is odd. So they belong to the same class, and the one can be reached from the other.
Here is a simple implementation of the parity check in JavaScript. It works for even sized grids as well:
function parity(grid) {
var inversions = 0;
// take copy and remove blank (0) from it.
var arr = grid.slice(0);
arr.splice(arr.indexOf(0), 1);
// perform sort and count swaps
for (var i = 1; i < arr.length; i++) {
for (var j = i - 1; j >= 0; j--) {
if (arr[j] <= arr[j+1]) break;
[arr[j+1], arr[j]] = [arr[j], arr[j+1]];
inversions++;
};
}
if (grid.length % 2 == 0) { // even grid width
var size = Math.round(Math.sqrt(grid.length));
var blankRow = Math.floor((grid.length - 1 - grid.indexOf(0)) / size);
inversions += blankRow;
}
return inversions & 1; // only odd/even is needed as info
}
document.querySelector('button').onclick = function() {
var res = '';
var txt = document.querySelector('textarea');
var grid = txt.value.trim().split(/[,\s]+/g).map(Number);
var size = Math.round(Math.sqrt(grid.length));
var res = size*size !== grid.length
? 'input is not a complete square matrix of data'
: 'parity = ' + parity(grid);
document.querySelector('pre').textContent = res;
}
Enter grid. 0 represents empty slot.<br>
<textarea rows=4>3 1 5
6 0 4
2 7 8
</textarea><button>Verify</button><br>
<pre></pre>
Upvotes: 2