Rotor Routers on a Grid

10

1

Input

Your input is a single string, separated by newlines into 2n+1 lines of length 2n+1, for some integer n ≥ 0. The integer n is not part of the input; you'll have to compute it from the string. The lines are composed of the "direction characters" >^<v. If newlines pose a problem, you can replace them by vertical pipes |.

The input forms a square grid of size (2n+1)x(2n+1), and each cell of the grid is interpreted as a rotor router, which points in one of the four cardinal directions. We proceed to drop a token on the router at the center of the grid, and then the routers will move it around in the following way. When the token lands on a router, the router turns 90 degrees in the counter-clockwise direction, and moves the token one step in the new direction it points to. If it lands on another router, the process is repeated, but eventually, the token will fall off the grid.

Output

Your output is the final configuration of the routers, in the same format as the input.

Example

As an example input, consider the 3x3 grid

<^<
^><
>^v

where the central router has been highlighted to indicate the token (it's a bit hard to see). The central router rotates to face north, and moves the token to the central cell of the top row:

<^<
^^<
>^v

This router rotates to face west, and sends the token to the top left corner:

<<<
^^<
>^v

The router in the corner sends the token south, so it's now at the leftmost cell of the middle row:

v<<
^^<
>^v

That router rotates to face west and sends the token off the grid.

v<<
<^<
>^v

This is the final grid configuration, so your program should output it. Note that in more complex examples, the token can pass the same router multiple times before falling off the grid.

Rules

You can write either a function or a full program. This is code-golf, so the lowest byte count wins. Standard loopholes are disallowed. You can decide whether there is a trailing newline in the input and/or output.

Test Cases

Input:
v
Output:
>

Input:
<^<
^><
>^v
Output:
v<<
<^<
>^v

Input:
>>^>>
v<vv<
>^>^<
^<>>^
vvv>>
Output:
>>^>>
>v>>v
^>>vv
^^>>>
v^<<^

Input:
<^^^^^^^^
<<^^^^^^>
<<<^^^^>>
<<<<^^>>>
<<<<^>>>>
<<<vv>>>>
<<vvvv>>>
<vvvvvv>>
vvvvvvvv>
Output:
>>>>>>>>v
^>>>>>>vv
^^>>>>vvv
^^^>>vvvv
<<<<<vvvv
^^^^<<vvv
^^^<<<<vv
^^<<<<<<v
^<<<<<<<<

Zgarb

Posted 2015-02-13T13:21:15.200

Reputation: 39 083

Should the two instances of "rotates to the east" say "rotates to face west"? – Peter Taylor – 2015-02-13T14:03:12.347

@PeterTaylor Good catch. I always seem to confuse the two. – Zgarb – 2015-02-13T14:04:04.943

Is the input string terminated with a newline? – edc65 – 2015-02-13T15:54:22.153

@edc65 You can decide that yourself, also for the output. There are no preceding newlines, though. – Zgarb – 2015-02-13T15:55:56.403

Answers

3

CJam, 62 61 63 bytes

Try it online

Nq_N#):D;+_,2/{:P"^<v>^

"_P4$=#:X)=t_,0PX[1DW*WDSP]=-e>e<}h;1>

Expanded and commented:

Nq              "Read the input grid";
_N#):D;         "Calculate the vertical delta (line length + 1)";
+               "Prepend a newline to the grid";
_,2/            "Calculate the initial position as the length of the grid
                 string divided by 2";
{               "Do...";
  :P"^<v>^

"
  _P4$=           "Get the character indexed by the position in the grid";
  #:X             "Map the character to an operation number:
                   '^'=>0, '<'=>1, 'v'=>2, '>'=>3, '^'=>4, '\n'=>5, '\n'=>6
                   (the unreachable duplicate mappings are important below)";
  )=t             "Set the character indexed by the position in the grid to
                   the result of mapping the operation number + 1 backwards";
  _,0PX[1DW*WDSP]="Map the operation number to a negated delta (this occurs
                   after rotating routers, which means that operation n should
                   act like the character corresponding to operation n + 1):
                   0=>1, 1=>-delta, 2=>-1, 3=>delta, 5=>position";
  -e>e<           "Subtract the negated delta from the position and clamp it to
                   [0, length of the grid string] (array indices are circular,
                   so the length of the grid string will act like the index 0
                   and point to the initial newline next iteration, which will
                   *really* set the position to 0)";
}h              "... while the position is not 0 (i.e. not at the initial
                 newline)";
