05AB1E, 85 81 bytes
2FINi(}Θ©˜ƶIgäΔ2Fø0δ.ø}2Fø€ü3}®*εεÅsyøÅs«à]+ÐU˜ê¦©vyX®y†AS:¾1:'a0:4FJTx:€Søí}S2¢: "If you have participated in the previous challenge, having to count the liberties of multiple groups may require a quite different strategy." That's an understatement, haha. This answer is almost 8 times as large as my 05AB1E answer for the related challenge. Although this is primarily because flood-filling is so expensive in 05AB1E; and the conversion I use is currently pretty verbose as well..
Uses -1/1 for O/X and 0 for empty spaces.
Try it online or verify all test cases.
Explanation:
Step 1: Flood-fill the individual islands. I've done this before in 05AB1E for this challenge (which actually contained a bug that I discovered thanks to the final test case here):
2F # Loop 2 times (for each 1/-1 type of piece individually): I # Push the input-matrix Ni } # If the 0-based loop-index is 1: ( # Negate all values Θ # Check which values are equal to 1 (maps 1→1; 0→0; -1→0) © # Store this in variable `®` (without popping) ˜ # Flatten it to a list ƶ # Multiply each value by its 1-based index ä # Convert it back to the matrix, Ig # using the input-length amount of rows Δ # Loop until it no longer changes to flood-fill: 2Fø0δ.ø} # Add a border of 0s around the matrix: 2F } # Loop 2 times: ø # Zip/transpose; swapping rows/columns δ # Map over each row: 0 .ø # Add a leading/trailing 0 2Fø€ü3} # Convert it into overlapping 3x3 blocks: 2F } # Loop 2 times again: ø # Zip/transpose; swapping rows/columns € # Map over each inner list: ü3 # Convert it to a list of overlapping triplets ®* # Multiply each 3x3 block by the value in matrix `®` # (so the 0s remain 0s) εεÅsyøÅs«à # Get the largest value from the horizontal/vertical cross of # each 3x3 block: εε # Nested map over each 3x3 block: Ås # Pop and push its middle row y # Push the 3x3 block again ø # Zip/transpose; swapping rows/columns Ås # Pop and push its middle rows as well (the middle column) « # Merge the middle row and column together to a single list à # Pop and push its maximum ] # Close the nested maps, flood-fill loop, and outer loop + # Add the values in the two matrices together Step 2: Loop over the individual islands, and convert all 0s to 1s; the current island to 0s; and all other islands to lowercase letters, as preparation for the next step:
Ð # Triplicate the resulting matrix U # Pop one, and save it in variable `X` ˜ # Flatten another one ê # Sort and uniquify the values ¦ # Remove the leading 0 © # Store these island-values in variable `®` (without popping) v # Loop over each island-value `y`: X # Push matrix `X` ® # Push list `®` y† # Filter the current island to the front AS # Push the lowercase alphabet as list : # Replace the island-values with letters ¾1: # Replace all 0s with 1s 'a0: # Replace all "a" (the current island) with 0s Try the first 2 steps online (with some added debug-lines).
Step 3: Use the same method as in the linked challenge to get the liberty-counts of each island:
4F # Loop 4 times: J # Join the inner rows together to strings T # Push 10 x # Double it (without popping): 20 : # Replace all "10" with "20" €S # Convert each row back to a list again øí # Rotate the matrix 90 degrees clockwise: ø # Zip/transpose; swapping rows/columns í # Reverse each inner row } # Close the loop S # Convert the matrix to a flattened list of characters 2¢ # Count how many 2s are in this list Try the first 3 steps online (again with added debug-lines).
Step 4: Convert the current island to this count in the matrix:
# The matrix from the triplicate of step 2 is still on the stack y # Push island-value `y` from the still open loop of step 2 : # Replace all of these islands with its count from step 3 # (after which the resulting matrix is output implicitly)