ErlangでN-Queens

を書いてみた。というか移植した。
N-QueensはチェスのQueen(縦・横・斜めに動ける)をお互いに取り合わないように盤面に置くパズル。本来の盤面は8x8ですが。
あまりに典型的なので、探せば絶対あると思うんだけど、まぁいいや、ということで。
Flengで昔使っていたのをベースにしました。

-module(qu).
-export([qu/1, go/1, count/1]).

go(N) -> timer:tc(qu,count,[qu(N)]).

count(C) -> count(C,0).
count([_H|T],Crnt) -> count(T,Crnt+1);
count([],Crnt) -> Crnt.

append([A|X],Y) -> [A|append(X,Y)];
append([],Y) -> Y.

qu(N) -> qu(generate(N), [],[]).

generate(N) ->
        if N > 0 -> [N|generate(N - 1)];
           N == 0 -> []
        end.

qu([P|Lu],Ls,Lp) -> 
        Lr = append(Lu,Ls),
        Ans1 = check(P,1,Lr,Lp,Lp),
        Ans2 = qu(Lu,[P|Ls],Lp),
        append(Ans1, Ans2);
qu([],[_|_],_) -> [];
qu([],[],Lp) -> [Lp].

check(P,D,L,[Q|Lp0],Lp) ->
        if (Q + D == P) or (Q - D == P) -> [];
           true -> D1 = D + 1, check(P,D1,L,Lp0,Lp)
	end;
check(P,_,L,[],Lp) -> qu(L,[],[P|Lp]).

# なぜ動くのかは聞かないで(^^;

1> c(qu).
{ok,qu}
2> qu:go(13).
{1122,73712}

サイズ13の時、置き方は73712種類あって、計算に11.22秒かかっています。

ちなみに、KL1移植版をKLICで実行すると、5〜6秒くらい。KLICはa.outになることを考えると、Erlangはそこそこ速いですね。KLICについてくるqueenの実装はもうちょっと速くて1台で4.5秒、pvmを使った2台で2.8秒、とかでした。

Erlang版を並列化するのは挫折 orz