Does 8 puzzle solvability rules work for any goal state? - algorithm

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.

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>

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.

Related

Loop over part of Matrix

I have a Matrix A. I want to iterate over the inner part of the matrix (B), while also working with the rows and columns that are not part of B.
A = [1 4 5 6 7 1; B = [2 2 2 2;
8 2 2 2 2 1; 2 3 3 2;
9 2 3 3 2 1; 2 8 2 2];
0 2 8 2 2 1;
1 1 1 1 1 1];
I know it is possible to select the part of A like this:
[rows,columns] = size(A);
B = A([2:1:rows-1],[2:1:columns-1]);
for i = 1:(rows*columns)
%do loop stuff
endfor
This however wont work because I also need the outer rows and columns for my calculations. How can I achieve a loop without altering A?
So, why do not use two indexes for the inner matrix?
%....
for i=2:rows-1
for j=2:cols-1
% here, A(i,j) are the B elements, but you
% can still access to A(i-1, j+1) if you want.
end
end
%....

Efficiently construct a square matrix with unique numbers in each row

A matrix of size nxn needs to be constructed with the desired properties.
n is even. (given as input to the algorithm)
Matrix should contain integers from 0 to n-1
Main diagonal should contain only zeroes and matrix should be symmetric.
All numbers in each row should be different.
For various n , any one of the possible output is required.
input
2
output
0 1
1 0
input
4
output
0 1 3 2
1 0 2 3
3 2 0 1
2 3 1 0
Now the only idea that comes to my mind is to brute-force build combinations recursively and prune.
How can this be done in a iterative way perhaps efficiently?
IMO, You can handle your answer by an algorithm to handle this:
If 8x8 result is:
0 1 2 3 4 5 6 7
1 0 3 2 5 4 7 6
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
4 5 6 7 0 1 2 3
5 4 7 6 1 0 3 2
6 7 4 5 2 3 0 1
7 6 5 4 3 2 1 0
You have actually a matrix of two 4x4 matrices in below pattern:
m0 => 0 1 2 3 m1 => 4 5 6 7 pattern => m0 m1
1 0 3 2 5 4 7 6 m1 m0
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
And also each 4x4 is a matrix of two 2x2 matrices with a relation to a power of 2:
m0 => 0 1 m1 => 2 3 pattern => m0 m1
1 0 3 2 m1 m0
In other explanation I should say you have a 2x2 matrix of 0 and 1 then you expand it to a 4x4 matrix by replacing each cell with a new 2x2 matrix:
0 => 0+2*0 1+2*0 1=> 0+2*1 1+2*1
1+2*0 0+2*0 1+2*1 0+2*1
result => 0 1 2 3
1 0 3 2
2 3 0 1
3 2 1 0
Now expand it again:
0,1=> as above 2=> 0+2*2 1+2*2 3=> 0+2*3 1+2*3
1+2*2 0+2*2 1+2*3 0+2*3
I can calculate value of each cell by this C# sample code:
// i: row, j: column, n: matrix dimension
var v = 0;
var m = 2;
do
{
var p = m/2;
v = v*2 + (i%(n/p) < n/m == j%(n/p) < n/m ? 0 : 1);
m *= 2;
} while (m <= n);
We know each row must contain each number. Likewise, each row contains each number.
Let us take CS convention of indices starting from 0.
First, consider how to place the 1's in the matrix. Choose a random number k0, from 1 to n-1. Place the 1 in row 0 at position (0,k0). In row 1, if k0 = 1 in which case there is already a one placed. Otherwise, there are n-2 free positions and place the 1 at position (1,k1). Continue in this way until all the 1 are placed. In the final row there is exactly one free position.
Next, repeat with the 2 which have to fit in the remaining places.
Now the problem is that we might not be able to actually complete the square. We may find there are some constraints which make it impossible to fill in the last digits. The problem is that checking a partially filled latin square is NP-complete.(wikipedia) This basically means pretty compute intensive and there no know short-cut algorithm. So I think the best you can do is generate squares and test if they work or not.
If you only want one particular square for each n then there might be simpler ways of generating them.
The link Ted Hopp gave in his comment Latin Squares. Simple Construction does provide a method for generating a square starting with the addition of integers mod n.
I might be wrong, but if you just look for printing a symmetric table - a special case of latin squares isomorphic to the symmetric difference operation table over a powerset({0,1,..,n}) mapped to a ring {0,1,2,..,2^n-1}.
One can also produce such a table, using XOR(i,j) where i and j are n*n table indexes.
For example:
def latin_powerset(n):
for i in range(n):
for j in range(n):
yield (i, j, i^j)
Printing tuples coming from previously defined special-case generator of symmetric latin squares declared above:
def print_latin_square(sq, n=None):
cells = [c for c in sq]
if n is None:
# find the length of the square side
n = 1; n2 = len(cells)
while n2 != n*n:
n += 1
rows = list()
for i in range(n):
rows.append(" ".join("{0}".format(cells[i*n + j][2]) for j in range(n)))
print("\n".join(rows))
square = latin_powerset(8)
print(print_latin_square(square))
outputs:
0 1 2 3 4 5 6 7
1 0 3 2 5 4 7 6
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
4 5 6 7 0 1 2 3
5 4 7 6 1 0 3 2
6 7 4 5 2 3 0 1
7 6 5 4 3 2 1 0
See also
This covers more generic cases of latin squares, rather than that super symmetrical case with the trivial code above:
https://www.cut-the-knot.org/arithmetic/latin2.shtml (also pointed in the comments above for symmetric latin square construction)
https://doc.sagemath.org/html/en/reference/combinat/sage/combinat/matrices/latin.html

