JavaScript (ES6), 140 bytes
a=>a.map(p=n=>(g=([m,o],...q)=>(p=m&255)-n.charCodeAt()?g[p]?g(...q):g(...q,g[p]=[p+1,o+'+'],[p-1,o+'-'],[p*p,o+'s']):o+'o')([p,''])).join``
Try it online!
Input array of characters, output a string.
Remove the g[p]?g(...q):
would work in theory but actually result stack overflow. :(
a=> // input (as array of characters)
a.map(
p= // p&255 is the value of cell, initial to 0
n=> // for each character `n`
(g= // a recursive function apply bfs for shortest code output `n`
// g is assigned each iteration, so g[p] (discussed later) is cleared
([m, // current value got
o], // code for current value
...q // queue for bfs
)=>
(p= // let `p` memorize code of previous char
m&255) // bit-wise and 255 for mod 256, works for negative numbers
-n.charCodeAt()? // the value got equals to current char?
// not equal
g[p]? // value `p` had been searched before
g(...q): // don't search it again
g(...q, // bfs with following items enqueue
g[p]= // assign g[p] to something thuthy so we won't search it again
[p+1,o+'+'], // +
[p-1,o+'-'], // -
[p*p,o+'s']): // s
o+'o' // output this char
)([p,'']) // search starts from empty code output previous value
).join`` // join codes for each char
Python 3.9, 137 bytes
p=0
for n in input():
q=[[p,'']]
for p,o in q:
if chr(p:=p%256)==n:print(end=o+'o');break
q[:]+=[p+1,o+'+'],[p-1,o+'-'],[p*p,o+'s']
Try it online!
The TIO link is 139 bytes by changing the last line q[:]
into q[-1:]
. The code still works without the -1
there on my computer, it only takes much longer time (timeout on TIO). And I don't know why -1
may help the performance.
It is shorter than the mojibake like JavaScript