Mathematica help ~ Randomly change elements in a matrix - matrix

I have a 10X10 matrix with elements that have the values -1 or 1. Given a percentage, I want to randomly change that percentage of elements to its opposite value. For example, if I input 20% i want to randomly change 20 elements; if the value is -1 I want it to change to 1, and if the value is 1 I want it to flip to -1. I hope that makes sense. Thanks

(example = Table[1, {10}, {10}] ) // MatrixForm
example RandomChoice[{80, 20} -> {1, -1} , {10, 10}] // MatrixForm
In case you want exactly 20 flipped you can get that like this:
example Partition[RandomSample[Table[-1, {20}]~Join~Table[1, {80}], 100], 10]

In[1]:= m = 2*RandomInteger[{0, 1}, {10, 10}] - 1
Out[1]= {{1, 1, -1, -1, -1, -1, 1, -1, 1, 1},
{-1, -1, 1, -1, -1, -1, -1, 1, 1, -1},
{-1, -1, 1, -1, 1, 1, 1, 1, -1, 1},
{1, 1, -1, 1, -1, -1, -1, 1, -1, -1},
{1, -1, 1, 1, 1, -1, 1, -1, 1, 1},
{-1, 1, 1, -1, -1, -1, -1, 1, 1, 1},
{-1, -1, 1, 1, 1, 1, -1, 1, -1, 1},
{-1, -1, -1, 1, -1, -1, -1, -1, -1, 1},
{1, -1, 1, 1, 1, 1, -1, 1, -1, 1},
{-1, -1, -1, 1, -1, 1, 1, -1, -1, 1}}
In[2]:= flip[m_, p_] := Module[{vm = m, v},
v = RandomChoice[Range[100] - 1, p];
For[i = 1, i <= p, i++,
vm[[Quotient[v[[i]], 10] + 1, Mod[v[[i]], 10] + 1]] *= -1
];
vm
];
fm = flip[m, 3] (* flip 3% *)
Out[3]= {{1, 1, -1, -1, -1, -1, 1, -1, 1, 1},
{-1, -1, 1, -1, -1, -1, -1, 1, 1, -1},
{-1, -1, 1, -1, 1, 1, 1, 1, -1, 1},
{1, 1, -1, 1, -1, -1, -1, 1, -1, -1},
{1, -1, 1, 1, 1, -1, 1, -1, 1, 1},
{-1, 1, 1, -1, -1, -1, -1, 1, 1, 1},
{-1, -1, 1, 1, -1, 1, -1, 1, -1, 1},
{-1, -1, -1, 1, -1, 1, -1, -1, -1, 1},
{1, -1, 1, 1, 1, 1, -1, 1, -1, 1},
{-1, 1, -1, 1, -1, 1, 1, -1, -1, 1}}
In[4]:= MapThread[#1-#2&, {m, fm}] (*subtract matricies to hilight changes*)
Out[4]= {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, -2, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, -2, 0, 0, 0, 0, 0, 0, 0, 0}}
Alternate method using * for pairwise element multiply, not vector dot product
flip[m_, p_] := Partition[
Flatten[m]*RandomSample[Join[Table[-1, {p}], Table[1, {100-p}]]], 10];

Related

Iterating over integer arrays with fixed sum in Julia