;1>             "Clean up and remove the initial newline";

My solution operates on the input as a flat string, so there's only one position value to keep track of and virtually no pre/postprocessing; there are only 2 bytes of preprocessing to add newline to the beginning of the grid and 2 bytes of postprocessing to remove it from the output. But these 4 bytes are well worth the cost as they let me keep newlines in and "execute" them like routers, but they "rotate" into another newline and set the position to zero. And the main loop ends when the position becomes zero.

Runer112

Posted 2015-02-13T13:21:15.200

Reputation: 3 636

I'll rule that the preceding newline unfortunately has to go; only trailing ones are permitted. – Zgarb – 2015-02-13T15:53:41.180

@Zgarb Fixed, +2 bytes. – Runer112 – 2015-02-13T16:13:07.573

It seems that the output from your link is not correct – aditsu quit because SE is EVIL – 2015-02-13T20:30:21.227

@aditsu You are indeed correct. I'm not sure what I touched, I swear it used to work fine. I'll look into it. – Runer112 – 2015-02-13T20:33:30.967

@aditsu Turns out subtraction isn't commutative. Thanks for pointing out that it was broken, that was easy enough to fix. But now one of the comments touches the code. :( – Runer112 – 2015-02-13T20:41:53.833

2

CJam, 90 69 bytes

q_,mqi):L_*Lm2/(:X;{_X_@="^<v>"_@#_[WL1LW*]=X+:X;)=tX)L%XW>XLL(*<**}g

Huge for now, Can still be reduced a lot.

Try it online here

Optimizer

Posted 2015-02-13T13:21:15.200

Reputation: 25 836

1Curses, foiled again! I was just about to post by 70 byte CJam solution, but it looks like that'll need some rethinking now. – Runer112 – 2015-02-13T15:19:27.103

1

JavaScript (ES6) 121 120 127 129

A named function that gets the string as an input parameter and returns the output.
Assuming the input string is terminated with a newline.

Edit bug fix, .search() does not work well with undefined

F=s=>(o=~s.search('\n'),s=[...s],
R=p=>~(u='^<v>'.indexOf(s[p]))?R(p+[-1,-o,1,o][u],s[p]='<v>^'[u]):s)(-~o*o/2-1)
.join('')

Ungolfed and explained

F=s=>{
  o = s.search('\n')+1; // offset to next row
  s = [...s]; // string to array
  R=p=>{ // recursive search functiom, parameter p is current position in grid
    u = '^<v>'.indexOf(s[p]); // find direction
    if (u<0) return s; // if no direction found, out of grid -> stop recursion
    s[p] = '<v>^'[u] // set new direction into the array cell 
    return R(p+[-1,o,1,-o][u]) // call recursive function with new position
  }
  return R((o-1)*o/2-1) // start recursive search with initial position at grid center
  .join('') // array to string
}

Test In Firefox/FireBug console

s='<^^^^^^^^\n\
<<^^^^^^>\n\
<<<^^^^>>\n\
<<<<^^>>>\n\
<<<<^>>>>\n\
<<<vv>>>>\n\
<<vvvv>>>\n\
<vvvvvv>>\n\
vvvvvvvv>\n'
console.log(F(s))

Output

>>>>>>>>v
^>>>>>>vv
^^>>>>vvv
^^^>>vvvv
<<<<<vvvv
^^^^<<vvv
^^^<<<<vv
^^<<<<<<v
^<<<<<<<<

edc65

Posted 2015-02-13T13:21:15.200

Reputation: 31 086