[Question]
  [
Related: [Multiply Quaternions](https://codegolf.stackexchange.com/q/36928/78410)
## Challenge
Given a string made of `ijk`, interpret it as the product of imaginary units of [**quaternion**](https://en.wikipedia.org/wiki/Quaternion) and simplify it into one of the eight possible values `1`, `-1`, `i`, `-i`, `j`, `-j`, `k`, `-k`.
The evaluation rules are as follows:
$$
ii = jj = kk = -1 \\
ij = k, \quad jk = i, \quad ki = j \\
ji = -k, \quad kj = -i, \quad ik = -j
$$
The multiplication of quaternions is associative but not commutative. This means that you may do the simplification in any order, but you cannot reorder the items.
For the I/O format, function parameter and return from a function should be done as a string (list of chars or list of codepoints is also OK). You may assume the input is not empty. You may output any amount of leading and trailing whitespace (spaces, tabs, newlines).
## Test cases
```
i -> i
j -> j
k -> k
ij -> k
ji -> -k
kk -> -1
ijkj -> -j
iikkkkkjj -> k
kikjkikjk -> -k
kjijkjikijkjiki -> 1
jikjjikjikjikjjjj -> j
```
  
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), ~~32~~ ~~29~~ 27 bytes
```
≔⁰θＦＳ≔⁺×θＸ³℅ι℅ιθ‹³﹪θ⁸§1ijkθ
```
[Try it online!](https://tio.run/##VYxBCsIwFET3niJ09T9EUNwIXXVZUAzoBUIT629jYpNUvX1MsC7cDDzmzXQ36TsnTUpNCNRb2HA2Yb26Os@gtY85nqMn2wMiWwxh5gAXuusAE2fCvbSHHWcnr8hKA4SIf/Q9FPklwkGHUOSjU7NxZb/P@q9tYmuVfkO1pWGsyg7rlMYh00Djkmn9NB8 "Charcoal – Try It Online") Link is to verbose version of code. Explanation: The values are encoded to integers equivalent to `0..7` (modulo `8`) in the order `1`, `i`, `j`, `k`, `-1`, `-i`, `-j`, `-k`. The multiplications by `i`, `j` and `k` have the following effect on the integer:
* Multiplying by `i` is equivalent to tripling the integer and adding `1`.
* Multiplying by `j` is equivalent to adding `2` to the integer.
* Multiplying by `k` is equivalent to tripling the integer and adding `3`.
Edit: Thanks to @NickKennedy for saving 3 bytes by pointing out that the ordinals of `i`, `j` and `k` are equivalent (mod 8) to `1`, `2` and `3` respectively. This means that the integer needs to be tripled if the ordinal is odd, and then the ordinal can be added to it.
Edit: Furthermore, tripling the integer (mod 8) if the ordinal is odd is equivalent to multiplying the integer by 3 to the power of the ordinal, for a further 2 byte saving.
```
≔⁰θ
```
Start with `0`.
```
ＦＳ
```
Loop over the input...
```
≔⁺×θＸ³℅ι℅ιθ
```
... multiply the current value by 3 to the power of the ordinal, then add the ordinal.
```
‹³﹪θ⁸
```
Output a `-` sign if the result (mod `8`) is greater than 3. (There are other ways to express this in Charcoal but sadly I couldn't do better than 5 bytes.)
```
§1ijkθ
```
Output `1`, `i`, `j`, or `k`, depending on the result (mod `4`).
[Answer]
# [sed -r 4.2.2](https://www.gnu.org/software/sed/), 71
Using @Neil's [Retina 0.8.2](https://codegolf.stackexchange.com/a/226318/11259) approach:
```
:
s/k/ij/
s/ii|jj/-/
s/ji/-ij/
s/(\w)-/-\1/
s/--//
t
s/ij/k/
s/^-?$/&1/
```
[Try it online!](https://tio.run/##LUuxDgJRCNv5DmN0IM2tLv7IxUmHlsQzvktc/HYR9BqghZZxu2aebCBAoZh8S/CWIvx/PMyvo8PnqRd3wNaOqr6KL37eYT8hkyYLo0y0aBEyMhoqh6FfW6gtxjYrXj5jq8Jneaxc7iP9@QU "sed 4.2.2 – Try It Online")
---
Previous answer:
# [sed -r 4.2.2](https://www.gnu.org/software/sed/), 97
Saved 3 bytes thanks to @FryAmTheEggman.
```
:
s/(\w)\1/-/
s/(\w)-/-\1/
s/--//
s/ij/k/
s/jk/i/
s/ki/j/
s/ji/-k/
s/kj/-i/
s/ik/-j/
t
s/^-?$/&1/
```
[Try it online!](https://tio.run/##LYrBCgJBDEPv/Q4RPZSwVy/@yOJJD2lgV5wF/96xHSa0TcJrez17v1nDZf1e1wWOmR2eNYs7yhhQeQgsFxGjEz6AAj4IBU90ZHz4/YTzgt5pYTKGBU0VFEaqFEmoGGuKQtS8@Z6cmpP67e@D@9a6f/4 "sed 4.2.2 – Try It Online")
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 82 bytes
```
e=>e.map(q=>p=+p?q:o[i=o.search(p+q),s^=i<5,i+2],p=s=1,o=' 1jikjijkij')&&'- '[s]+p
```
[Try it online!](https://tio.run/##TVBBbsMgELzzir0kgGwjuVIvTdc99RWuq1guaXdJAjFWFanq211DnaoIGGlmltmF@88@DiOFqTr7NzsfcLbYWHPqg7pgE7AIT5cH3xJ6E20/Dh8qFBddxlekx/uSiruuDBixLj1KqJkcEztiqbdbWYFsY1eEebJxGvpoIyDsBUHVAAlOwMIlcIL4FzmrlRMuC1W9KC5rFQsilxavXrek5XMrSdlLC@ud2FqklnJbeTOvsXszjXRS2sRwpEnJl7PUeeorYAPXG53MUuud@BvBHPz43C//oFoqwXc6@b8EwODP0R@tOfp3JTceNlGWcFCtMYY6vcYBIvh/9PLyt97NPw "JavaScript (Node.js) – Try It Online")
Input array of chars, output string.
---
# [JavaScript (Node.js)](https://nodejs.org), 66 bytes
```
e=>e.map(q=>p=p<99?q:(s^=(~p+q)%3&&36,p^=q)?104|p:49,p=s=9)&&[s,p]
```
[Try it online!](https://tio.run/##PVDLbsMgELzzFVxig2qjRokqOSmOqqhf0GOaKBbFyUJisEFVpD5@3QWXdgU70s7sLItq3hsnBrC@7MybHFs@Sl5Ldm0s6XltuX2sqk2/Iu7Aybe96@lskWWLh8IeeE838/vlp10tq8JyxyuaZTtX2P3opfOicdJhjo8IcFljQCqCQjqCRqB@UU1sqZGeiHIeGD1xpUIAOoZKWg1aTfevRUUt6JRjdR4Mgx50OkqlsUfmB7gSypy9gCf5a5fTacsb5jW@/ZWjOKd0jf5XYK0ZnhtxJmQHBZZ7GvUfCGNhOuexCSu@BOvuxNrBXLfnZtiGjySMsZbsQob9NEbENsFE4p88oSHSo9bJzlwku5gTyWcGz1xeRHeOZcAg@aLr8Qc "JavaScript (Node.js) – Try It Online")
Input array of codepoints, output array of codepoints.
[Answer]
# [Retina](https://github.com/m-ender/retina/wiki/The-Language), 43 bytes
```
3{`\bii
-
ij
k
\bik
-j
}T`ijk`jki
--
\B$
1
```
[Try it online!](https://tio.run/##LYoxCoBAEAP7vEPB5grxBzZ@wNLiFCySgIXYiW8/98SwGwIz537xWPvSdlMuw52XjUQCBSO2kYRnzpSzHCQBy9igL4WoTogiXIcF0jUKQut7WBXRf4cenP4v8gI "Retina – Try It Online") Link includes test cases. Explanation:
```
3{`
```
Loop three times.
```
\bii
-
ij
k
\bik
-j
```
Perform some simplifications.
```
T`ijk`jki
```
Rotate by 120° along the `i=j=k` axis.
```
}`
```
Repeat the above loop until the output converges. (Since the inner loop iterates three times, the rotations will cancel out.)
```
--
\B$
1
```
Tidy up the result.
[Answer]
# JavaScript (ES6), ~~60 55 53~~ 52 bytes
Expects an array of ASCII codes. Returns a string.
This is based on [@Neil's excellent insight](https://codegolf.stackexchange.com/a/226315/58563).
```
a=>["-"[a.map(y=>x+=y%2*2*x+y,x=4),x&4]]+"1ijk"[x&3]
```
[Try it online!](https://tio.run/##nZLbDoIwDIbvfQrSRMNBRlBux4WvQbhYlJmuwAioGU8/DzFqNGTEP23vvvZvUyUuYtj32J3iVh8qK7kVPC8ghkKwRnT@yHMT8XG5CTehica14VmwNqusLCNIUREUZrUt7V63g64rVuujL/2CMbY7S1n1TPa68QHB@1JQBoGXJJ6HCwerplnlYmmaJReLP4Pnswqn2NjJEk2yqdszfbl@sc5bIdJd6t1g/r6EpB4Jf@yr7q6RnhU@5qbuO9/8Ij3jJnj/hr0C "JavaScript (Node.js) – Try It Online")
### How?
According to Neil:
> 
> at each step if the input is `i` or `k` then the integer is tripled and
> incremented, and if the input is `j` or `k` then 2 is added to it
> 
> 
> 
In JS at least, it is shorter to express the above as follows:
$$x \gets x + (y \bmod 2)\times 2\times x+(y \bmod 4)$$
where \$x\$ is the sum and \$y\$ is the ASCII code of the next input character.
[@NickKennedy](https://codegolf.stackexchange.com/users/42248/nick-kennedy) noticed that it may actually be optimized one step further (thanks to Neil as well for pointing that out):
$$x \gets x + (y \bmod 2)\times 2\times x+y$$
We end up with the following encoding for \$x\$:
```
… x x 2 1 0
\___/ | \_/
  |   |  |
  |   |  +---> 00 = 1, 01 = i, 10 = j, 11 = k
  |   +------> sign bit, set for positive
  |            (which is why we start with x = 4)
  +----------> upper bits are ignored
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~72 67 66~~ 64 bytes
```
->s{w=k=0;s.bytes{|x|k>0&&w^=13[k+2-x&3];k^=x&3};?-*w+"1ijk"[k]}
```
[Try it online!](https://tio.run/##KypNqvyfZvtf1664utw229bAulgvqbIktbi6pqIm285ATa08ztbQODpb20i3Qs041jo7zhZI11rb62qVaysZZmZlK0Vnx9b@L1BIi1bKzFSK5YKwsuCsbBgrCy6bBZfNgstmw2Wz4bLZSHqzs0AYgrJABvwHAA "Ruby – Try It Online")
Thanks dingledooper for -2 bytes.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~40~~ 37 bytes
```
ΔJ2ôεDg<iËi¼õë…ijkyмyC3%<½]J1«н¾É'-×ì
```
[Try it online!](https://tio.run/##AU4Asf9vc2FiaWX//86USjLDtM61RGc8acOLacK8w7XDq@KApmlqa3nQvHlDMyU8wr1dSjHCq9C9wr7DiSctw5fDrP//aWprav8tLW5vLWxhenk "05AB1E – Try It Online") or [Try all cases!](https://tio.run/##VY09CsJAEIX7OcUUilUMarvY@FPYeAKL1Sw6O5IVE5BY2Yqt4A1stDRdtMj24hm8SNxoGh/zB9883lRGi2ImY@zizASqaSI5JYVC4GA8LJ7HUdvenml/LsgeKM9sai/v3Zk0J68s6XXqIr9PRq388rrnD7tvePZkr4WzAmwWtFS4VjJACiEwgOibVez/Eqr1F@p5ofGWcpu4eIG1rytUBYEGBtKgCbg8WAMRl9KOEOtvA@sSEVfTvTtOXJUTfAA)
```
Δ                # until the output doesn't change:
 J2ô             #   split the string into groups of 2
                 #   (last one might be a single character)
 ε               #   for each group y:
  Dg<i           #     if the length of y is 2:
      Ëi         #       if all characters are the same:
        ¼õ       #         increment the '-'-counter and return empty string
       ë         #       else:
        …ijkyм   #         remove the two characters from "ijk"
        yC3%<½   #         increment the '-'-counter if y converted from binary ...
                 #         ... is equal to 2 modulo 3
]                # close all loops and if statements
J1«              # append a 1
   н             # take the first character
    ¾É'-×ì       # if the '-'-counter is odd, prepend a '-'
```
---
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~44~~ 43 bytes
```
Δ…ijk©Dâ•KĀ ‰9Ï•„ -®«ÅвJ#:Σ'-Ê]„--KD'-såi1«
```
[Try it online!](https://tio.run/##yy9OTMpM/f//3JRHDcsys7IPrXQ5vOhRwyLvIw0Kjxo2WB7uB3IeNcxT0D207tDqw60XNnkpW51brK57uCsWKKyr6@2irlt8eGmm4aHV//9nZwGNyMrMhpIA "05AB1E – Try It Online") or [Try all cases!](https://tio.run/##XU47CsJAEO3nFAMKVqtYKsFKLUzhCSyiWcjsiCtGsN3GxsbG2iKiIIKIR8haB8@Qi8SNpvIx//eYmWkQR8UsWGMPZzqUTR0HU5LoeTgYD4vskJsLKU6vfZvkJvFfBnPz6Ni9a3JzRJHe05vdvp@jWjc7NYTdTdxYCL/fELE9Uzu9FW4RwCaiucSVDEKkBYQaEFt6uW797lXp7wUP61/tQhYEChhIgSLgsmAFRFxCOYZYfR1YlRRxFZ3c8cSVOcAH)
```
Δ                    # Until the output doesn't change:
…ijk©Dâ              #   = ii ij ik ji jj jk ki kj kk
•KĀ ‰9Ï•" -®«ÅвJ#    #   =  -  k -j -k  -  i  j -i  -
:                    #   Replace
Σ'-Ê                 #   Sort "-" to the front
„--K                 # Remove all non-overlapping occurences of "--"
'-såi                # If the result is a substring of "-":
1«                   #   Append a 1
```
[Answer]
# [Retina 0.8.2](https://github.com/m-ender/retina/wiki/The-Language/a950ad7d925ec9316e3e2fb2cf5d49fd15d23e3d), 44 bytes
```
k
ij
ii|jj
-
ji
-ij
--
}`.-
-$&-
ij
k
\B$
1
```
[Try it online!](https://tio.run/##LUwxDoBACNv7DjUumPgFFz/hcA4OpYmDcdS3n2CugYbSwnXcPPfaj@NaqkAH@bjD4ISFNAPeMhmsGyx9YVs6zLUSKWITSeWgPFYiHojyvyFPi2oc8fCpVoEP "Retina 0.8.2 – Try It Online") Link includes test cases. Explanation:
```
k
ij
```
Replace `k` with `ij` as an interim measure.
```
ii|jj
-
```
Substitute `-1` for `ii` and `jj`.
```
ji
-ij
```
Substitute `-ij` for `ji`.
```
--
.-
-$&-
```
Propagate `-`s to the left.
```
}`
```
Repeat until no more changes can be made.
```
ij
k
```
Convert `ij` back into `k`.
```
\B$
1
```
Output `1` if there is no `i`, `j` or `k`.
My original idea unfortunately turned out to be as long as the naïve approach which has since been golfed anyway:
```
^(..)+$
-ijk$&
+`^(.*)((\w)\3|(j|k)(i|j))
-$1$5$4
ijk
-
--
\B$
1
```
[Try it online!](https://tio.run/##LYrBCgJBDEPv@Y4qrcssLOoPeNmfGGQ9eGgDHkTwMv8@dmRDUkpe3s@Pvx79oOvW7zrPNgmKB@WIacviZKr1a/XcNBpNvYUZiixylQtyiIJSgHoTLL07Aswa4eB4GHDnUCRxxj9gDOTcb86TO3enfg "Retina 0.8.2 – Try It Online") Link includes test cases. Explanation:
```
^(..)+$
-ijk$&
```
Prepend `-ijk` if there are an even number of letters, because the next stage doesn't affect the parity and we want to end up with a single letter if possible.
```
+`^(.*)((\w)\3|(j|k)(i|j))
-$1$5$4
```
Repeatedly delete two identical letters or exchange two unsorted letters. These operations both negate the final result.
```
ijk
-
```
Reduce any remaining `ijk` to `-1`.
```
--
\B$
1
```
Tidy up the result.
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), ~~71~~ 63 bytes
-8 bytes thanks to @coltim!
```
(r,"-",'r:"1ijk")@((8!A,4+A:a,'4+a:4 4#0,8\5717110953644).,)/4!
```
[Try it online!](https://ngn.bitbucket.io/k#eJxVj1ELgjAQx9/9FHoFKs5qNNO2l/ocFuSLcHdBID0kUZ+9zWbp2I3fsd+f21qddAJyEHGnQSIxpIckqaKjUNlRNyJWWaNVqBYbUZ2KUpZSbvbFdqdUuhLpWkVBcNfPZd2/O92GD3O5sUkubYNX8zC96dLzK7jXAhCMrfPAZJk8s2UeGJD+TPzzgfHnAznOvcQukHsLXSL3Gg6a9BmaNMyTxn6XZil2iybvYGQaajbW5ZD9aW/GQVZ09d1E4z8/Wm5iBA==)
[Answer]
# [Python 3](https://docs.python.org/3/), 89 bytes
```
a=0
for c in input():a=b'147223453614'[ord(c)%3*4+a%4]^(a&4)
print('-'[:a&4]+'1ijk'[a%4])
```
[Try it online!](https://tio.run/##HYpLCoAgFAD3naJNPS2CzFdB0EmkwIrIBBWxRae3D8wsBsbd4bCGxyjHOtmtT9dUmRd3BUIHOS7AsG8aji3vGIKwfiMrzXiBpcxwmonMkSbOKxMIVCCGt6cSmDo1iO@gMWqlz98H "Python 3 – Try It Online")
It encodes the unit quaternions 1, i, j, k, -1, -i, -j, -k as the numbers 0..7 respectively, so that `a%4` represents one of 1, i, j, k, and `a&4` represents whether the value is negated.
The loop works by accumulating a result in the variable `a`, multiplying one quaternion from the input on each iteration, much like you'd write `a = 1; for x in numbers: a *= x` to compute a product normally.
The byte-string `b'147223453614'` encodes a multiplication table for i, j, k multiplied by 1, i, j, k. Indexing a byte-string gives the ASCII values as integers, but we only care about the lowest 3 bits and, conveniently, the ASCII value of each digit 0..7 has the correct lowest 3 bits, so this is practically like indexing a list of integers. The table is 3x4 instead of 8x8 because one operand (from the user input) can only be i, j or k, and we can ignore the sign from the other operand (the accumulator variable) and deal with the sign afterwards.
The expression `ord(c)%3` converts the ASCII characters i, j, k into 0, 1, 2 respectively; the ASCII values of i, j and k are correct for this modulo 3. (If they weren't, the multiplication table could be changed.) The `^(a&4)` part XORs the result with the third bit of `a`, swapping the sign of the result from the multiplication table if this operand was negative, since we ignored the sign before.
The output uses string slicing to conditionally print the minus sign (`'-'[:4]` conveniently isn't an error in Python).
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~23~~ 20 bytes
```
3*żæ.ƒ0%8ṃ“ijk1””--¦
```
[Try it online!](https://tio.run/##y0rNyan8/99Y6@iew8v0jk0yULV4uLP5UcOczKxsw0cNc4FIV/fQsv///0cbGpjpKBgamIIIcxBhBifQxPBzkYhYAA "Jelly – Try It Online")
[Try all examples](https://tio.run/##y0rNyan8/99Y6@iew8v0jk0yULV4uLP5UcOczKxsw0cNc4FIV/fQsv/WQCEFXTsFIN/a/3C7CtfDHZse7lh0uJ3r4e4th9sfNa2J/P8/E6QikysLRGVxZYOobK7MLAidBZbVzebKBkvoGgJlssFyullcmZnZIJAFVZudmZ0FxjAtWSC1mdlQEiRqCDQQqD4zG4qyIHqzAA)
A full program taking a list of code points and printing to STDOUT.
Uses [Neil’s clever observation](https://codegolf.stackexchange.com/a/226315/42248) about the effect of multiplication by I, j and k in his Charcoal answer so be sure to upvote that one too! Thanks also to Neil for saving a byte with the observation that \$3 ^ x \mod 8\$ is 3 for all odd \$x\$ and 1 for all even \$x\$.
Thanks to @cairdcoinheringaahing for saving a byte by pointing out that I could remove the trailing `”`. Thanks to @JonathanAllan for a neat 1 byte save using `ṃ`.
## Explanation (outdated)
```
 3*                    | 3 to the power of each codepoint
   ż                   | Zip with original list of codepoints
    æ.ƒ0               | Starting with zero, reduce the list using dot product (extending the shorter argument with ones)
        %8             | Mod 8
          d4           | Divmod 4
            ị"“- “ijk1 | Index into zipped "- ", "ijk1"
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 61 bytes
```
,ḅ8‘ị“;CAĖ*VÆSȮṀƒḳẹ²^÷d5ñYƭẏ§O’b8¤
_ȷ2ç/ị“1“-i“-j“-k“i“j“k“-1
```
[Try it online!](https://tio.run/##y0rNyan8/1/n4Y5Wi0cNMx7u7n7UMMfa2fHINK2ww23BJ9Y93NlwbNLDHZsf7tp5aFPc4e0ppoc3Rh5b@3BX/6Hl/o8aZiZZHFrCFX9iu9Hh5foQ3YZArJsJIrJARDaQAPFAHBBb1/D/o4a5D3dOMzi0DKjV/3D7o6Y1kf//RytlKukoKGWBiGwQkQlmZoFFs6Ei2WCxzMxsEMiCqM3MzgJjMCcLpCYzG0pCDAAqzMyGIiBQigUA "Jelly – Try It Online")
-2 bytes thanks to caird coinheringaahing
---
Takes input as a list of codepoints, outputs as a string.
The indexing to get the final answer is terrible. Looking for a way to improve that.
This is very unclever. The first link just encodes the entire multiplication table into a size-64 list, converts the left and right arguments from base 8, and indexes into that. The main link takes the input as codepoints, subtracts 100 (which makes `ijk` equal to `567` and thus I put `-1, 1, -i, -j, -k` into `01234`), reduces the list from the left by the helper link, and then indexes the answer into a valid output format.
[Answer]
# [C (gcc)](https://gcc.gnu.org/), ~~104~~ ~~103~~ 101 bytes
```
a,z,n,h='h';f(s,d)int*s,*d;{for(a=n=9;z=*s++;n^=(~a+z)%3&&a>h?0:36)a=a>h?a^z^h:z;*d++=n;*d=a>h?a:49;}
```
[Try it online!](https://tio.run/##dZDhboIwFEb/8xQdi1qgLBqXJdLVvYBvMGfStDDaaiWAc8G4V2ctVJdhbKAtp9zz3ZTFn4y1LUUN0ignk3yCM1ghHghdhxUKOT5l@xJSoskCNySsogjrDYE/NGqC0Xw8psv8bZrMXwJK7JZumk2eNDjkUUS0WXqaPC/wuX0Umm0PPAWvR5bT8ilfen@oqrnYW/S1FxzUaVVD0wMIhS4ONQLdPv0uUlanPPBOHjDDQlqW7/MPQMBpesYdzaCrMUdBj4rS/JpBf7StQLwEZknshMCIr7Vv7V3Bxd@VIvBwZBXbFbD7uGYb5dnzbPSOCg0vvXQdr3xhbCt/XQvfRTsuHZcDrhxXAy7knQPZJ8RDrnpTPLsRqV4VD6OFUHbIe0lKKNm9dwKlVQvlZieZ3bRrAoRyj5T/7sFcZPsL "C (gcc) – Try It Online")
Apparently I had basically the same idea as tsh, using xor.
It still needs some optimization, considering how tsh's is like half the size in calculations.
* -1 byte for using tab (9) instead of space (32)
* -2 bytes for making a temp for `'h'`
Input is a null terminated array of codepoints, output is stored to a pointer to a bunch of codepoints.
```
void f(const int *src, int dst[2])
{
    int acc, tmp, sign;
    for (acc = sign = '\t'; (tmp = *src++); ) {
        // My XOR math will end up with less than 'i' for 1.
        // TODO: fix this efficiently and I can remove some checks.
        if (acc < 'i') {
            acc = tmp;
        } else {
            // Xoring all of them together will result in the result or 'h'
            acc = acc ^ tmp ^'h';
        }
        // Magic for testing when we need to negate
        if ((acc - tmp + 1) % 3 == 0 && acc > 'h') {
             // Switches between tab and '-'
             sign ^= 36;
         }
     }
     // Output sign
     dst[0] = sign;
     // Correct our xor math
     dst[1] = a < 'i' ? '1' : a;
}
```
[Answer]
# [APL(Dyalog Unicode)](https://dyalog.com), ~~33~~ 26 bytes [SBCS](https://github.com/abrudz/SBCS)
A port of [Nick Kennedy](https://codegolf.stackexchange.com/users/42248/nick-kennedy)'s [Jelly answer](https://codegolf.stackexchange.com/a/226330/64121).
```
' -' '1ijk'⌷⍨¨2 4⊤⊢⊥⍨3*2|⊢
```
[Try it on APLgolf!](https://razetime.github.io/APLgolf/?h=e9Q31dP/UdsEAwA&c=U1fQVVdQN8zMylZ/1LP9Ue@KQyuMFEwedS151LXoUddSoICxllENkAMA&f=S1PQedQ3NdQ5WEE9U50rDcHLQuFlg3hwhVnIvKxMZF42mspsFLWZmdkgkIUimJ2ZnQXGKIJZIL2Z2VAS1UKgAZnZUAQE6gA&i=AwA&r=tryapl&l=apl-dyalog&m=train&n=f)
A train submission which takes a list of codepoints as the right argument.
APL has *mixed radix decode* (`⊥`) which makes the calculation part quite short:
```
       2|⊢  ⍝ each value in the input modulo 2
     3*     ⍝ raise 3 to this power
  ⊢⊥⍨       ⍝ use the resulting numbers as a mixed radix to decode the input
```
Technically the `2|` is not needed, but without it even the test cases with 2 characters start to fail because of very large numbers.
`2 4⊤` calculates `4|⊢` and `2|4÷⍨⊢`, and both resulting integers are used to index into one string.
[Answer]
# [Vyxal](https://github.com/Lyxal/Vyxal),~~95 91~~ 55 bytes
```
λ2ẇ«½∇«:Ẋ«∨uOŻN€bMċ∇Dk«⌈Ŀṅ\e/:L‹\e*$ṅ+;Ẋ‛eeo:\erß›\e\-V
```
[Try it Online!](http://lyxal.pythonanywhere.com?flags=&code=%CE%BB2%E1%BA%87%C2%AB%C2%BD%E2%88%87%C2%AB%3A%E1%BA%8A%C2%AB%E2%88%A8uO%C5%BBN%E2%82%ACbM%C4%8B%E2%88%87Dk%C2%AB%E2%8C%88%C4%BF%E1%B9%85%5Ce%2F%3AL%E2%80%B9%5Ce*%24%E1%B9%85%2B%3B%E1%BA%8A%E2%80%9Beeo%3A%5Cer%C3%9F%E2%80%BA%5Ce%5C-V&inputs=ii&header=&footer=)
Partially ported ovs. Do I win 'Most improved'?
Makes a lot more sense now.
```
λ                                     ;                 # Lambda
 2ẇ                                                     # Chunks of 2
   «½∇«                                                 # Compressed `ijk`
       :Ẋ                                               # Cartesian square
         «∨uOŻN€bMċ∇Dk«                                 # Compressed string `e k ej ek e i j ei e`
                       ⌈                                # Split by spaces
                        Ŀ                               # Transliterate
                         ṅ                              # Join
                          \e/                           # Split by `e`
                             :                          # Duplicate
                              L‹\e*                     # (Length - 1) es
                                   $ṅ+                  # Prepended (so es are bubbled to start
                                       Ẋ                # Repeat on input until result doesn't change 
                                        ‛eeo            # Get rid of double es
                                            :\erß       # If result is a substring of 'e'
                                                 ›      # Append a 1
                                                  \e\-V # Replace es with -s
```
[Answer]
# [Retina](https://github.com/m-ender/retina/wiki/The-Language), ~~65~~ 58 bytes
```
(\w)\1
-
ij
k
jk
i
ki
j
ji|kj|ik
-$^$&
--
}`.-
-$&-
\B$
1
```
[Try it online!](https://tio.run/##LYuxCgJBEEP7fMd6rMUI@ws2/sQiZ3FFErAQweb89nVWLsyEGV7y2t58Pto41XpbR@2fc28IUDBkECYEcbd2GlHuZUEE8F0vke8S6NeCNsbMeRaVpXlYID2lJLT@C2si@vCMJ6ePSf0A "Retina – Try It Online")
Saved 7 bytes thanks to [Neil](https://codegolf.stackexchange.com/users/17602/neil)!
The main tricks deal with handling negative signs and the negative products. Negative signs are "bubbled" towards the beginning of the string to prevent needing to account for them in the other rules. The products that produce a negative such as `ji` are all reversed and then negated, to avoid dealing with them specifically. At the end, if there is no letter, we add a 1.
[Answer]
# [Factor](https://factorcode.org/) + `math.matrices math.quaternions`, 125 bytes
```
[ "1ijk"4 identity-matrix zip tuck substitute 1 n>q [ q* ] reduce dup sum 0 < 45 32 ? -rot vabs swap assoc-invert at 2array ]
```
[Try it online!](https://tio.run/##bVA9T8MwEN3zKx4dkVrRUhZAZUQsLIipYnCdC3Xc2onP6QeI3x4udjrBKXmy7949v7tK6ehD//728vp8j72K25lAMJoYO6/VjsHUduSGhGL2mhMrU9tORQrOeMewcqBdzh9oUJWGENRZFETQfTKMR3scVWZ0ikExHoqiPX4XkDAJ64Q2Z/KlzhV7SdqcNsYOUY8dxtbpz7d6oBk74igjXGPHT6L4KdZYJZP4EOcNxriC9u5AISJuiQnRX0bxlZRKQuONi9yvMZnLE5MlTEkumniepvWd8GUalF2DafAR3G1Yil0kzOFWLdZor@XJQGWnKfG42@MGj1je4XaBp9x3UBvZ3lGMpaVNTTalIhaj615cD0PkFaMRjCJMSm//jlEFv/9/EFQ@SBOfxZIqRan/BQ "Factor – Try It Online")
On TIO it's 129 bytes; this is because Factor on TIO is ancient and doesn't have [tuck](https://docs.factorcode.org/content/word-tuck,kernel.html) which is the same as `dup -rot`.
## Explanation:
It's a quotation (anonymous function) that takes an array of code points as input from the data stack and leaves an array of code points as output on the data stack.
* `"1ijk"4 identity-matrix zip tuck substitute` Convert the input to quaternions that Factor can do arithmetic on. For example, `"ijkj"` -> `{ { 0 1 0 0 } { 0 0 1 0 } { 0 0 0 1 } { 0 0 1 0 } }`
* `1 n>q [ q* ] reduce` Take the product.
* `dup sum 0 < 45 32 ? -rot` Place the code point for the sign on the data stack.
* `vabs swap assoc-invert at` Convert the product quaternion to a code point.
* `2array` Make an array out of the code points that are on the stack.
[Answer]
# [Python 3](https://docs.python.org/3/), ~~199~~ \$\cdots\$ ~~182~~ 173 bytes
```
f=lambda s,n=0:s<'.'and f(s[1:],1-n)or len(s)>1and f(s<'2'and s[1:]or(s[0]==s[1]and'-1'or{'ij':'k','jk':'i','ki':'j','ji':'-k','kj':'-i','ik':'-j'}[s[:2]])+s[2:],n)or'-'*n+s
```
[Try it online!](https://tio.run/##bVHRboMwDHzvV/jNZCVTQydVQqU/wnjoaFCTdAGRTNqG@HZmB/YyzQLrfHf4CAxf8d7747J01eP6/na7Qsh9dSjDGZ/x6m/QZaFWZZMr6UU/wkP7LIiL2qQzFsmVPP1I3kNTVTQ1xKJU2I8TGoslOszROgKGgDMELDMMJGuOTZJFwy5pca5DXRZNI/ahLugNOB8lPvl9WKIOMUAFGa8DXgWcAJzFc2LdxrjEGeO47Oo1zqY7DZY9xm19XUBG47aLCsVOfw66jfr2X2xqcu0qdfuHVusDYtfedev0mLa8fhSnl5YVRupIckcfOeYajIdvM2TpoDn8ZotyB1R89C6LIg3DaHzMOpziDPICU5hh2kJqTT@jmVEsPw "Python 3 – Try It Online")
Slightly longer version without direct mappings of \$i\$, \$j\$, and \$k\$ inter-multiplications:
# [Python 3.8](https://docs.python.org/3.8/), 174 bytes
```
f=lambda s,n=0,o='ijkijki':s<'.'and f(s[1:],1-n)or len(s)>1and f(s<'2'and s[1:]or(s[0]==s[1]and'-1'or((b:=o.find(s[1],(a:=o.find(s[0]))))-a-1)*'-'+o[2*b-a])+s[2:],n)or'-'*n+s
```
[Try it online!](https://tio.run/##bVHRasMgFH3vV/h2NdVS08FGqP2RzIc0MVTtTIgOtpV8e6YmgzF20cO95x7vQR0/w21wp5dxWpZe3Ju3a9cgT5040kGANjYtqPwZDtC4DvXY17ySlDNHhgndlcOeXPjWOkOZVVkzTFF7lELESkYWGIfI4WslhkOvXZdGSYqbX/VRkhisYZwUwGA/1GVxZY0ke1@X0TaZRr5we78E5YNHAmHQQBGYBDaBzqnJrN0YmzmtbQqzarU1eefCJI22G64DolDbbcUAslMfo2qD6v6zzcBW5BnNH5qvB8iuvanWqilPeX0vn5/a1EkZP8V2H182UIW0Q196xPmiFP14k2qHYqSr9ziQXIyTdgH38AgzYhf08DN6bCa1ij8gZyDLNw "Python 3.8 (pre-release) – Try It Online")
[Answer]
# [Haskell](https://www.haskell.org/), ~~135~~ 84 bytes
```
x#'i'=x*3+1
x#'j'=x+2
x#'k'=x*3+3
t=(cycle([pure,('-':).pure]<*>"1ijk")!!).foldl(#)0
```
[Try it online!](https://tio.run/##y0gszk7Nyfn/v0JZPVPdtkLLWNuQC8jOArK1jUCsbIioMVeJrUZyZXJOqkZ0QWlRqo6Guq66laYeiB1ro2WnZJiZla2kqaioqZeWn5OSo6GsafA/NzEzz7agKDOvRKVEKSszOwuEIQgIlP4DAA "Haskell – Try It Online")
Had a lot of trouble doing this efficiently in Haskell. Hopefully this will inspire someone to create a better Haskell answer.
[Answer]
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), 55 bytes
Port of the [Arnauld's solution](https://codegolf.stackexchange.com/a/226331/80745).
Expects an array of ASCII codes. Returns a string.
```
,4+$args|%{$x+=$_%2*2*$x+$_}
'-'[$x-band4]+'1ijk'[$x%4]
```
[Try it online!](https://tio.run/##VY/NboMwEITvfoo9GJEEfCDiGgmpp55aNccIoYSY1DYFikFFIjw79R8kWRnLMzv72TT1H23lNy3LueirvGN1BcU4h3GAz@1N3r0RD8EBZ95@t9@pI84m5BP/hAdyOVfXOA38iHGhDS9O5wmhZIPCjc98CEHtWy24EdwKYYSwgvFnxe0UcVLYKImWrLBp4kiMCV38heHM1V5hTHDzvbpcU5lwu@lFy2MUggm3OH/8xBbu4MGIQBWWXcuqWwiYDg3NO3qFA@DM9loq@7JTRgGJzRn/9Hl862VX/3xcuBpJE4vSdezznEqpGW6Y0N8He819LWRsT2vjvWp64z/dN6Fp/gc "PowerShell – Try It Online")
---
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), ~~122~~ 120 bytes
Thanks [@Neil](https://codegolf.stackexchange.com/a/226318/80745) for the `k -> ij` simplification.
```
for($s="$args";$p-ne($p=$s)){'k ij9ii|jj -9ji -ij9--9.- -$0-9ij k'-split9|%{$s=$s-replace-split$_}}
$p+'1'*($p-in'','-')
```
[Try it online!](https://tio.run/##VY9PT4NAEMXvfIpJs82CMsYeiWnSxJMnjT0a01Rc6swirCxEE8pnx4WF/pmwE96bNz9YU/6qyn6pPO@zpkhrKgvI2j4rq1DY9ULsq4NdPAiDhQqFWQsbRa3UQJwQHZkBEyZAJxGTOwQU95gQg5ZoTU51cly2jiMsVsrk@1R5W@y6LhDmVq7kjcMiFVLGEmXUd0GwCYM4lCQhBtejQfAo2As9Cu0F8aViv4WT1D6KqzmrfRonEpEeiq8Yk3myTzDSPJ5rlwcq6amPs9X8Mw5BenqYz5eI4AhLaANwJWxdUXGIQag/o9JafcIaxM7PKmWbvHZGNudG/@1l@9jYuvx@/mC38r7xqKG2TZoqawfGtIzq58w@5V5nsvBvp8FTYZrRv/heF3T9Pw "PowerShell – Try It Online")
[Answer]
# [Haskell](https://www.haskell.org/), 58 bytes
```
(\m->['-'|m 8>3]++["1ijk"!!m 4]).mod.foldl(\x y->3^y*x+y)0
```
[Try it online!](https://tio.run/##FcixDoIwFEDRX3k0JoCkjQYHF9jcdHIETBqw@to@2gBGSPx2q9zp5D7laO7WBlXUIamJl1XM4w/BscybLKvYHrVhUURwaFJBrhPK2c4m9QwLL/Pbsp2zJd0FkthDAST9BRL/mq7TcO6FEv8BanB06l@UwgbebuhGhqDBAGrQCGaF0YBo1rRm4dsqKx9j4K33Pw "Haskell – Try It Online")
A port of Neil's Charcoal answer that takes a list of codepoints as input.
[Answer]
# [Shue](https://codegolf.stackexchange.com/questions/242897/golf-the-prime-numbers-in-shue), 46 bytes
```
1
i
j
k
-1
-i
-j
-k
=1
--=
ii=-
jk=i
k=ij
j=ki
```
[Try it online!](https://tio.run/##lVXBjpswEL37KyxOdhNo0d6QUE@7p0rbQ9VLQisHJokJ2Mg2u4128@3pGEJC2E21jRSFmXl@nnl@Js3ebbW6O8q60cZRA3Nq95YYiGmKUZTrupEVMLMKGFv8SrPX5TLlnzhLx9HXgBNSwJq2CmwuGmCSJ4Tix4BDolUQdBEWMfrSPa@1oTmVisoe6T9y3UGEKrCU@nXLZXApnwhnp8JVfkzdxdVbsvQGV/r/VOpWW@pjXJPVQlqgP0XVwr0x2rB18F0YC4aCDxO60Y7mW2FE7jD5kh@oWPsnVIFfc9/SrW8kHoEtvDvC3oFlizzreafdfqjT@8dvn@8fH6Y94gatUf6H9G5p/MqzVRBbSyWcNhY7teDYaVlbwXWmkqrLyMg2lXSsk52fXVV5V3WYS991Z@c4qoXLt6ziY8vV0cbotmF3fCKI3/g1pS/sbOsBGnM@p2@yd3wRJxnnh3@oPJrSU7/HfBirNcLP@4567eAP5K0Dls/pWMABhOP26ub9qK2ST4Ax5l9kv0GtC4x@mBa68HmL99wnR6J1iAeBQ5xzCp5/j8guhzKob736A@J6dtS6q3aNJqcB7UdX@7KYrzygG/G6OiB0VxdqA6wCxSyfxfwtcuhmoRM98zjBM39xxPvQ6eD@5Owi0dlsNUOOE0OSHW6unog9OZIxN7l1zYzeGFEP90xpdEhTiRxqUM5SYYA22lq5wlNEw6JH8AYUdAVb8SR1a7h/R5NcF7ghvo@DY0wkKcmOhDEJJQlLEu5Iis9hSqRMQ1LuUknwW5Iy3ckjLkF3h3FGiFSNP/q9jawrpIoMiILxCJRnRzvg34c34NmimEWXqoaTxkjlGJajAnowP8pyV/4F "Python 3 – Try It Online")
It's... beautiful.
Uses an `i`-dominated internal representation. Basically, the number of `j` and `k` characters is decreasing. The last two rules allow the movement of `j` and `k` between `i`s.
Due to the rule `=1`, this is a bit slow. If you want to test this answer, I suggest you use [This](https://tio.run/##lVXBjpswEL37KyxOdhNo0d6QUE@7p0rbQ9VLQisHJokJ2Mg2u4128@3pGEJC2E21RYrCzDw/zzw/J83ebbW6O8q60cZRA3Nq95YYiGmKUZTrupEVMLMKGFv8SrPX5TLlnzhLx9HXgBNSwJq2CmwuGmCSJ4TiY8Ah0SoIugiLGH3p3tfa0JxKRWWP9I9cdxChCiylft1yGVzKJ8LZqXCVH1N3cfWWLL3Blf4/lbrVlvoY12S1kBboT1G1cG@MNmwdfBfGgqHgw4RutKP5VhiRO0y@5Acq1v4NVeDX3Ld06xuJR2AL746wd2DZIs963mm3H@r0/vHb5/vHh2mPuEFrlP8ivVsav/JsFcTWUgmnjcVOLTh2WtZWcJ2ppOoyMrJNJR3rZOdnV1XeVR3m0nfd2TmOauHyLav42HJ1tDG6bdgdnwjiN35N6Qs723qAxpzP6ZvsHV/EScb54R8qj6b01O8xH8ZqjfDzvqNeO/gDeeuA5XM6FnAA4bi9unk/aqvkE2CM@RfZb1DrAqMfpoUufN7iPffJkWgd4kHgEOecguffI7LLoQzqW6/@gLieHbXuql2jyWlA@9HVvizmKw/oRryuDgjd1YXaAKtAMctnMX@LHLpZ6ETPPE7wzF8c8T50Org/ObtIdDZbzZDjxJBkh5urJ2JPjmTMTW5dM6M3RtTDPVMaHdJUIocalLNUGKCNtlau8BTRsOgRvAEFXcFWPEndGu5/o0muC9wQf4@DI5GkJDsSklCSsCQhvoYpkTINSblLJcFPScp0J4@IRmOHcUaIVI0/9b2NrCukigyIgvEIlCdGJ@A/h/fe2Z2YRYOqhpPGSOUYlqMCejA/SrnzT1n@BQ "Python 3 – Try It Online") equivalent program.
[Answer]
# [Lexurgy](https://www.lexurgy.com/sc), 108 bytes
```
a propagate:
``=>*
{ii,jj,kk,ij,jk,ki,ji,kj,ik}=>{`,`,`,k,i,j,`k,`i,`j}
[]$1 `=>` $1
b:
*=>\1/{$,`} _ $
`=>\-
```
Explanation:
```
# while the input changed last iteration...
a propagate:
# cancel out negatives
``=>*
# ijk conversion
{ii,jj,kk,ij,jk,ki,ji,kj,ik}=>{`,`,`,k,i,j,`k,`i,`j}
# move negative signs to the front
[]$1 `=>` $1 
# cleanup
b: 
# put in 1s on empty string or leading `
*=>\1/{$,`} _ $
# ` to minus
`=>\-
```
[Answer]
# [J](http://jsoftware.com/), 41 bytes
```
'1ijk -'&([({~4&|,~4+3&<)(8|]+[*3^])/@i.)
```
[Try it online!](https://tio.run/##bY@xCsIwEIZ3n@JwyDW2iZZ2kKIgCE5OrqUuYvHuBh/A0lePqdrrYI/8GT7y/Uc4LD22sK8AIYMNVDHOw/FyPgXMiQUcmqROXn1puqwv08LsbLLtmrReFdfGrg/kbbCL@@3xjBWE4CpoAQlHxCNiRTIi@Uekz5wy1jaXq6qu48mVmSVEMgzPFAsJf6LW1M9DG8nvnvlO9IZ8TxwMbw "J – Try It Online")
[Neil's excellent idea](https://codegolf.stackexchange.com/a/226315/15469) applied to J.
[Answer]
# [Python 3](https://docs.python.org/3/), 289 bytes
```
R={"ii":"-","jj":"-","kk":"-","ij":"k","jk":"i","ki":"j","ji":"-k","kj":"-i","ik":"-j"}
def f(x):
    if x=="-":return"-1"
    if len(x)==1:return x
    if len(x)==2and x[0]=="-":return x
    for s,e in R.items():x=x.replace(s,e)
    return f(("-"if x.count("-")%2else"")+"".join(c for c in x if c!="-"))
```
[Try it online!](https://tio.run/##VY7LCsIwEEXX9ivGASHBWnzsCvkJt@KixAlOWtPSVoiI314zpQvdTe65Zybda7y34TRNZ/NGZixxhzl6vwx1vQwsSS1IEhYkZS/JbAmrZ00gz57HT3YjB05FXWYrdhCNSevKnsZnH3B3wDltKKSGMYcFQPyLj1W4Qbzsr7@ydFzbw5ATcIBzwSM9BqXLaGLRU9dUllSCOlstglMq6fKJwrbPMMpLb47UDISot4iFbzkoC7LWytIIqW3XclXrafoC) Takes input as a string.
[Answer]
# [Python 3](https://docs.python.org/3/), 132 bytes
Function that iterates over the characters of the expression, evaluating step by step the product of a pair of characters.
```
def f(e,s=0):
 while e[1:]:p,e=e[:2],e[2:];a=set('ijk')-set(p);e=a.pop()[len(a):]+e;s^=p not in'ijki'
 return'-'[:s]+['1',e][len(e)]
```
[Try it online!](https://tio.run/##LU/LCsMgELz7Fd5WqS1NezP4JWIh0A1ZLUaipfTrU7UZ1mEdZl/pW5Y13vf9iTOfBapsrlIz/lnohRztoJ1OCg1afXMK7U27cTIZiwDyAeS5pUmOaKZLWpOQ9oVRTFK7E475YRKPa@EUm5uA8Q3Le4twBquzO1kYQKHrNSjdXjAXY4FAMfCNQiPqqe9qOJTQNaLQ4P9eCr6//vHNQ@Hgf4NqpHBEBTjG5nXjVPfjbXS9uyJtFIuYBUm5/wA "Python 3 – Try It Online")
---
*Code explanation:*
* `def f(e, s=0):`  
function definition: takes the expression to be evaluated as input `e`; the 2nd parameter `s` is the sign, passed as optional parameter to be initialized (0 => +, 1 => -).
* `while e[1:]:`  
main loop: iterates over the characters in the expression, while there are at least 2 characters left (the empty string evaluates to False).
* `p, e = e[:2], e[2:];`  
take the first two characters `p` (to evaluate their product), and the remaining part of the expression.
* `a = set('ijk') - set(p);`  
evaluates the set `a` as difference between the set of 3 chars {i, j, k} and the set of 2 chars in `p`. This can be used to distinguish the different cases: if `p` is a mixed product (ij, jk, ...) then the difference set will contain the char resulting from their product; otherwise, the difference set will have `len==2`.
* `e = a.pop()[len(a):] + e;`  
prepend to the remaining expression the char resulting from the product. This exploits the set `a` built before: `pop()` will return the correct char only if we have a mixed product: the difference set will contain only the resulting char. It is taken by slicing the single char string with `len`: actually `len=0` accounts for the fact that `a.pop` is evaluated before `len`.
* `s ^= p not in 'ijki'`  
evaluates the sign: the product will have negative sign for {ii, jj, kk} and {ji, kj, ik}, all of them are not contained in the string `'ijki'`. The boolean evaluates to integer to compute the xor function: sign xor (1, 0) follows the sign multiplication rules.
* `return '-'[:s] + ['1', e][len(e)]`  
finally, the function returns the results of the expression: first the sign `-` only if `s==1`. Then the results of the expression: `e` if it contains the remaining single char (exit from loop), otherwise `1`.
[Answer]
# x86-64 machine code, 36 bytes
```
30 C1 74 06 28 C8 04 02 7B 05 35 31 C9 31 C0 AC 24 03 75 EC 9E 79 03 B0 2D AA 8D 41 31 E3 02 04 37 66 AB C3
```
[Try it online!](https://tio.run/##dVNNj5swED0zv2JKFclsslGa9ENKml7aay89Vcrm4BiTGIxBmOwSovz10rGBtFupCEaeN483z4MRZfl4FKLruM2R4Y@QwfyoiwPXmEB@1rUq9WUNQVNUKPQMuYYgbTHRqrTqaCCw5wOBMypCwOPYr5fEKQs0sqlhZJLG/HCpJS6a1QdIBkkpmpkLQ8ZdxhtwbxJDF7E9kKzpZVcka1ocXVFvfkocZtFmqsyVOVsI8uLZsxfN8htR6oIk7mUnKnnfaFeJZkpu3u1Jg9YtFkY65p@NUPUTDOi6F3uBoJI1tOsAohCjDZBVWRkMv4Z4fS5UjAkTJ17hQyUtOaXJFMbW2GM22qAnjZtgI9DS6gbwVhmhz7HEz7aOVTE/fQH4W6CWthbcSrvb4xavoQpnGKYuZC4ov0w9mg1I5jGlMnelPVdlqX98kjqOyobYCxBRZcNNV3jbgDI15lwZFsEVgoS@F3vlDNd4dxdBQJzAV/o57Fb7DSEJG8dSRy4vK5JNWDixOLFPhpq/qt/gzngy37k4KSNpoLFch67sLDU0h8UML5TGBV5HOk4Wy58kd9kydjbuBMrYO32IxtlHu2Y63dPY8eWktMT/EnFKXd5s8d966zzcG7KJQnfCbeT30VDx1nW/RKL50XaP@cf3FOg32xJf6t8 "C++ (gcc) – Try It Online")
Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes in RDI an address at which to place the result, as a null-terminated byte string; and the address of the input, as a null-terminated byte string, in RSI. The starting point is after the first 11 bytes.
In assembly:
```
# ECX holds 0 for 1, 1 for i, 2 for j, or 3 for k.
# The high bit of AH holds a sign: 1 to negate or 0 to not negate.
multiply:       # Here, AL is 1, 2, or 3 for the current input letter (as above).
    xor cl, al  # Exclusive-or CL (the low byte of ECX) with that value.
                    # This produces the correct new value.
    jz flipsign # If the result is 0 (i*i, j*j, k*k), jump to flip the sign.
    sub al, cl  # Subtract CL from AL.
    add al, 2   # Add 2 to AL. The possibilities based on the original CL and AL are:
                #  0: j*i=-k
                #  1: k*i=j  i*j=k
                #  2: 1*i=i  1*j=j  1*k=k
                #  3: k*j=-i i*k=-j
                #  4: j*k=i
    jpo next    # Jump if the sum of the low 8 bits is odd, to skip the sign flipping.
                #  It is odd for 1, 2, and 4, so the sign is flipped for 0 and 3.
flipsign:
    .byte 0x35  # This byte combines with the next two instructions to form
                #  'xor eax, 0xC031C931', which in particular flips the high bit of AH.
f:
    xor ecx, ecx    # (Start here) Set ECX to 0.
    xor eax, eax    # Set EAX to 0.
next:
    lodsb           # Load a byte from the input string into AL, advancing the pointer.
    and al, 3       # AND that byte with 3, converting i,j,k to 1,2,3 respectively.
    jnz multiply    # Jump if the result is not 0. It is 0 for the null byte.
    sahf            # Set flags from AH. In particular, the high bit of AH goes into SF.
    jns skipminus   # Jump if SF=0 to skip the minus sign.
    mov al, 0x2D    # Set AL to the ASCII code of HYPHEN-MINUS.
    stosb           # Add that to the output string, advancing the pointer.
skipminus:
    lea eax, [rcx+0x31] # Set EAX to ECX+0x31. 0x31 is the ASCII code of 1.
    jrcxz oneskip       # Jump if ECX is 0.
    add al, 0x37        # (Otherwise) Add 0x37 to AL, for a net addition of 0x68,
                        #  which makes 1,2,3 into the ASCII codes of i,j,k respectively.
oneskip:
    stosw   # Add AL and AH (which is 0) to the output string, advancing the pointer.
    ret     # Return.
```
]