I am looking for an algorithm to iterate over all arrays of length n whose entries are integers between 0 and d and whose sum is k*d. It would be even better if there is a way to do this with built-in Julia functions and iterators. The algorithm should be non-recursive and memory efficient as I am hoping to use this for reasonable values of n.
For small values of n, d, and k, I've written down all such arrays in lexicographical ordering, but I haven't been able to come up with code for iterating through all such arrays.
I think this should work but it requires Combinatorics.jl and ResumableFunctions.jl
using Combinatorics, ResumableFunctions
#resumable function gen_all(n, k, d)
for x in partitions(k*d + n, n)
x = x .- 1
if all(x .<= d)
ys = Set(permutations(x))
for y in ys
#yield y
end
end
end
end
for ga in gen_all(5, 2, 2)
println(ga)
end
gives
[2, 0, 0, 2, 0]
[2, 0, 0, 0, 2]
[0, 0, 2, 2, 0]
[0, 2, 2, 0, 0]
[2, 0, 2, 0, 0]
[0, 2, 0, 2, 0]
[2, 2, 0, 0, 0]
[0, 0, 0, 2, 2]
[0, 0, 2, 0, 2]
[0, 2, 0, 0, 2]
[0, 2, 0, 1, 1]
[0, 1, 1, 0, 2]
[0, 1, 2, 0, 1]
[0, 1, 1, 2, 0]
[2, 1, 1, 0, 0]
[2, 1, 0, 0, 1]
[0, 0, 1, 1, 2]
[1, 2, 1, 0, 0]
[1, 2, 0, 0, 1]
[0, 1, 2, 1, 0]
[0, 1, 0, 1, 2]
[1, 0, 0, 1, 2]
[0, 2, 1, 1, 0]
[2, 0, 0, 1, 1]
[1, 0, 2, 0, 1]
[1, 2, 0, 1, 0]
[0, 1, 0, 2, 1]
[2, 0, 1, 0, 1]
[0, 2, 1, 0, 1]
[1, 0, 1, 2, 0]
[0, 0, 1, 2, 1]
[1, 0, 0, 2, 1]
[2, 1, 0, 1, 0]
[1, 1, 0, 0, 2]
[1, 0, 2, 1, 0]
[1, 0, 1, 0, 2]
[1, 1, 0, 2, 0]
[0, 0, 2, 1, 1]
[2, 0, 1, 1, 0]
[1, 1, 2, 0, 0]
[1, 1, 1, 0, 1]
[1, 1, 0, 1, 1]
[1, 0, 1, 1, 1]
[1, 1, 1, 1, 0]
[0, 1, 1, 1, 1]

Special Sorting Algorithm

I 'am developing a technique for sorting a table that contains either 0 or 1 such as:
{{1, 1, 0, 1, 1, 1, 1, 1},
{1, 1, 0, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 0, 1},
{0, 0, 0, 1, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 1, 1, 0, 0, 0}}
The objective is to count the total per column and sort the table:
I. Descending based on the total per column.
II. coverage. For instance, in the 1st row the 3rd value is 0. We'll have to find the 1st column that has 1 in the 3rd column and re-sort the columns. In other words, 1 stands for coverage and we have to make sure that we cover all within the 1st few columns.
I managed to get the total per column, as follows:
For (i=0; i<m; i++)
For (j=0; j< TS.Size(); j++)
if (tc.detected()==1)
TS_Detect[j][i]= 1
else
TS_Detect[j][i]= 0
TC_Sum=(2, TS.Size())
For (k=0; k<TS.Size(); k++)
TC_Sum(0, k)=k
For (l=0; l< m; l++)
Flag=TS_Detect[l][k]
If (flag == 1)
TC_Sum(1, k)= TC_Sum(1, k)+1
int temp
For (g=0; g<TC_Sum.length-1; g++)
For (b=1; b< TC_Sum.length-1; b++)
If (TC_Sum[b-1]< TC_Sum[b])
temp= TC_Sum[b-1]
TC_Sum[b-1]= TC_Sum[b]
TC_Sum[b]= temp
return TC_Sum
The problem now is that I couldn't sort the original array (TC_Detect) based on the column number from TC_Sum.
Consequently, I would like to re-sort the table so if a column has 0, the next one will be 1.
The expected output for the above example will look like:
{{1, 1, 0, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 0, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 1, 0, 1},
{1, 1, 1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 0},
{0, 0, 0, 1, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 1, 1, 0, 0, 0}}
Any suggestion, please.
I'm not sure what language you are using, but I think my answer is general enough.
I assume that you have a list of lists, let's call it A.
A = [ [0,1,0,0] , [1,0,1,1] , [0,0,0,0] ]
You've used your counting algorithm above to make another list, call it S for sum.
S = [ 3 , 1 , 0 ]
You now want to sort A based on the values of S.
To make things easy, let's define a third list that we'll call I for index.
I = [ 0 , 1 , 2 ]
I would continue up to 3,4,5,6,... depending on the number of elements in your list
What you need now is a sort function that allows you to sort based on a key. Such a sort function usually takes the thing you want to sort along with a function for comparing two items.
In this case, sort I. The sort function is then passed indices. Compare these indices based on the values in S. The result is a list I* containing indices sorted according to S. You can now reorder A based on I*.
I am not sure what language you are using, but the following Python code accomplishes this:
def MyComparison(i,j):
return S[j]-S[i]
A = [ [0,1,0,0] , [1,0,1,1], [0,0,0,0] ]
S = [ 1 , 3 , 0 ]
I = [ 0 , 1 , 2 ]
Istar = sorted(I, cmp=MyComparison)
#The above returns: [2, 0, 1]. If this is the wrong order, reverse the result.
[A[x] for x in Istar]
#The above returns: [[1, 0, 1, 1], [0, 1, 0, 0], [0, 0, 0, 0]]
Note that the comparison function returns -1, 0, or 1 depending on the relative ranking of the items compared.

