第12回オフラインリアルタイムどう書くの参考問題 Erlang による実装

http://qiita.com/Nabetani/items/1de39df381dfeee305ab
「道なりの亀」をErlangでやってみました。

とても制限時間内にはできません。
練習ということで…。

```erlang:turtle.erl
-module(turtle).
-export([start/1, tests/0, test/2]).

start(Data) -> move(Data, {1, 1, 2}, [$A]).

map() -> ["ABCDEFGHIJK", "LMNOPQRSTUV", "WXYZabcdefg",
          "", "jmpsvy147", "ilorux036", "hknqtwz25"].

dir() -> [{0, -1}, {1, 0}, {0, 1}, {-1, 0}].

move([],     _,   L) -> lists:reverse(L);
move([$L|T], Pos, L) -> move(T, left(Pos), L);
move([$R|T], Pos, L) -> move(T, right(Pos), L);
move([F|T],  Pos, L) ->
  case forward(list_to_integer([F], 16), Pos, L) of
    {false, NPos, NL} -> move([], NPos, NL);
    {true,  NPos, NL} -> move(T, NPos, NL)
  end.

forward(0, Pos, L) -> {true, Pos, L};
forward(Count, {X, Y, D}, L) ->
  {DX, DY} = lists:nth(D, dir()),
  case check(X + DX, Y + DY, D) of
    {false, _, _, _}   -> {false, 0, [$?|L]};
    {true, NX, NY, ND} ->
      Chr = lists:nth(NX, lists:nth(NY, map())),
      forward(Count - 1, {NX, NY, ND}, [Chr|L])
  end.

% turn left.
left({X, Y, 1}) -> {X, Y, 4};
left({X, Y, D}) -> {X, Y, D - 1}.

% turn right.
right({X, Y, 4}) -> {X, Y, 1};
right({X, Y, D}) -> {X, Y, D + 1}.

% jump WXY -> hij.
check(X, 4, 3)  when X =< 3 -> {true, 1, 8 - X, 2};

% jump efg -> 765.
check(X, 4, 3)  when X >= 9 -> {true, 9, X - 4, 4};

% jump hij -> WXY.
check(0, Y, _) when Y >= 5  -> {true, 8 - Y, 3, 1};

% jump 765 -> efg.
check(10, Y, _) when Y >= 5 -> {true, Y + 4, 3, 1};

% out of map.
check(X, Y, D) when X < 1          -> {false, X, Y, D};
check(X, Y, D) when X > 11, Y =< 3 -> {false, X, Y, D};
check(X, Y, D) when X > 9,  Y >= 5 -> {false, X, Y, D};
check(X, Y, D) when Y == 0; Y == 4; Y == 8 -> {false, X, Y, D};

% on map.
check(X, Y, D) -> {true, X, Y, D}.

tests() ->
  test("2RcL3LL22", "ABCNYjmpsvy147edcbcdef"),
  test("L3R4L5RR5R3L5", "A?"),
  test("2ReLLe", "ABCNYjmpsvy147eTITe741yvspmjYNC"),
  test("1ReRRe", "ABMXilorux036fUJUf630xuroliXMB"),
  test("ReRRe", "ALWhknqtwz25gVKVg52zwtqnkhWLA"),
  test("f", "ABCDEFGHIJK?"),
  test("Rf", "ALWhknqtwz25gVK?"),
  test("1Rf", "ABMXilorux036fUJ?"),
  test("2Rf", "ABCNYjmpsvy147eTI?"),
  test("aR1RaL1LaR1R2L1L2", "ABCDEFGHIJKVUTSRQPONMLWXYZabcdefg567432"),
  test("2R1R2L1L2R1R2L1L2R1R2L1L2R1R2L1L2", "ABCNMLWXYjihklmponqrsvutwxy"),
  test("2R4R2L4L2R4R2L4L2R4R2L4L2", "ABCNYjmlknqtwxy147efgVK?"),
  test("R1L2R4R2L4L2R4R2L4L2R4R2L4L2", "ALMNYjmponqtwz0147eTUVK?"),
  test("R2L2R4R2L4L2R4R2L4L2R4R2L4L2", "ALWXYjmpsrqtwz2347eTIJK?"),
  test("R3L2R4R2L4L2R4R2L4L2R4R2L4L2", "ALWhijmpsvutwz2567eTI?"),
  test("R5L2L5L1LaR1L4L5", "ALWhknopmjYNCBMXilorux0325gVKJIHGF"),
  test("1R2L4L2R4R2L4L2R4", "ABMXYZabQFGHIJUfg?"),
  test("2R2L4L2R4R2L4L2R4", "ABCNYZabcRGHIJKVg?"),
  test("3R2L4L2R4R2L4L2R4", "ABCDOZabcdSHIJK?"),
  test("4R2L4L2R4R2L4L2R4", "ABCDEPabcdeTIJK?"),
  test("5R2L4L2R4R2L4L2R4", "ABCDEFQbcdefUJK?"),
  test("LLL1RRR1LLL1RRR2R1", "ALMXYZ?"),
  test("R3RRR3", "ALWhij?"),
  test("1LLL4RRR1LR1RL1", "ABMXilm?"),
  test("R2L1R2L1R3R4", "ALWXilmpsvut?"),
  test("7R4f47LLLc6R9L", "ABCDEFGHSd?"),
  test("5RR868L8448LL4R6", "ABCDEFEDCBA?"),
  test("42Rd1RLLa7L5", "ABCDEFGRc?"),
  test("RRLL6RLR1L5d12LaLRRL529L", "ABCDEFGRSTUV?"),
  test("RLR7L6LL1LRRRcRL52R", "ALWhknqtuv?"),
  test("1RLR8RLR1R437L99636R", "ABMXiloruxwtqnkhWLA?"),
  test("LLL2L3La9Le5LRR", "ALWXYZOD?"),
  test("R1LcRR491", "ALMNOPQRSTUV?"),
  test("R8L1R1R512L8RLLReRf", "ALWhknqtwx0z?"),
  test("1RcL8f1L29a5", "ABMXilorux036fedcbaZYXW?"),
  test("R822LeL46LL39LL", "ALWhknqtwz25gfedcbaZYXW?"),
  test("9R3L5LRRLb5R3L7cLLLR4L", "ABCDEFGHIJUf65?"),
  test("7LLRRR2R3R69Lf76eR2L", "ABCDEFGHSdcbaPE?"),
  test("8RRRLL3Le", "ABCDEFGHITe765?"),
  test("8R5RLL6LbL4LL5bL", "ABCDEFGHITe7410z?"),
  test("6LR2R1LR5LRLRL484L63", "ABCDEFGHITe741yxw?").

test(Data, Expected) ->
  io:fwrite("~s -> ~s, ~p~n", [Data, Expected, start(Data) =:= Expected]).
```