# How do I encode this replacement rule?

I'm pulling a 5x5 array from a larger array. The small sub-array (call it S) can contain any combination of the symbols A, B or 0. What I'd like to do is: if the array contains any matching pairs between the center cell and a border cell with a 0 between them, we change the zero to match.

To enumerate (and make perfectly clear what I'm talking about) here are all the possible cases (using ? as a wildcard):

 ? ? A ? ?          ? ? A ? ?
? ? 0 ? ?          ? ? A ? ?
? ? A ? ?   ---->  ? ? A ? ?
? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?

? ? ? ? A          ? ? ? ? A
? ? ? 0 ?          ? ? ? A ?
? ? A ? ?   ---->  ? ? A ? ?
? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?

? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?
? ? A 0 A   ---->  ? ? A A A
? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?

? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?
? ? A ? ?   ---->  ? ? A ? ?
? ? ? 0 ?          ? ? ? A ?
? ? ? ? A          ? ? ? ? A

? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?
? ? A ? ?   ---->  ? ? A ? ?
? ? 0 ? ?          ? ? A ? ?
? ? A ? ?          ? ? A ? ?

? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?
? ? A ? ?   ---->  ? ? A ? ?
? 0 ? ? ?          ? A ? ? ?
A ? ? ? ?          A ? ? ? ?

? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?
A 0 A ? ?   ---->  A A A ? ?
? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?

A ? ? ? ?          A ? ? ? ?
? 0 ? ? ?          ? A ? ? ?
? ? A ? ?   ---->  ? ? A ? ?
? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?


Also these rule(s) stack so you can have something like this:

 A ? ? ? ?          A ? ? ? ?
? 0 ? ? ?          ? A ? ? ?
? ? A 0 A   ---->  ? ? A A A
? ? ? ? ?          ? ? ? ? ?
? ? ? ? ?          ? ? ? ? ?


And likewise for B. There's obviously a huge amount of symmetry in this situation, but I have no idea how to exploit it to avoid writing out 8 separate replacement rules. Seems like there should be clever way to just write one replacement rule that does the job. I'm stumped on that though :)

Edit: I'm using Mathematica 10

• I note the filling used here differs from the requirement in the earlier, very similar question. There, only the even row/column were to be filled, here it is any in the local surroundings. Is this what is intended for both (in that case, the other answer does this by removing the even test)? – ciao Apr 29 '16 at 4:16

Function - just feed it the 5 x 5 array, returns updated array:

chg[mat_] := ReplacePart[mat, {x_ /; 2 <= x <= 4, y_ /; 2 <= y <= 4} /;
mat[[x, y]] === 0 && mat[[2 x - 3, 2 y - 3]] === mat[[3, 3]] ->
mat[[3, 3]]];


Personally, I find even that messy, and prefer (as in this is how I'd do it) this:

chg2 = ReplacePart[#, Position[#, 0]~Intersection~Position[ArrayPad[Downsample[#, 2], 1],
#[[3, 3]]] -> #[[3, 3]]] &;

• Woah, I didn't know Condition could be used like that! On the sidenote, since the array contains variables A and B, mat[[x,y]] == 0 may not evaluate. === would be better. – JungHwan Min Apr 29 '16 at 4:57
• @JHM - yes, it's a convenient (if not explicitly exemplified in the documentation) way of limiting what makes it through the "rest" of the rule/condition train. Re: the evaluation, yep, I thought of putting a note about silent failure, and showing the extended "catch all" version, but the end result is of course the same. Actually, now that I think about it, that's sneeky/bad coding, so editing now... – ciao Apr 29 '16 at 5:11

This may not be as clear as 8 Rules, but hey, it works!

ToMatch[input_] :=
Module[{center = input[[3, 3]], temp},
temp = input;
temp[[2 ;; 4, 2 ;; 4]] =
MapIndexed[
If[#1[[2, 2]] === 0 && #1[[Delete[#2, 0]]] === center,
center, #1[[2, 2]]] &, Partition[input, {3, 3}, {1, 1}], {2}];
temp]

• The OP seems to be asking for a rule-based solution... – ciao Apr 29 '16 at 4:13
• Thanks. Yes it just seems it should be possible to compress the 8 rules down to one because they are so similar.... – Eriek Apr 29 '16 at 4:26