Graph algorithm involving chess: possible paths in k moves

I'm trying to solve an algorithm problem involving chess.
Suppose I have a king in A8 and want to move it to H1 (only with allowed moves).
How could I find out how many possibilities (paths) there is making exactly any given k moves?
(e.g. How many paths/possibilities there is if I want to move the king from A8 to H1 with 15 moves?)
One trivial solution is to see it as a graph problem and use any standard
path finding algorithm counting each move as having cost 1. So, let's say I want to move my king from A8 to H1 in 10 moves. I would simply search all paths which sum up to 10.
My question is, if there are other more clever and efficient ways of doing this?
I was also wondering, if there could be something more "mathematical" and straightforward to find this number and not so "algorithmic" and "brute-force-like"?
This is a straight-forward O(N^3) dynamic programming problem.
Simply assign a 3D array as follows:
Let Z[x][y][k] be the number of moves of k steps to reach the destination from position (x,y) on board.
The base cases are:
foreach x in 0 to 7,
foreach y in 0 to 7,
Z[x][y][0] = 0 // forall x,y: 0 ways to reach H1 from
// anywhere else with 0 steps
Z[7][7][0] = 1 // 1 way to reach H1 from H1 with 0 steps
The recursive case is:
foreach k in 1 to K,
foreach x in 0 to 7,
foreach y in 0 to 7,
Z[x][y][k+1] = Z[x-1][y][k]
+ Z[x+1][y][k]
+ Z[x][y-1][k]
+ Z[x][y+1][k]
+ ...; // only include positions in
// the summation that are on the board
// and that a king can make
Your answer is then:
return Z[0][0][K]; // number of ways to reach H1(7,7) from A8(0,0) with K moves
(There is a faster way to do this in O(n^2) by decomposing the moves into two sets of horizontal and vertical moves and then combining these and multiplying by the number of interleavings.)
See this related question and answer: No of ways to walk M steps in a grid
You could use an adjacency matrix. If you multiply such a matrix with itself, you get the amount of paths from Point to Point. Example:
Graph: complete K3 graph : A<->B<->C<->A
Matrix:
[0 ; 1 ; 1]
[1 ; 0 ; 1]
[1 ; 1 ; 0]
Paths for length 2: M * M
[2 ; 1 ; 1]
[1 ; 2 ; 1]
[1 ; 1 ; 2]
Length 3 would then be M * M * M
[2 ; 3 ; 3]
[3 ; 2 ; 3]
[3 ; 3 ; 2]
.......E <-end
........
........
........
........
........
........
S....... <-start
Unfortunately you can't use "any standard path finding algorithm" because your paths might not be shortest-paths. You'd have to specifically use a naive search which considered all paths (depth-first or breadth-first, for example).
However, because you don't care how you got to a tile, you can use a technique called dynamic programming. For every location (i,j), the number of ways to get there in n moves (let's call it waysi,j(n)) is:
waysi,j(n) = waysi-1,j(n-1) + waysi+1,j(n-1) + waysi,j-1(n-1) + waysi,j+1(n-1) + waysi+1,j+1(n-1) + waysi-1,j+1(n-1) + waysi+1,j-1(n-1) + waysi-1,j-1(n-1)
That is, the king can move from any of the adjacent squares in 1 move:
waysi,j(n) = sumneighbors(i,j)(waysneighbor(n-1))
Thus you'd do, for example in python:
SIZE = 8
cache = {}
def ways(pos, n):
r,c = pos # row,column
if not (0<=r<SIZE and 0<=c<SIZE):
# off edge of board: no ways to get here
return 0
elif n==0:
# starting position: only one way to get here
return 1 if (r,c)==(0,0) else 0
else:
args = (pos,n)
if not args in cache:
cache[args] = ways((r-1,c), n-1) + ways((r+1,c), n-1) + ways((r,c-1), n-1) + ways((r,c+1), n-1) + ways((r-1,c-1), n-1) + ways((r+1,c-1), n-1) + ways((r+1,c-1), n-1) + ways((r+1,c+1), n-1)
return cache[args]
Demo:
>>> ways((7,7), 15)
1074445298
The above technique is called memoization, and is simpler to write than dynamic programming, because you don't need to really think about the order in which you do things. You can see the cache grow as we perform a series of larger and larger queries:
>>> cache
{}
>>> ways((1,0), 1)
1
>>> cache
{((1, 0), 1): 1}
>>> ways((1,1), 2)
2
>>> cache
{((0, 1), 1): 1, ((1, 2), 1): 0, ((1, 0), 1): 1, ((0, 0), 1): 0, ((2, 0), 1): 0, ((2, 1), 1): 0, ((1, 1), 2): 2, ((2, 2), 1): 0}
>>> ways((2,1), 3)
5
>>> cache
{((1, 2), 1): 0, ((2, 3), 1): 0, ((2, 0), 2): 1, ((1, 1), 1): 1, ((3, 1), 1): 0, ((4, 0), 1): 0, ((1, 0), 1): 1, ((3, 0), 1): 0, ((0, 0), 1): 0, ((2, 0), 1): 0, ((2, 1), 1): 0, ((4, 1), 1): 0, ((2, 2), 2): 1, ((3, 3), 1): 0, ((0, 1), 1): 1, ((3, 0), 2): 0, ((3, 2), 2): 0, ((3, 2), 1): 0, ((1, 0), 2): 1, ((4, 2), 1): 0, ((4, 3), 1): 0, ((3, 1), 2): 0, ((1, 1), 2): 2, ((2, 2), 1): 0, ((2, 1), 3): 5}
(In python, can also use a #cached or #memoized decorator to avoid having to write the entire code in the last else: block. Other languages have other ways to automatically perform memoization.)
The above was a top-down approach. It can sometimes produce very large stacks (your stack will grow with n). If you want to be super-efficient to avoid unnecessary work, you can do a bottom-up approach, where you simulate all positions the king could be, for 1 step, 2 steps, 3 steps, ...:
SIZE = 8
def ways(n):
grid = [[0 for row in range(8)] for col in range(8)]
grid[0][0] = 1
def inGrid(r,c):
return all(0<=coord<SIZE for coord in (r,c))
def adjacentSum(pos, grid):
r,c = pos
total = 0
for neighbor in [(1,0),(1,1),(0,1),(-1,1),(-1,0),(-1,-1),(0,-1),(1,-1)]:
delta_r,delta_c = neighbor
(r2,c2) = (r+delta_r,c+delta_c)
if inGrid(r2,c2):
total += grid[r2][c2]
return total
for _ in range(n):
grid = [[adjacentSum((r,c), grid) for r in range(8)] for c in range(8)]
# careful: grid must be replaced atomically, not element-by-element
from pprint import pprint
pprint(grid)
return grid
Demo:
>>> ways(0)
[[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
>>> ways(1)
[[0, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
>>> ways(2)
[[3, 2, 2, 0, 0, 0, 0, 0],
[2, 2, 2, 0, 0, 0, 0, 0],
[2, 2, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
>>> ways(3)
[[6, 11, 6, 4, 0, 0, 0, 0],
[11, 16, 9, 5, 0, 0, 0, 0],
[6, 9, 6, 3, 0, 0, 0, 0],
[4, 5, 3, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
>>> ways(4)
[[38, 48, 45, 20, 9, 0, 0, 0],
[48, 64, 60, 28, 12, 0, 0, 0],
[45, 60, 51, 24, 9, 0, 0, 0],
[20, 28, 24, 12, 4, 0, 0, 0],
[9, 12, 9, 4, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]

Sort a list of lists based on alphabetical order of inner list elements in Mahtematica

I have a list of lists with inner lists possibly of variable lengths. I need to sort the outer list based on the alphabetical order of the inner list elements. For example, given a list of
{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 10, 0}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}
I want the output after Sort to be
{{0, 0, 10, 0}, {0, 0, 7}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}}
I just do not know how to handle the variable lengths of inner lists in order to write a comparison function. Please help.
Edit
BTW, the original list is a numerical one.
Edit 2
For example, I have a list:
{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 11, 0}, {0, 0, 1, 12}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}
The output should be:
{{0, 0, 1, 12}, {0, 0, 11, 0}, {0, 0, 7}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}}
The reason is that 1 is lexically less than 11, which is less than 7.
You can set up a lexciographic comparator like this:
lexComp[_, {}] := False;
lexComp[{}, _] := True;
lexComp[{a_, as___}, {b_, bs___}] := a < b || a == b && lexComp[{as}, {bs}];
You can then sort using that to get the desired effect:
Sort[{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 10, 0}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}, lexComp]
{{0, 0, 7}, {0, 0, 10, 0}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}}
If you wish to treat the numbers as strings in your sorting, you can modify it like so:
lessAsString[a_, b_] := Order ## (ToString /# {a, b}) === 1;
olexComp[_, {}] := False;
olexComp[{}, _] := True;
olexComp[{a_, as___}, {b_, bs___}] := lessAsString[a, b] || a === b && olexComp[{as}, {bs}];
Here is the example of such a sort:
In[5]:= Sort[{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 11, 0}, {0, 0, 1, 12}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}, olexComp]
Out[5]= {{0, 0, 1, 12}, {0, 0, 11, 0}, {0, 0, 7}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}}
alphaSort = #[[ Ordering # Map[ToString, PadRight##, {2}] ]] &;
This works by preparing the data for the default Ordering sort, and then using that order to sort the original list.
In this case, padding all of the lists to the same length keeps this Sort property from interfering:
Sort usually orders expressions by putting shorter ones first, and then comparing parts in a depth-first manner.
ToString is used to get an alphabetical order rather than a numeric one.
This should do it
{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 10, 0}, {0, 6, 2}, {5, 1, 2}, {0, 3,
6, 1, 4}} // SortBy[#, ToString] &
This works because lexically, comma and space precede the numbers, so {a,b} is lexically before {a,b,c}.

How do I get rid of gray boundaries for ArrayPlot in Mathematica?

I have the following plot.
lst={{1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0,
0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0,
0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0,
1}, {1, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1}};
ArrayPlot[lst, Mesh -> All,
MeshStyle -> Directive[AbsoluteThickness[3.], Gray, Opacity[0.1]]]
But it does not look as I expected, in which I want the grey boundaries/grids for the black squares to be overshadowed by the color of these black squares. Only show the gray boundaries/grids of the white squares.
This isn't something that can be easily solved using built in options (AFAIK). You can define a custom function that plots the gridlines only at those rows and columns that you need and masks the others. Here is my solution:
gridArrayPlot[mat_?MatrixQ, options___] := Module[{dim = Dimensions#mat},
Show[
ArrayPlot[mat, Mesh -> ({Range[#1 - 1], Range[#2 - 1]} & ## dim), options],
ArrayPlot[mat, Mesh -> ({{0, #1}, {0, #2}} & ## dim),
ColorRules -> {0 -> Directive[Opacity#0, White]},
options /. Opacity[_] :> Opacity[1] /. (RGBColor[___] | GrayLevel[_]) :> White
]
]
]
The above solution first plots an ArrayPlot, drawing the mesh everywhere except at the outer boundaries and overlays a second ArrayPlot with the White cells set to be transparent, and draws White mesh lines on the outer boundary (to mask the bits sticking out from the previous plot).
You can call the above function as
gridArrayPlot[lst,MeshStyle -> Directive[AbsoluteThickness[3.],Gray,Opacity[0.1]]]
and the output is:
How about just ditching grid lines and mesh lines and using Epilog and Line?
ArrayPlot[lst, Mesh -> False, Frame -> False,
Epilog -> {GrayLevel[0.5], AbsoluteThickness[1],
Line#Table[{{2 + i, 8}, {2 + i, 1}}, {i, 0, 5}],
Line#Table[{{1, 2 + i}, {8, 2 + i}}, {i, 0, 5}]}]
This is obviously specific to this list of data but is straight forward to generalize to data where you have "x" unit black "perimeter" and "y" times "y" white square (i.e. a y+2x list of rows and columns).
gridArrayPlot[mat_?MatrixQ] := Module[{dim = First#Dimensions#mat,
white = Length#Cases[mat, {__, 0 .., __}], black, left, right, grid},
black = (dim - white)/2;
left = black + 1;
right = dim - black;
grid = white - 2;
ArrayPlot[mat, Mesh -> False, Frame -> False,
Epilog -> {GrayLevel[0.5], AbsoluteThickness[1],
Line#Table[{{left + i, right}, {left + i, black}}, {i, 0, grid}],
Line#Table[{{black, left + i}, {right, left + i}}, {i, 0, grid}]}]
]

Resources