Jumping and Running

Perl, 53 characters

s/-...(?=(-|-...)*-$)/J/g;y/-/R/;/_/?$_="!":s/.$//

Run this with perl -p jumpnrun.pl. I've counted 3 characters for the -p option, which is the length difference between perl jumpnrun.pl and perl -p jumpnrun.pl.

I'm not that fluent in Perl, so I'm pretty sure this can be shortened further. This uses a regexp similar to Howard's solution.


Ruby, 93 90 79 70 characters

I thought a regex solution would be quite fine and compact (let the matcher do the work). Unfortunately all the edge-cases and special treatments made this one such long - at least I didn't touch the 100 ;-).

puts gets.gsub(/-...(?=(-|-...)*-$)/,?J).tr(?-,?R)=~/^([JR]*)R$/?$1:?!

It passes all testcases of the provided script.

Saved several characters in comparison to the previous script (now a single call to gsub is sufficient).

Edit 1: Changed puts z!=?-??!:'' to z!=?-&&$><<?! after the test script allowed no output for test case 1.

Edit 2: The previous version was

z=gets.chop
z.chars{z.sub!(/^(-|-...)((-|-...)*-)$/){$><<($1==?-??R:?J);$2}}
z!=?-&&$><<?!

My original idea was to replace the characters by using a look-behind and look-ahead strategy like this: The pattern was ^(?<=[RJ]*)(-|-...)(?=(-|-...)*-$) and I then would replace '-' with 'R' and otherwise with 'J'. Unfortunately Ruby does not allow variable-length look-behind and another capturing group for the first part made the code even longer.

So then I did the iterative approach: if I can start with a step or jump ^(-|-...) followed by series of other steps or jumps until the last platform (-|-...)*-$ then I print the corresponding letter, remove the first one/four characters and start over again. On can even tune the RJ vs. JR priority by switching the choices inside the expression (currently it prefers RJ).

Edit 3: Splitting the single subtitution

puts (z=gets.chop.gsub(/(-...|-)(?=(-|-...)*-$)/){$1==?-??R:?J})=~/_/??!:z.chop

into two

puts (z=gets.chop.gsub(/-...(?=(-|-...)*-$)/,?J).tr(?-,?R))=~/_/??!:z.chop

gave another few chars. Finally I managed to get rid of this end-of-line issue but at a cost: the fail-detection costs some more characters.