I know how Merge Sort works, but How Merge Sort Code Works?

You can read this on Wikipedia:
function merge_sort(list m)
// Base case. A list of zero or one elements is sorted, by definition.
if length(m) <= 1
return m
// Recursive case. First, *divide* the list into equal-sized sublists.
var list left, right
var integer middle = length(m) / 2
for each x in m before middle
add x to left
for each x in m after or equal middle
add x to right
// Recursively sort both sublists
left = merge_sort(left)
right = merge_sort(right)
// Then merge the now-sorted sublists.
return merge(left, right)
On line 1 there's a list of numbers, let's say 9 6 3 7 5 1 8 2
They say that merge_sort divides the list on 2 and 2 again and again until each list has only 1 integer left, like this one:
9 6 3 7 5 1 8 2 -->
9 6 3 7 - 5 1 8 2 -->
9 6 - 3 7 - 5 1 - 8 2 -->
9 - 6 - 3 - 7 - 5 - 1 - 8 - 2
And then the numbers are put together like this:
6 9 - 3 7 - 1 5 - 2 8 -->
3 6 7 9 - 1 2 5 8 -->
1 2 3 5 6 7 8 9 -->
But I don't see where in the code the list of integers are divided on 2 again and again until each has only 1 integer left?
var list left, right
var integer middle = length(m) / 2
for each x in m before middle
add x to left
for each x in m after or equal middle
add x to right
As I understand, on the code above, the list of numbers is divided to two different lists:
9 6 3 7 and 5 1 8 2
What then happens on the code below?
left = merge_sort(left)
right = merge_sort(right)
Can someone explain me how the merge_sort code above exactly works step by step?
But I don't see where in the code the list of integers are divided on 2 again and again until each has only 1 integer left?
var list left, right
var integer middle = length(m) / 2 --------statement-1
for each x in m before middle --------statement-2
add x to left
for each x in m after or equal middle --------statement-3
add x to right
At the statement-1 you divide the array into two parts and add them to the left and right sub-array. In the statement-2, you are adding all the element before middle, which is your middle element of the array. Similarly statement-3, you are adding rest of the element in right sub-array. So essentially, you keep on dividing the array in two parts until their size is 1 or 0.
if length(m) <= 1
return m
In the start you have above conditional check, which return the method call if the size of the array is less then or equal to one.
What then happens on the code below?
left = merge_sort(left)
right = merge_sort(right)
This is a recursive call to sort (divide the array until size is one) the each sub array. Which is created in the above pseudo-code. You sort left and right sub-array separately and then join them into a single array.
return merge(left, right)
Here both left and right sub-array are passed to a merge function. These both array are sorted array. The task of the merge function is merge these sub-array into a single sorted array.
The pseudo code is missing some details. There was debate on the talk page about removing it or fixing it. Note it's supposed to be working with a list, not an array, which is why elements can only be appended one at a time. The list is not really split into 2 parts; instead two new initially empty lists left and right are created, then (middle = length/2) elements are moved from list to left, then (length - middle) elements are moved from list to right. This cleaned up example with C++ comments may make more sense, but it's still an inefficient way to sort a list. A bottom up merge sort using an array of pointers is much more efficient. I can add example code here if anyone is interested.
var list left, right
var integer middle = length(m) / 2
var integer count
for (count = 0; count < middle; count += 1)
get x from front of list // x = *list.front()
remove first element from list // list.pop_front()
add x to left // left.push_back(x)
for (count = middle; count < length; count += 1)
get x from front of list // x = *list.front()
remove first element from list // list.pop_front()
add x to right // right.push_back(x)
In that same wiki article, there are two C / C++ like code examples, which should be easier to understand. The examples are simplified and copy data back to the original array after each merge step, which could be avoided with more optimized code.
http://en.wikipedia.org/wiki/Merge_sort#Top-down_implementation
http://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation
The sequence is different for top down merge sort, it's depth first, left first:
9 6 3 7 5 1 8 2
9 6 3 7|5 1 8 2
9 6|3 7
9|6
6 9
3|7
3 7
3 6 7 9
5 1|8 2
5|1
1 5
8|2
2 8
1 2 5 8
1 2 3 5 6 7 8 9
Bottom up merge sort skips the recursion and just starts off assuming a run size of 1, and merges width first, left to right:
9 6 3 7 5 1 8 2
9|6|3|7|5|1|8|2 run size = 1
6 9|3 7|1 5|2 8 run size = 2
3 6 7 9|1 2 5 8 run size = 4
1 2 3 5 6 7 8 9 done
Another example of bottom up merge sort algorithm:
http://www.mathcs.emory.edu/~cheung/Courses/171/Syllabus/7-Sort/merge-sort5.html

