Prolog で FizzBuzz

Prolog でやってみた.

fizzbuzz(N, L) :-
	fizzbuzz(N, L, []).

fizzbuzz(0, L, L).
fizzbuzz(N, L, D) :-
	sub(N, V),
	N1 is N - 1,
	fizzbuzz(N1, L, [V | D]).

sub(N, 'FizzBuzz') :-
	N mod 15 =:= 0.
sub(N, 'Fizz') :-
	N mod 3 =:= 0.
sub(N, 'Buzz') :-
	N mod 5 =:= 0.
sub(N, N).

もっと簡潔に書けるのかもしれないけど,本職じゃないからこんなもんで.
大森さんとこの Scheme と比べると,Prolog の方が普通の言語に見えるような.(^^;
そんなことない?


ともあれ (JW),実行結果.

2 ?- fizzbuzz(100, L).

L = [1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 
11, 'Fizz', 13, 14, 'FizzBuzz', 16, 17, 'Fizz', 19, 'Buzz', 
'Fizz', 22, 23, 'Fizz', 'Buzz', 26, 'Fizz', 28, 29, 'FizzBuzz', 
31, 32, 'Fizz', 34, 'Buzz', 'Fizz', 37, 38, 'Fizz', 'Buzz', 
41, 'Fizz', 43, 44, 'FizzBuzz', 46, 47, 'Fizz', 49, 'Buzz', 
'Fizz', 52, 53, 'Fizz', 'Buzz', 56, 'Fizz', 58, 59, 'FizzBuzz', 
61, 62, 'Fizz', 64, 'Buzz', 'Fizz', 67, 68, 'Fizz', 'Buzz', 
71, 'Fizz', 73, 74, 'FizzBuzz', 76, 77, 'Fizz', 79, 'Buzz', 
'Fizz', 82, 83, 'Fizz', 'Buzz', 86, 'Fizz', 88, 89, 'FizzBuzz', 
91, 92, 'Fizz', 94, 'Buzz', 'Fizz', 97, 98, 'Fizz', 'Buzz'] 

Yes


ちなみに,世間では Erlang とか並行処理への関心が高まっている様子.
でもでも,並行処理と言ったら我が国が 10 年以上の歳月と 500 億円以上の予算を投じた国家プロジェクト,「第五世代コンピュータ」の出番ですよ?
そのプロジェクトで生み出された並行論理プログラミング言語GHC あるいは KL1 がもっと話題になってもいいのではなかろうか?
あ,GHC ってのは Guarded Horn Clauses の頭文字に由来する並行論理プログラミング言語の名前であって,どこぞのコンパイラの名前じゃありませんよっ.
もちろん,ノアの至宝でもありません>かっくん
その GHC をベースにした言語が KL1.


ちなみに,上記の Prolog プログラムを GHC あるいは KL1 で書き換えるとこんな感じじゃないかなぁ.

fizzbuzz(N, L) :- true |
	fizzbuzz(N, L, []).

fizzbuzz(N, L, D) :- N =:= 0 |
	L = D.
fizzbuzz(N, L, D) :- N > 0 |
	sub(N, V),
	N1 is N - 1,
	fizzbuzz(N1, L, [V | D]).

sub(N, V) :- N mod 15 =:= 0 |
	V = 'FizzBuzz'
sub(N, V) :- N mod 3 =:= 0, N mod 5 =\= 0 |
	V = 'Fizz'
sub(N, V) :- N mod 5 =:= 0, N mod 3 =\= 0 |
	V = 'Buzz'.
sub(N, V) :- N mod 3 =\= 0, N mod 5 =\= 0 |
	V = N.

ちょっと煩雑になった感はあるけれど,意外と逐次版と違ってないのがいいですよねっ (久々に直ちん風).
KL1 だとガード条件が true の場合は省略するのが慣習ぽいけど GHC でも省略できるのかは知らない.
本当はもっとストリーム (パイプライン) を活用するようなコードにした方がそれっぽいんだろうけど,それは置いておくテスト.


もし.
もしですよ?
もし,とある環境では剰余を求めるのに 10 秒かかるとしましょう.あり得ないけど.
もしそんな環境で上記の Prolog コードを実行したら...
えっと,えっと,100 までのリストを求めるのに,たぶん 2610 秒くらいかかるんじゃないかなぁ?


とっこっろっがっ!!
GHC/KL1 だったら...
20秒くらいで終わっちゃう可能性があるんじゃなかろうか.
CPU が 400 コくらいあれば (^^;
1 プロセッサあたり 8 コア × 4 スレッドで 32 スレッド同時実行可能な Ultra SPARC T1 搭載のサーバであっても,16 ソケット (トータル 512 スレッド)くらい必要ですね (笑).
32 ソケット (トータル 1024 スレッド) あれば 10 秒くらいで終わっちゃったりするのだろうか?
組み込み述語に限定されるガード部を並行に実行するかどうかは処理系次第なんだろうけど微妙かも.
ともあれ (JW),我が日本の並行言語はァァァァァァァァアアア世界一ィィィイイイイ