Contaminated Squares
JavaScript, 105 97 bytes
Saved 8 bytes thanks to @Patrick Roberts!
l=a=>a.slice(1,-1)
p=a=>l(a).map(l)
c=a=>a.join``.replace(/[^0]/g,"")
s=a=>c(p(a))<c(a)?s(p(a)):a
Defines function s
, which returns a 2D array of integers when provided a 2D array of integers as input.
How it Works
function
l
: given an arraya
, returns a copy without its first and last indexes.function
p
: given a 2D arraya
, callsl
to remove the first and last row, then for each remaining row callsl
to remove the fist and last column. This performs the onion peeling.function
c
: given a 2D arraya
, returns a string that only contains the0
s in the stringified form ofa
.function
s
: given a 2D arraya
, callsc
on the peeled form of the array given byp
, and on the array itself. Compares these strings lexicographically to determine if the peeled form has less0
s than the original. If it does, then the original is contaminated, so calls
recursively on the peeled form. Otherwise return the original.
Retina, 60 57 bytes
Byte count assumes ISO 8859-1 encoding. The trailing linefeed is significant.
+`(?<=(?=.*0|[^_]+(¶0|0¶|0.*$))^[^_]*)(^.+¶|¶.+$|.?\b.?)
Try it online!
Explanation
Due to the trailing linefeed, this finds all matches of the regex after the `
and removes them from the input. Due to the leading +
this is done repeatedly until the output stops changing (which will be because the regex will stop matching).
As for the regex itself, it consists of two parts:
(?<=(?=.*0|[^_]+(¶0|0¶|0.*$))^[^_]*)
This part checks whether there's a 0
anywhere in the outer shell. It does this by moving the regex engine's "cursor" to the beginning of the string with a lookbehind (we use [^_]
to match both digits and linefeeds):
(?<=...^[^_]*)
And then from that position we use a lookahead to find a 0
either in the first line, adjacent to a linefeed, or in the last line:
(?=.*0|[^_]+(¶0|0¶|0.*$))
Then the actual match will consist either of the first line (including its trailing linefeed), the last line (including its leading linefeed) or the first or last character of a line, where we abuse the word boundary \b
as a beginning/end of line anchor:
(^.+¶|¶.+$|.?\b.?)
Jelly, 19 16 bytes
Fœ^F}P
ḊṖZµ⁺⁸ßç?
Try it online! or verify all test cases.
How it works
ḊṖZµ⁺⁸ßç? Main link. Argument: M (2D list)
Ḋ Dequeue; remove the first row.
Ṗ Pop; remove the last row.
Z Zip; transpose rows with columns.
µ Combine the chain to the left into a link.
⁺ Copy the link, executing it twice.
The copy removes the first and last column and restores the orientation.
ç? If the helper link returns a non-zero integer:
⁸ Return M unmodified.
ß Else, recursively call the main link on the "peeled" M.
Fœ^F}P Helper link. Arguments: P ("peeled" M), M (unmodified)
F Flatten P.
F} Flatten M.
œ^ Perform multiset symmetric difference, removing the elements of P from
the elements of M, respecting multiplicities, leaving precisely the
elements of the outer shell.
P Return the product of the remaining elements.