Explanation
I'll addHere is what the individual stages do:
ii - Combines all pairs of i into - to reduce the phase characters.
+`(.)\1|0 <empty> Now if there are two consecutive identical characters left, it's either -- or two identical matrices. In either case, multiplying them gives the identity. But we don't need identities, so we just remove all of them, and the explicit identities (the 0s) as well. This stage is repeated in itself with + until the result stops changing. This ensures that things like 123321 get resolved completely, such that the next step can assume that all pairs of digits are distinct.
(.)-|(\d)(\d) -$1$3$2 This is actually two separate transformations in one (for golfitude). Note that if the first alternative matches, $2 and $3 are empty, and if the second one matches $1 is empty. So this can be decomposed into these two steps:
(\d)(\d) -$2$1 This just swaps all pairs of digits and adds a more detailed explanationminus sign. Since we removed all 0s and all identical pairs, this will only match 12, 23, 31, 21, 32, 13. This step may seem weird, but it allows me to only check for half of these cases later on, because the ones I can't process then will be swapped here in the next iteration.
The other part of the above stage was:
(.)- -$1 This gradually moves - signs all the way to the left (one position per iteration). I do this such that ultimately they are all next to each other and get resolved in the earlier step.
12 i3 23 i1 31 i2 These three stages now simply resolve the three pairs of products. As I said above, this will only catch half of the relevant cases, but the other half will be taken care of in the next iteration, after the previous step swapped all pairs.
)`(\d)i i$1 This is the last stage of the loop. It's similar to the one that shifts - to the left, except for i. The main difference is that this one swaps i only with digits. If I used (.)i then in cases where I get a -i or i- the two would be swapped indefinitely and the program wouldn't terminate. So this only swaps them to the right of the - signs. This is sufficient - as long as all - and i appear together at some point, they can be resolved correctly.
^\D*$ $&0 The final step (outside of the loop). Remember that we always deleted all identities, so if the result is actually the identity (times a phase), then we won't have the required digit in the output any more, so we add it back.
As an example, here are all the intermediate forms of 0223202330203313021301011023230323 (skipping stages that don't perform any changes):
0223202330203313021301011023230323 32221321312323323 322213213i3323323 322213213i33i13i1321321312 # Remove identities 322-i3323-i33i33i13i131-12-132 # Swap all pairs -i1223-i3331-i33i33i13i1i3-132 # Resolve 12 -i12i1-i3331-i33i33ii3-i2i1132 # Resolve 23 -i1-2i3i2-3i33i33i3-ii2i1132 # Resolve 31 -i1i-i231i-i33i3332i-iii213-312 # Move - to the left and swap pairs -i1i-i231i-i33i3332i-3-i213i3 # Resolve 12 -i-i1-i23i2-ii3i213-i33 # Move i to the left -i-i1-ii1i2-ii3i213-i # Remove identities -i1-ii1ii-ii3i1i-i32-3i # Move - to the left --ii-i1-2-i3 # Move i to the left -1ii-1ii3-ii3-i1-2-i3 # Resolve ii i1-2-i3 # Remove identities i-i1i1-i1i32i3 # Move -ii3 to the left i-1-i23 # Move i to the left -i1ii-i1i31i-32 # Move -3 to the left and swap pairs -i-i1ii1-i1i3332 # Move i to the left --ii1ii-ii1i331-23 # Move - to the left and swap pairs --ii1ii-iii1331-i1 # Resolve 23 ----1-i1 # Resolve ii 1-i133i1 # Remove identities -1i1 # Move - to the left -i11 # Move i to the left -i # Remove identities. Now the loop can't change this any longer. -i0 # Fix the result by adding in the 0.