「境界線分」をErlangでやってみました。他の実装は 第16回オフラインリアルタイムどう書くの問題 から辿れます。
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
今回は「引数以外の変数は使わない」を心がけて作ってみました。計算結果を一時的に変数に格納 (バインド) する書き方は手続き型っぽいと思ったためです。おかげで以前より関数型っぽく書けた気がします。(コードがコンパクトになった分、難読化しているという話も…)
また、変数を使わないことで、関数の分け方を従来よりシステマチックに決めることができました。(同じ計算値を複数回使う場合には、その部分を関数に独立させ、値を引数として渡しています。)
リストで作った行列は扱いが面倒だと感じていますが、だいぶ慣れてきました。