Brainf*ckish directions

Python 2.7 - 154 147 134 128 bytes

l=r=p=0
exec"exec raw_input('%s->','p+=r+1;r=0%s<-','p-=l+1;l=0%s>','r+=1;p+=1%s<','l+=1;p-=1;')"%((";').replace('",)*4)
print p

Serious changes have been made to the way this program works. I've removed the old explanation, which can still be found in this answer's edit history.

This one's gross.

It works pretty much the same way as other answers for this question, replacing the characters in the input with valid statements in that language and executing them. There's one major difference, though: replace is a long word. Screw that.

@ProgrammerDan in chat came up with the idea of using a tuple with the string ;').replace(' in it 4 times, to use the pre-str.format() method of formatting text. Four instances of %s are in the string on the second line, each one taking its value from the associated element of the tuple at the end. Since they're all the same, each %s is replaced with ;').replace('. When you perform the operations, you get this string:

exec raw_input(';').replace('->','p+=r+1;r=0;').replace('<-','p-=l+1;l=0;').replace('>','r+=1;p+=1;').replace('<','l+=1;p-=1;')

This is now valid python code that can be executed with exec. That's right, baby: Nested execs let me use string operations on code that needs to perform string operations on code. Someone please kill me.

The rest of it is pretty straightforward: Each command is replaced with code that keeps track of three variables: The current position, the number of rights since the last ->, and the same for lefts and <-. The whole thing is run and the position is printed.

You'll notice that I do raw_input(';'), using ';' as a prompt, rather than raw_input() which has no prompt. This saves characters in an unintuitive way: If I did raw_input(), I'd have to have the tuple filled with ).replace(', and every instance of %s would have ';\'' before it except the first one. Having a prompt creates more redundancy so I can save more characters overall.


GolfScript, 46 chars

'->'/')'*.'<-'-.')'/);+,\'>)'-.'<-'/);\'-'-+,-

This is one of the most linear GolfScript programs I've ever written — there's not a single loop, conditional or variable assignment in it. Everything is done using string manipulation:

  • First, I replace every occurrence of -> by ). Since the input is guaranteed to be valid, this ensures that any remaining occurrence of - must be a part of <-.

  • Next, I make two copies of the string. From the first copy, I remove the characters < and -, leaving only > and ). I then duplicate the result, remove all the )s and every > following the last ) from the second copy, concatenate them and count the characters. Thus, in effect, I'm counting:

    • +1 for each ),
    • +1 for each > after the last ), and
    • +2 for each > before the last ).
  • Next, I do the same for the other copy, except this time counting < and <- instead of > and ), and removing the -s before the final character count. Thus, I count:

    • +1 for each <-,
    • +1 for each < after the last <-, and
    • +2 for each < before the last <-.
  • Finally, I subtract the second count from the first one, and output the result.


Perl, 134 131 ... 99 95 bytes

sub f{$p+=$d;$&=~/-/?($p+=$s,$s=0):($s+=$d)}$_=<>;$d=1;s/-?>/f/eg;$s=0;$d=-1;s/<-?/f/eg;print$p

Takes input as a single line on stdin, eg:

ski@anito:~$ perl -le 'sub f{$p+=$d;$&=~/-/?($p+=$s,$s=0):($s+=$d)}$_=<>;$d=1;s/-?>/f/eg;$s=0;$d=-1;s/<-?/f/eg;print$p'
><->><-<-><-<>>->
4

or:

ski@anito:~$ echo "><->><-<-><-<>>->" | perl -le 'sub f{$p+=$d;$&=~/-/?($p+=$s,$s=0):($s+=$d)}$_=<>;$d=1;s/-?>/f/eg;$s=0;$d=-1;s/<-?/f/eg;print$p'
4

I split the instructions into the "right" operators (">" and "->") and "left" operators ("<" and "<-"). The advantages of this are that it's easier to exploit the parallelism between left and right operators, and we don't have to do anything fancy to tokenize the string. Each "direction" is dealt with as a substitution operation where we adjust the running total by the number of steps taken in that direction, ignoring the reverse direction which is taken care of by the other substitution operation. Here's a less-golfed ancestor of this code as a sort of documentation:

sub f {
  $dir=shift;
  if($1 =~ /-/) {
    $pos+=$side+$dir;
    $side=0;
  } else {
    $pos+=$dir;
    $side+=$dir;
  }
}

$_=<>;

s/(-?>)/f(1)/eg;
$side=0;
s/(<-?)/f(-1)/eg;

print $pos

In a prior iteration of this code, the substitutions were all done in one pass. This had the advantage of keeping a direct mapping between $p/$pos and the position that would be returned at any given point in time, but took more bytes of code.

If you want to use() 5.10.0, you can s/print/say/ to shave another 2 characters off the count, but that's not really my style.