Given a 2D array (arbitrary numeric / evaluates to numeric elements, simplified for examples, and can be arbitrary dimensions so long as the operation makes sense, I'm working with 2K X 2K in my application):
test={{2, 2, 2, 2, 1, 1, 1, 2, 2, 1}, {2, 2, 2, 2, 2, 1, 1, 1, 2, 2}, {2,
2, 2, 1, 1, 1, 1, 1, 1, 2}, {1, 2, 2, 1, 2, 1, 1, 1, 2, 1}, {1, 2,
1, 1, 1, 2, 2, 1, 2, 2}, {1, 1, 2, 1, 2, 1, 2, 1, 2, 1}, {1, 2, 1,
1, 1, 2, 2, 1, 2, 1}, {2, 1, 2, 2, 1, 2, 1, 2, 2, 2}, {2, 2, 1, 1,
1, 1, 1, 1, 2, 1}, {2, 1, 1, 2, 1, 1, 2, 1, 2, 2}};
in MatrixForm
:
I need to find the position(s), if any, of elements that are "boxed" by the same value of the element, with corners/edges treated the traditional way (i.e., corners have just 3 neighbors, edges have 5).
So, in the example array, the result should be
{{1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {3, 7}}
I'm using
boxed[array_] :=
SparseArray[Unitize[Subtract[MaxFilter[array, 1], MinFilter[array, 1]]],
Automatic, 1]["NonzeroPositions"]
which performs fairly well, curious if there's a more elegant/better performing method.
Update: Here are some timings of answers so far on the netbook (for comparison, times for what I've tested on the workstation are ~1/20 of these). Logarithmic scale, else two become noise:
The current scheme I'm fiddling with is ~twice as fast as my current posted above, so there's twenty minutes saved on app. runs, but I'm sure there's some more clever ideas yet to be seen.
The nice compiled recent answer is not suitable, since elements can (and often are) out of machine-precision range (and it would be nice to extend this to completely arbitrary elements, e.g. symbols, etc., but not required.)