Matlab: sorting a matrix in a unique way

I have a problem with sorting some finance data based on firmnumbers. So given is a matrix that looks like:
[1 3 4 7;
1 2 7 8;
2 3 7 8;]
On Matlab i would like the matrix to be sorted as follows:
[1 0 3 4 7 0;
1 2 0 0 7 8;
0 2 3 0 7 8;]
So basically every column needs to consist of 1 type of number.
I have tried many things but i cant get the matrix sorted properly.
A = [1 3 4 7;
1 2 7 8;
2 3 7 8;]
%// Get a unique list of numbers in the order that you want them to appear as the new columns
U = unique(A(:))'
%'//For each column (of your output, same as columns of U), find which rows have that number. Do this by making A 3D so that bsxfun compares each element with each element
temp1 = bsxfun(#eq,permute(A,[1,3,2]),U)
%// Consolidate this into a boolean matrix with the right dimensions and 1 where you'll have a number in your final answer
temp2 = any(temp1,3)
%// Finally multiply each line with U
bsxfun(#times, temp2, U)
So you can do that all in one line but I broke it up to make it easier to understand. I suggest you run each line and look at the output to see how it works. It might seem complicated but it's worthwhile getting to understand bsxfun as it's a really useful function. The first use which also uses permute is a bit more tricky so I suggest you first make sure you understand that last line and then work backwards.
What you are asking can also be seen as an histogram
A = [1 3 4 7;
1 2 7 8;
2 3 7 8;]
uniquevalues = unique(A(:))
N = histc(A,uniquevalues' ,2) %//'
B = bsxfun(#times,N,uniquevalues') %//'
%// bsxfun can replace the following instructions:
%//(the instructions are equivalent only when each value appears only once per row )
%// B = repmat(uniquevalues', size(A,1),1)
%// B(N==0) = 0
Answer without assumptions - Simplified
I did not feel comfortable with my old answer that makes the assumption of everything being an integer and removed the possibility of duplicates, so I came up with a different solution based on #lib's suggestion of using a histogram and counting method.
The only case I can see this not working for is if a 0 is entered. you will end up with a column of all zeros, which one might interpret as all rows initially containing a zero, but that would be incorrect. you could uses nan instead of zeros in that case, but not sure what this data is being put into, and if it that processing would freak out.
EDITED
Includes sorting of secondary matrix, B, along with A.
A = [-1 3 4 7 9; 0 2 2 7 8.2; 2 3 5 9 8];
B = [5 4 3 2 1; 1 2 3 4 5; 10 9 8 7 6];
keys = unique(A);
[counts,bin] = histc(A,transpose(unique(A)),2);
A_sorted = cell(size(A,1),1);
for ii = 1:size(A,1)
for jj = 1:numel(keys)
temp = zeros(1,max(counts(:,jj)));
temp(1:counts(ii,jj)) = keys(jj);
A_sorted{ii} = [A_sorted{ii},temp];
end
end
A_sorted = cell2mat(A_sorted);
B_sorted = nan(size(A_sorted));
for ii = 1:size(bin,1)
for jj = 1:size(bin,2)
idx = bin(ii,jj);
while ~isnan(B_sorted(ii,idx))
idx = idx+1;
end
B_sorted(ii,idx) = B(ii,jj);
end
end
B_sorted(isnan(B_sorted)) = 0
You can create at the beginning a matrix with 9 columns , and treat the values in your original matrix as column indexes.
A = [1 3 4 7;
1 2 7 8;
2 3 7 8;]
B = zeros(3,max(A(:)))
for i = 1:size(A,1)
B(i,A(i,:)) = A(i,:)
end
B(:,~any(B,1)) = []

Find row and column number of eight neighbors conditionally in Matlab

I have a 6 * 6 matrix
A=
3 8 8 8 8 8
4 6 1 0 7 -1
9 7 0 2 6 -1
7 0 0 5 4 4
4 -1 0 2 8 1
1 -1 0 8 3 9
I am interested in finding row and column number of neighbors starting from A(4,4)=5. But They will be linked to A(4,4) as neighbor only if A(4,4) has element 4 on right, 6 on left, 2 on top, 8 on bottom 1 on top left diagonally, 3 on top right diagonally, 7 on bottom left diagonally and 9 on bottom right diagonally. TO be more clear A(4,4) will have neighbors if the neighbors are surrounding A(4,4) as follows:
1 2 3;
6 5 4;
7 8 9;
And this will continue as each neighbor is found.
Also 0 and -1 will be ignored. In the end I want to have these cells' row and column number as shown in figure below. Is there any way to visualize this network as well. This is sample only. I really have a huge matrix.
A = [3 8 8 8 8 8;
4 6 1 0 7 -1;
9 7 0 2 6 -1;
7 0 0 5 4 4;
4 -1 0 2 8 1;
1 -1 0 8 3 9];
test = [1 2 3;
6 5 4;
7 8 9];
%//Pad A with zeros on each side so that comparing with test never overruns the boundries
%//BTW if you have the image processing toolbox you can use the padarray() function to handle this
P = zeros(size(A) + 2);
P(2:end-1, 2:end-1) = A;
current = zeros(size(A) + 2);
past = zeros(size(A) + 2);
%//Initial state (starting point)
current(5,5) = 1; %//This is A(4,4) but shifted up 1 because of the padding
condition = 1;
while sum(condition(:)) > 0;
%//get the coordinates of any new values added to current
[x, y] = find(current - past);
%//update past to last iterations current
past = current;
%//loop through all the coordinates returned by find above
for ii=1:size(x);
%//Make coord vectors that represent the current coordinate plus it 8 immediate neighbours.
%//Note that this is why we padded the side in the beginning, so if we hit a coordinate on an edge, we can still get 8 neighbours for it!
xcoords = x(ii)-1:x(ii)+1;
ycoords = y(ii)-1:y(ii)+1;
%//Update current based on comparing the coord and its neighbours against the test matrix, be sure to keep the past found points hence the OR
current(xcoords, ycoords) = (P(xcoords, ycoords) == test) | current(xcoords, ycoords);
end
%//The stopping condition is when current == past
condition = current - past;
end
%//Strip off the padded sides
FinalAnswer = current(2:end-1, 2:end-1)
[R, C] = find(FinalAnswer);
coords = [R C] %//This line is unnecessary, it just prints out the results at the end for you.
OK cool you got very close, so here is the final solution with the loops. It runs in about 0.002 seconds so it's pretty quick I think. The output is
FinalAnswer =
0 0 0 0 0 0
0 1 1 0 0 0
0 1 0 1 0 0
1 0 0 1 1 1
0 0 0 0 1 0
0 0 0 0 0 1
coords =
4 1
2 2
3 2
2 3
3 4
4 4
4 5
5 5
4 6
6 6

Resources