「境界線分」をErlangで(横へな16)

「[境界線分](http://nabetani.sakura.ne.jp/hena/ord16boseg/)」をErlangでやってみました。他の実装は [第16回オフラインリアルタイムどう書くの問題](http://qiita.com/Nabetani/items/6a9f5593d0f3d7e0568c) から辿れます。

```erlang:boseg.erl
-module(boseg).
-compile(export_all).

solve(Data) ->
  string:join([integer_to_list(X) || X <- boundlen(oct2bin(Data))], ",").

oct2bin([]) -> [];
oct2bin([X, Y | T]) -> [string:right("00000" ++
  integer_to_list(list_to_integer([X, Y], 8), 2), 6) | oct2bin(T)].

boundlen(D) -> counts(difflen(D) ++ difflen(transpose(D, []))).

counts(D) -> [length(lists:filter(
  fun(A) -> A =:= X end, D)) || X <- lists:seq(1, 6)].

difflen(D) -> element(2, lists:foldl(fun(B, {A, Acc})
  -> {B, difflen(A, B, 0, Acc)} end, {hd(D), []}, tl(D))).
difflen([], _, N, Acc) -> [N | Acc];
difflen([A | Xs], [A | Ys], N, Acc) -> difflen(Xs, Ys, 0, [N | Acc]);
difflen([_ | Xs], [_ | Ys], N, Acc) -> difflen(Xs, Ys, N + 1, Acc).

transpose([[] | _], Acc) -> Acc;
transpose(D, Acc) ->
  transpose([tl(X) || X <- D], Acc ++ [[hd(X) || X <- D]]).

test(Data, Expected) -> test(Data, solve(Data), Expected).
test(Data, Result, Expected) -> io:fwrite("~s: ~s -> ~s~n",
  [case Result =:= Expected of true -> ok; false -> ng end,
    Data, Result]).

tests() ->
  test("060276724276", "6,2,1,1,0,1"), %0
  test("770175454177", "2,3,0,3,1,0"), %1
  test("743733377170", "9,3,1,0,0,0"), %2
  test("724212121273", "5,2,1,1,1,1"), %3
  test("100000000000", "3,0,0,0,0,0"), %4
  test("000002000000", "4,0,0,0,0,0"), %5
  test("003622223600", "0,4,0,4,0,0"), %6
  test("520073737070", "8,3,1,1,0,0"), %7
  test("770077007700", "0,0,0,0,0,5"), %8
  test("555555555514", "2,0,0,0,2,2"), %9
  test("764252427600", "4,0,4,0,2,0"), %10
  test("774555554177", "3,3,1,3,0,0"), %11
  test("674574754557", "11,5,0,1,0,0"), %12
  test("000000000000", "0,0,0,0,0,0"), %13
  test("777777777777", "0,0,0,0,0,0"), %14
  test("774377777577", "6,0,2,0,0,0"), %15
  test("070777777777", "0,1,1,0,0,0"), %16
  test("373737373737", "0,0,0,0,0,1"), %17
  test("603260327725", "30,0,0,0,0,0"), %18
  test("466331144663", "30,0,0,0,0,0"), %19
  test("000000000242", "3,2,0,0,0,0"), %20
  test("567656043772", "18,2,1,0,0,0"), %21
  test("200763012420", "15,4,1,0,0,0"), %22
  test("400101140052", "14,3,0,0,0,0"), %23
  test("764767476476", "13,2,0,1,0,0"), %24
  test("001110140110", "12,2,1,0,0,0"), %25
  test("765405076527", "16,3,0,1,0,0"), %26
  test("377323370373", "8,4,2,0,0,0"), %27
  test("250541131216", "11,5,2,0,0,0"), %28
  test("744165741476", "12,3,2,0,0,0"), %29
  test("042101000300", "10,3,0,0,0,0"), %30
  test("002004554101", "11,3,1,0,0,0"), %31
  test("371707762706", "15,1,1,0,0,0"), %32
  test("130371310175", "7,3,1,2,0,0"), %33
  test("212537003613", "13,2,1,1,1,0"), %34
  test("157700063411", "15,3,0,0,0,1"), %35
  test("011500036007", "6,7,1,0,0,0"), %36
  test("743113313517", "17,2,1,0,0,0"), %37
  test("174105270405", "13,3,1,1,0,0"), %38
  test("427272200311", "13,3,2,0,0,0"), %39
  test("725370332237", "12,5,1,1,0,0"), %40
  test("005640420046", "12,1,3,0,0,0"), %41
  test("700350001101", "14,3,1,0,0,0"), %42
  test("577627744076", "16,1,1,1,0,0"), %43
  test("620332232007", "10,4,2,1,0,0"), %44
  test("260406401000", "15,1,1,0,0,0"), %45
  test("737272723276", "5,0,0,0,3,0"), %46
  test("000400040444", "7,0,2,0,0,0"), %47
  test("370222002177", "13,2,2,0,0,0"), %48
  test("372236024656", "9,3,2,0,1,0"), %49
  test("276131137003", "11,6,2,0,0,0"), %50
  test("742134007240", "13,4,2,0,0,0"), %51
  test("777721775571", "13,1,2,0,0,0"), %52
  test("700301232233", "11,2,3,0,0,0"). %53
```

今回は「引数以外の変数は使わない」を心がけて作ってみました。計算結果を一時的に変数に格納 (バインド) する書き方は手続き型っぽいと思ったためです。おかげで以前より関数型っぽく書けた気がします。(コードがコンパクトになった分、難読化しているという話も…)

また、変数を使わないことで、関数の分け方を従来よりシステマチックに決めることができました。(同じ計算値を複数回使う場合には、その部分を関数に独立させ、値を引数として渡しています。)

リストで作った行列は扱いが面倒だと感じていますが、だいぶ慣れてきました。