このディレクトリの索引
%% 1.0 剰余算 を核とするFizzBuzz %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


fizzbuzz(N) :-
        between(1,N,M),
        fizzbuzz_2(M,S),
        writef('%w ',[S]),
        N = N.

fizzbuzz_2(N,'FizzBuzz') :-
        0 is N mod 3,
        0 is N mod 5,!.
fizzbuzz_2(N,'Fizz') :-
        0 is N mod 3,!.
fizzbuzz_2(N,N,'Buzz') :-
        0 is N mod 5,!.
fizzbuzz_2(N,N).

%% 1.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        between(1,N,M),
        fizzbuzz(M,X),
        writef('%w ',[X]),
        M = N.

fizzbuzz(N,'Fizz') :- 0 is N mod 3,\+(0 is N mod 3).
fizzbuzz(N,'Buzz') :- 0 is N mod 5,\+(0 is N mod 5).
fizzbuzz(N,'FizzBuzz') :- 0 is N mod 3,0 is N mod 5.
fizzbuzz(N,N) :- \+(0 is N mod 3),\+(0 is N mod 5).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(M) :-
'Nを1から生成しMになるまでFizzBuzzを表示する'(M),!.

'Nを1から生成しMになるまでFizzBuzzを表示する'(M) :-
'Nを1から生成し'(M,N),
'NがMになるまでFizzBuzzを表示する'(M,N).

'Nを1から生成し'(M,N) :-
between(1,M,N).

'NがMになるまでFizzBuzzを表示する'(M,N) :-
'FizzBuzzを'(N,FizzBuzz),
writef('%w ',[FizzBuzz]),
M = N.

'FizzBuzzを、'(N,FizzBuzz) :-
'Nが、3と5で割り切れたらfizzbuzzを、3で割り切れ5で割り切れなかったらfizzを、5で割り切れ3で割り切れなかったらbuzzを、3でも5でも割り切れなければNを返す。'(N,FizzBuzz).

'Nが、3と5で割り切れたらfizzbuzzを、3で割り切れ5で割り切れなかったらfizzを、5で割り切れ3で割り切れなかったらbuzzを、3でも5でも割り切れなければNを返す。'(N,fizzbuzz) :-
'Nが、3と5で割り切れたら'(N).
'Nが、3と5で割り切れたらfizzbuzzを、3で割り切れ5で割り切れなかったらfizzを、5で割り切れ3で割り切れなかったらbuzzを、3でも5でも割り切れなければNを返す。'(N,fizz) :-
'Nが、3で割り切れ5で割り切れなかったら'(N).
'Nが、3と5で割り切れたらfizzbuzzを、3で割り切れ5で割り切れなかったらfizzを、5で割り切れ3で割り切れなかったらbuzzを、3でも5でも割り切れなければNを返す。'(N,buzz) :-
'Nが、5で割り切れ3で割り切れなかったら'(N).
'Nが、3と5で割り切れたらfizzbuzzを、3で割り切れ5で割り切れなかったらfizzを、5で割り切れ3で割り切れなかったらbuzzを、3でも5でも割り切れなければNを返す。'(N,N) :-
'Nが、3でも5でも割り切れなかったら'(N).

'Nが、3と5で割り切れたら'(N) :-
0 is N mod 3,
0 is N mod 5.

'Nが、3で割り切れ5で割り切れなかったら'(fizz) :-
0 is N mod 3.

'Nが、5で割り切れ3で割り切れなかったら'(buzz) :-
0 is N mod 5.

'Nが、3でも5でも割り切れなかったら'(N) :-
\+(0 is N mod 3),
\+(0 is N mod 5).

%% 1.2 再帰 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(0) :- !.
fizzbuzz(N) :-
        fizzbuzz(N,X),
        N_1 is N - 1,
        fizzbuzz(N_1),
        writef('%w ',[X]).

fizzbuzz(M,'FizzBuzz') :-
        0 is M mod 15,!.
fizzbuzz(M,'Fizz') :-
        0 is M mod 3,!.
fizzbuzz(M,N,'Buzz') :-
        0 is M mod 5,!.
fizzbuzz(M,M).

%% 1.3 再帰 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% @viperlikeさんのツイートを見てそこで示されている形式の再帰がまだないことに気がついた。
% 

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

fizzbuzz(0,L,L) :- !.
fizzbuzz(N,L1,L) :-
        fizzbuzz(N,S),
        succ(N_1,N),
        fizzbuzz(N_1,[S|L1],L).

fizzbuzz(M,'FizzBuzz') :-
        0 is M mod 15,!.
fizzbuzz(M,'Fizz') :-
        0 is M mod 3,!.
fizzbuzz(M,N,'Buzz') :-
        0 is M mod 5,!.
fizzbuzz(M,M).

write_fizzbuzz(L) :-
        atomic_list_concat(L,' ',S),
        writef('%w\n',[S]).

%% 1.4 末尾再帰 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz(1,N).

fizzbuzz(M,N) :- M > N,!.
fizzbuzz(M,N) :-
        fizzbuzz_2(M,X),
        writef('%w ',[X]),
        M_2 is M + 1,
        fizzbuzz(M_2,N).

fizzbuzz_2(M,'FizzBuzz') :-
        0 is M mod 15,!.
fizzbuzz_2(M,'Fizz') :-
        0 is M mod 3,!.
fizzbuzz_2(M,N,'Buzz') :-
        0 is M mod 5,!.
fizzbuzz_2(M,M).

%% 1.5 forall/2とbetween/3を使用 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        forall((  between(1,N,M),
                  fizzbuzz_2(M,S),
                  writef('%w ',[S])),
               true).

fizzbuzz_2(M,'FizzBuzz') :-
        0 is M mod 15,!.
fizzbuzz_2(M,'Fizz') :-
        0 is M mod 3,!.
fizzbuzz_2(M,N,'Buzz') :-
        0 is M mod 5,!.
fizzbuzz_2(M,M).

%% 1.6  findsols/4とnth1/3を使用 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findnsols(N,_,(  
            nth1(M,_,_),
            fizzbuzz_2(M)),_),!.
            
fizzbuzz_2(M) :-
        fizzbuzz_3(M,S),
        writef('%w ',[S]),!.

fizzbuzz_3(M,'FizzBuzz') :-
        0 is M mod 15.
fizzbuzz_3(M,'Fizz') :-
        0 is M mod 3.
fizzbuzz_3(M,N,'Buzz') :-
        0 is M mod 5.
fizzbuzz_3(M,M).


%% 1.7 between/3とfindall/3を使用 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        between(1,N,M),
        fizzbuzz(M,[[1,M],[3,'Fizz'],[5,'Buzz']],L2),
        fizzbuzz_2(L2,S),
        writef('%w ',[S]),
        N = M.

fizzbuzz(M,L1,L2) :-
        findall(S,(
                    member([U,S],L1),
                    0 is M mod U),
                L2).

fizzbuzz_2([N],N).
fizzbuzz_2([_,A|L],S) :-
        atomic_list_concat([A|L],S).

%% 1.8 末尾再帰 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz(1,N).

fizzbuzz(M,N) :-
        M > N,!.
fizzbuzz(M,N) :-
        fizzbuzz表示(M),
        M_2 is M + 1,
        fizzbuzz(M_2,N).

fizzbuzz表示(M) :-
        fizzbuzz表示(M,_表示),
        writef('%w ',[_表示]).

fizzbuzz表示(M,'FizzBuzz') :-
        0 is M mod 3,
        0 is M mod 5,!.
fizzbuzz表示(M,'Fizz') :-
        0 is M mod 3,!.
fizzbuzz表示(M,'Buzz') :-
        0 is M mod 5,!.
fizzbuzz表示(M,M).

%% 1.9 剰余情報をリストに持つ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        between(1,N,_n),
        findall(A,(
                    member([_m,A],[[1,_n],[3,'Fizz'],[5,'Buzz']]),
                    0 is _n mod _m),
                L),
        fizzbuzz_2(L,S),
        writef('%w ',[S]),
        N = _n.

fizzbuzz_2([N],N).
fizzbuzz_2([_,A|L],S) :-
        atomic_list_concat([A|L],S).

%% 1.10 剰余情報をリストに持ち、findnsols/4とbetween/3で制御 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findnsols(N,_,(
                nth1(M,_,_),
                findall(S,(
                    member([U,S],[[1,M],[3,'Fizz'],[5,'Buzz']]),
                    0 is M mod U),L2),
        fizzbuzz_2(L2,S),
        writef('%w ',[S])),_),!.
 
fizzbuzz_2([N],N).
fizzbuzz_2([_,A|L],S) :-
        atomic_list_concat([A|L],S).

%% 1.11 末尾再帰  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :- 
        fizzbuzz(1,N).

fizzbuzz(N,Max) :- N > Max.
fizzbuzz(N,Max) :-
        fizzbuzz_2(N,C),
        nth0(C,[N,'Fizz','Buzz','FizzBuzz'],X),
        writef('%w ',[X]),
        N_2 is N + 1,
        fizzbuzz(N_2,Max).

fizzbuzz_2(N,C) :-
        0 is N mod 3 -> A=1;A=0.
        0 is N mod 5 -> B=1;B=0,
        C is A + 2 * B.

%% 2.0 FizzBuzzの変位をリストのパターンとして表現 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        fizzに置換する(L,L1),
        buzzに置換する(L1,L2),
        表示する(L2),!.

fizzに置換する([_1,_2,_3|R1],[_1,_2,fizz|R2]) :-
        fizzに置換する(R1,R2).
fizzに置換する(L,L).

buzzに置換する([_1,_2,_3,_4,fizz|R1],[_1,_2,_3,_4,fizzbuzz|R2]) :-
        buzzに置換する(R1,R2).
buzzに置換する([_1,_2,_3,_4,_5|R1],[_1,_2,_3,_4,buzz|R2]) :-
        buzzに置換する(R1,R2).
buzzに置換する(L,L).

表示する(L) :-
        atomic_list_concat(L,' ',_表示文字列),
        writef('%w\n',[_表示文字列]).

%% 2.1  リストのシフトで割り算を表現  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
fizzbuzz(N,_fizzbuzzならび),
fizzbuzzならびを表示する(_fizzbuzzならび),!.

fizzbuzz(N,L2) :-
最初に自然数ならびを作り(N,_自然数ならび),
fizzに置換する(_自然数ならび,L1),
buzzに置換する(L1,L2).

最初に自然数ならびを作り(N,_自然数ならび) :-
findall(M,between(1,N,M),_自然数ならび).

fizzに置換する([_1,_2,_3|R1],[_1,_2,fizz|R2]) :-
fizzに置換する(R1,R2).
fizzに置換する(L,L).

buzzに置換する(L1,L2) :-
fizzbuzzも考慮しつつbuzzに置換する(L1,L2).
buzzに置換する(L,L).

fizzbuzzも考慮しつつbuzzに置換する([_1,_2,_3,_4,fizz|R1],[_1,_2,_3,_4,fizzbuzz|R2]) :-
buzzに置換する(R1,R2).
fizzbuzzも考慮しつつbuzzに置換する([_1,_2,_3,_4,_5|R1],[_1,_2,_3,_4,buzz|R2]) :-
buzzに置換する(R1,R2).

fizzbuzzならびを表示する(_fizzbuzzならび) :-
atomic_list_concat(_fizzbuzzならび,' ',_表示文字列),
writef('%w\n',[_表示文字列]).

%% 2.2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        length(L0,N),
        fizzbuzz([_],[_|L0],[_,_,_],[_,_,_,_,_]).

fizzbuzz(Lm,Lm,_,_).
fizzbuzz(L0,Lm,L1,L2) :-
        fizzbuzz(L0,L1,L2,L3,L4,_正解),
        writef('%w ',[_正解]),
        fizzbuzz([_|L0],Lm,L3,L4).

fizzbuzz(_,[_],[_],[_,_,_],[_,_,_,_,_],'FizzBuzz').
fizzbuzz(_,[_],[_|L2],[_,_,_],L2,'Fizz').
fizzbuzz(_,[_|L1],[_],L1,[_,_,_,_,_],'Buzz').
fizzbuzz(L,[_|L1],[_|L2],L1,L2,N) :-
        length(L,N).

%% 2.3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        fizzbuzz([_],[_],L).

fizzbuzz(_,_,[]) :- !.
fizzbuzz([_,_,_],[_,_,_,_,_],[_|R]) :-
        fizzbuzz([],[],['FizzBuzz'|R]).
fizzbuzz([_,_,_],L2,[_|R]) :-
        fizzbuzz([],L2,['Fizz'|R]).
fizzbuzz(L1,[_,_,_,_,_],[_|R]) :-
        fizzbuzz(L1,[],['Buzz'|R]).
fizzbuzz(L1,L2,[A|R]) :-
        writef('%w ',[A]),
        fizzbuzz([_|L1],[_|L2],R).

%% 2.4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        fizzbuzz([_,_,_],[_,_,_,_,_],L).

fizzbuzz(_,_,[]) :- !.
fizzbuzz([],[],[_|R]) :-
        fizzbuzz([_,_,_],[_,_,_,_,_],['FizzBuzz'|R]).
fizzbuzz([],L2,[_|R]) :-
        fizzbuzz([_,_,_],L2,['Fizz'|R]).
fizzbuzz(L1,[],[_|R]) :-
        fizzbuzz(L1,[_,_,_,_,_],['Buzz'|R]).
fizzbuzz([_|L1],[_|L2],[A|R]) :-
        writef('%w ',[A]),
        fizzbuzz(L1,L2,R).

%% 2.5  リストのシフトで割り算 空文字を使いfizzbuzzを表示させない技法 %%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        forall(fizzbuzz(['','','Fizz'],['','','','','Buzz'],L),true).

fizzbuzz([A|R1],[B|R2],[N|R3]) :-
        fizzbuzz(A,B,N,C),
        writef('%w ',[C]).
fizzbuzz([A|R1],[B|R2],[_|R3]) :-
        append(R1,[A],L1),
        append(R2,[B],L2),
        fizzbuzz(L1,L2,R3).

fizzbuzz('','',N,N) :- !.
fizzbuzz(A,B,_,C) :-
        atom_concat(A,B,C).


%% 2.6 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        fizzbuzz(['','','Fizz'],['','','','','Buzz'],L).

fizzbuzz(_,_,[]).
fizzbuzz([A|R1],[B|R2],[N|R3]) :-
        fizzbuzz(A,B,N,C),
        writef('%w ',[C]),
        append(R1,[A],L1),
        append(R2,[B],L2),
        fizzbuzz(L1,L2,R3).

fizzbuzz('','',N,N) :- !.
fizzbuzz(A,B,_,C) :-
        atom_concat(A,B,C).

%% 2.7 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        forall(fizzbuzz(['','','Fizz'],['','','','','Buzz'],L),true).

fizzbuzz([A|R1],[B|R2],[N|R3]) :-
        fizzbuzz(A,B,N,C),
        writef('%w%w%w',[A,B,C]).
fizzbuzz([A|R1],[B|R2],[_|R3]) :-
        append(R1,[A],L1),
        append(R2,[B],L2),
        fizzbuzz(L1,L2,R3).

fizzbuzz('','',N,N).
fizzbuzz(A,B,_,' ').

%% 2.8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        forall(fizzbuzz(['','','Fizz'],['','','','','Buzz'],L),true).

fizzbuzz([A|R1],[B|R2],[N|R3]) :-
        fizzbuzz(A,B,N,C),
        writef('%w%w%w ',[A,B,C]).
fizzbuzz([A|R1],[B|R2],[_|R3]) :-
        append(R1,[A],L1),
        append(R2,[B],L2),
        fizzbuzz(L1,L2,R3).

fizzbuzz('','',N,N) :- !.
fizzbuzz(A,B,_,'').

%% 2.9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz([],N,['','','Fizz'],['','','','','Buzz']),!.

fizzbuzz(Ln,N,_,_) :-
        length(Ln,N).
fizzbuzz(Ln,N,L1,L2) :-
        fizzbuzz_1([_|Ln],L1,L2,S),
        writef('%w ',[S]),
        fizzbuzz_2(L1,L2,L1_2,L2_2),
        fizzbuzz([_|Ln],N,L1_2,L2_2).

fizzbuzz_1([_|Ln],[''|_],[''|_],N) :-
        length([_|Ln],N).
fizzbuzz_1(_,[A|_],[B|_],S) :-
        atomic_list_concat([A,B],S).

fizzbuzz_2([A|R1],[B|R2],L1_2,L2_2) :-
        append(R1,[A],L1_2),
        append(R2,[B],L2_2).

%% 2.10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz([_],['','','',fizz],['','','','',buzz],Lnx),
        length(Lnx,N).

fizzbuzz(Ln,[A|R1],[B|R2],Ln) :-
        表示(Ln,A,B).
fizzbuzz(Ln,[A|R1],[B|R2],Lnx) :-
        回転([A|R1],[B|R2],L1,L2),
        fizzbuzz([_|Ln],L1_2,L2_2,Lnx).

回転([A|R1],[B|R2],L1,L2) :-
        append(R1,[A],L1),
        append(R2,[B],L2).

表示(Ln,A,B) :-
        表示項(Ln,A,B,X),
        writef('%w '[X]).

表示項(Ln,'','',N) :-
        length(Ln,N),!.
表示項(_,A,B,C) :-
        atom_concat([A,B],C).

%% 2.11 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz([],N,['','','Fizz'],['','','','','Buzz']).

fizzbuzz(L,N,_,_) :-
        length(L,N),!.
fizzbuzz(Ln,N,[_31,_32,_33],[_51,_52,_53,_54,_55]) :-
        fizzbuzz_1(_31,_51,Ln,A),
        writef('%w%w%w ',[_31,_51,A]),
        fizzbuzz([_|Ln],N,[_32,_33,_31],[_52,_53,_54,_55,_51]).

fizzbuzz_1('','',Ln,M) :-
        length([_|Ln],M),!.
fizzbuzz_1(_,_,_,'').

%% 2.12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz([_],[_,_],[_,_,_,_],Ln,X),
        writef('%w',[X]),
        length(Ln,N),!.

fizzbuzz(L1,L2,L3,Ln,X) :-
        fizzbuzz_1(L1,L2,L3,L2_1,L3_1,Y),
        fizzbuzz_2(L1,L2_1,L3_1,Y,Ln,X).

fizzbuzz_2(L1,L2,L3,X,L1,X).
fizzbuzz_2(L1,L2,L3,_,Ln,X) :-
        fizzbuzz([_|L1],L2,L3,Ln,X).

fizzbuzz_1(R1,[],[],[_,_],[_,_,_,_],'FizzBuzz ').
fizzbuzz_1(R1,[],[_|R3],[_,_],R3,'Fizz ').
fizzbuzz_1(R1,[_|R2],[],R2,[_,_,_,_],'Buzz ').
fizzbuzz_1(R1,[_|R2],[_|R3],R2,R3,N) :-
        length(R1,N).

%% 2.13 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(Nth,X) :-
        fizzbuzz([_],[_,_],[_,_,_,_],Nth,X).

fizzbuzz(L1,L2,L3,Nth,X) :-
        length(L1,Nth_1),
        fizzbuzz_1(Nth_1,L2,L3,L2_1,L3_1,Y),
        fizzbuzz_2(L1,L2_1,L3_1,Nth_1,Nth,Y,X).

fizzbuzz_2(L1,L2,L3,Nth,Nth,X,X).
fizzbuzz_2(L1,L2,L3,_,Nth,_,X) :-
        fizzbuzz([_|L1],L2,L3,Nth,X).

fizzbuzz_1(_,[],[],[_,_],[_,_,_,_],'FizzBuzz').
fizzbuzz_1(_,[],[_|R3],[_,_],R3,'Fizz').
fizzbuzz_1(_,[_|R2],[],R2,[_,_,_,_],'Buzz').
fizzbuzz_1(N,[_|R2],[_|R3],R2,R3,N).

%% 2.14 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(M) :-
        fizzbuzz(M,[_],[_,_,_],[_,_,_,_,_]).

fizzbuzz(M,[_|L],_,_) :-
        length(L,M),!.
fizzbuzz(M,L,L1,L2) :-
        fizzbuzz(L,L1,L2,L_1,L1_1,L2_1,S),
        writef('%w ',[S]),
        fizzbuzz(M,L_1,L1_1,L2_1).

fizzbuzz(L,L,L,[_|L],[_,_,_|L],[_,_,_,_,_|L],fizzbuzz) :- !.
fizzbuzz(L,L,L2,[_|L],[_,_,_|L],L2,fizz) :- !.
fizzbuzz(L,L1,L,[_|L],L1,[_,_,_,_,_|L],buzz).
fizzbuzz(L,L1,L2,[_|L],L1,L2,N) :-
        length(L,N).

%% 2.15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  
%  PrologというのはFizzBuzz問題向きなのだろうか。
%  

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        fizzbuzz([_],[_],L).

fizzbuzz([_,_,_],[_,_,_,_,_],[_|R]) :-
        fizzbuzz([],[],['FizzBuzz'|R]).
fizzbuzz([_,_,_],L2,[_|R]) :-
        fizzbuzz([],L2,['Fizz'|R]).
fizzbuzz(L1,[_,_,_,_,_],[_|R]) :-
        fizzbuzz(L1,[],['Buzz'|R]).
fizzbuzz(L1,L2,[A|R]) :-
        writef('%w ',[A]),
        fizzbuzz([_|L1],[_|L2],R).
fizzbuzz(_,_,[]).

%% 2.16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizbuzz(1,N,['','','Fizz'],['','','','','Buzz']).

fizzbuzz(M,N,_,_) :-
        M > N,!.
fizzbuzz(M,N,[_31,_32,_33],[_51,_52,_53,_54,_55]) :-
        出力情報(_31,_51,M,_N),
        writef('%w%w%w ',[_31,_51,_N]),
        fizzbuzz(M,N,[_32,_33,_31],[_52,_53,_54,_55,_51]).

出力情報('','',_N,_N) :- !.
出力情報(_,_,_,'').

%% 2.17 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        forall(fizzbuzz(['','','Fizz'],['','','','','Buzz'],L),true).

fizzbuzz([A|R1],[B|R2],[N|R3]) :-
        fizzbuzz(A,B,N,C),
        writef('%w%w%w ',[A,B,C]).
fizzbuzz([A|R1],[B|R2],[_|R3]) :-
        append(R1,[A],L1),
        append(R2,[B],L2),
        fizzbuzz(L1,L2,R3).

fizzbuzz('','',N,N) :- !.
fizzbuzz(A,B,_,'').

%% 3.0 ペアノ数 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(M) :-
        s(S,M),
        fizzbuzz(S,s(0),s(s(s(0))),s(s(s(s(s(0)))))).

fizzbuzz(S,s(S),_,_) :- !.
fizzbuzz(MS,S,S1,S2) :-
        fizzbuzz(S,S1,S2,S_1,S1_1,S2_1,A),
        writef('%w ',[A]),
        fizzbuzz(MS,S_1,S1_1,S2_1).

fizzbuzz(S,S,S,s(S),s(s(s(S))),s(s(s(s(s(S))))),fizzbuzz) :- !.
fizzbuzz(S,S,S2,s(S),s(s(s(S))),S2,fizz) :- !.
fizzbuzz(S,S1,S,s(S),S1,s(s(s(s(s(S))))),buzz).
fizzbuzz(S,S1,S2,s(S),S1,S2,N) :-
        s(S,N).

s(0,0) :- !.
s(s(S),N) :-
var(N),
s(S,N_1),
succ(N_1,N).
s(s(S),N) :-
integer(N),
succ(N_1,N),
s(S,N_1).

%% 4.0 FizzBuzz整数の15個パターンの利用 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

finzzbuzz(N) :-
        fizzbuzz([],N,['FizzBuzz',_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_],[]).

fizzbuzz(Ln,N,_,_) :-
        length(Ln,N).
fizzbuzz(Ln,N,Ln2,[_,_,_,_,_,_,_,_,_,_,_,_,_,_,_]) :-
        fizzbuzz(Ln,N,Ln2,[]).
fizzbuzz(Ln,N,Ln2,L) :-
        append(_,[A|L],Ln2),
        fizzbuzz_2(Ln,A,B),
        writef('%w ',[B]),
        fizzbuzz([_|Ln],N,Ln2,[_|L]).

fizzbuzz_2(Ln,A,A) :-
        atom(A).
fizzbuzz_2(Ln,A,N) :-
        length([_|Ln],N).

%% 4.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        findall(M,between(1,N,M),L),
        fizzbuzz(L,[_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz']).

fizzbuzz([],_) :- !.
fizzbuzz(L,[]) :-
        fizzbuzz(L,[_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz']).
fizzbuzz([A|R1],[B|R2]) :-
        var(B),
        writef('%w ',[A]),
        fizzbuzz(R1,R2).
fizzbuzz([A|R1],[B|R2]) :-
        atomic(B),
        writef('%w ',[B]),
        fizzbuzz(R1,R2).

%% 4.2  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

'FizzBuzz'(N) :-
        findall(M,between(1,N,M),L1),
        'FizzBuzz置換パターン'(L1,L2),
        atomic_list_concat(L2,' ',S),
        writef('%w\n',[S]).

'FizzBuzz置換パターン'([_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15|R1],[_1,_2,'Fizz',_4,'Buzz','Fizz',_7,_8,'Fizz','Buzz',_11,'Fizz',_13,_14,'FizzBuzz'|R2]) :-
        'FizzBuzz置換パターン'(R1,R2).
'FizzBuzz置換パターン'(L,R) :-
        length(L,Len),
        length(R,Len),
        append(L,_,[_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15]),
        append(R,_,[_1,_2,'Fizz',_4,'Buzz','Fizz',_7,_8,'Fizz','Buzz',_11,'Fizz',_13,_14,'FizzBuzz']).


%% 4.3 nth1/3とfindall/3とflatten/2を利用 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        置換パターンならびを生成(_置換パターンならび),
        nth1(_nth1,_置換パターンならび,A),
        fizzbuzz_2(_nth1,A),
        _nth1 = N.

置換パターンならびを生成(_置換パターンならび) :-
        U is (N // 15) + 1,
        findall([_,_,'Fizz',_,'Buzz',_,_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,U,_),LL),
        flatten(LL,_置換パターンならび).

fizzbuzz_2(_nth1,A) :-
        var(A),
        writef('%w ',[_nth1]).
fizzbuzz_2(_,A) :-
        atom(A),
        writef('%w ',[A]).

%% 4.4 findall/3とforall/2を使う %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        M is N // 15 + 1,
        findall([_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,M,_),LL),
        flatten(LL,L),
        forall((
                 append(L0,[A|R],L),
                 length([_|L0],N_1),
                 (   N_1 > Max,!,fail;
                     fizzbuzz_2(A,N_1,B))),
                 writef('%w ',[B])).

fizzbuzz_2(A,N,N) :-
        var(A),!.
fizzbuzz_2(A,N,A).

%% 4.5 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        'fizzbuzzパターンの形成'(N,L),
        'fizz/buzz/fizzbuzz/順序数のどれかを表示する'(N,L,_順序数).

'fizzbuzzパターンの形成'(N,L) :-
        N_1 is (N - 1) // 15 + 1,
        findall([_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,N_1,_),LL),
        flatten(LL,L).

'fizz/buzz/fizzbuzz/順序数のどれかを表示する'(N,L,_順序数) :-
        nth1(_nth1,L,A),
        表示項の選択(_nth1,A,_表示項),
        writef('%w ',[_表示項]),
        _nth1 = N,!.

表示項の選択(_nth1,_nth1,_nth1) :- !.
表示項の選択(_nth1,A,A).

%% 4.6 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        'fizzbuzzパターンの形成'(N,L1),
        変数だけ要素位置番号を埋める(N,L1,L2),
        forall(member(A,L2),writef('%w ',[A])).

'fizzbuzzパターンの形成'(N,L) :-
        N_1 is (N - 1) // 15 + 1,
        findall([_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,N_1,_),LL),
        flatten(LL,L).

変数だけ要素位置番号を埋める(N,L1,L2) :-
        findall(U,(
                    nth1(_nth1,L1,U),
                    _nth1 =< N,
                    (U=_nth1;atom(U))),
                L2).

%% 4.7 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        'fizzbuzzパターンの形成'(N,L1),
        変数だけ要素位置番号を埋める(N,L1,L2),
        forall(member(A,L2),writef('%w ',[A])).

'fizzbuzzパターンの形成'(N,L) :-
        N_1 is (N - 1) // 15 + 1,
        findall([_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,N_1,_),LL),
        flatten(LL,L).

変数だけ要素位置番号を埋める(M,N,L) :- M > N,!.
変数だけ要素位置番号を埋める(M,N,[M|R]) :-
        M_2 is M + 1,
        変数だけ要素位置番号を埋める(M_2,N,R).
変数だけ要素位置番号を埋める(M,N,[_|R]) :-
        M_2 is M + 1,
        変数だけ要素位置番号を埋める(M_2,N,R).

%% 4.8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        'fizzbuzzパターンの形成'(N,L1),
        変数だけ要素位置番号を表示する(N,L1).

'fizzbuzzパターンの形成'(N,L) :-
        N_1 is (N - 1) // 15 + 1,
        findall([_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,N_1,_),LL),
        flatten(LL,L).

変数だけ要素位置番号を表示する(N,L1) :-
        forall((nth1(_nth1,L1,U),_nth1 =< N,(U=_nth1;atom(U))),writef('%w ',[U])).

%% 4.9 情報の持ち方が独特 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        fizzbuzz(0,N),!.

fizzbuzz(N,M) :-
        append(L0,[A|R],[1,2,[3,fizz],4,[5,buzz],[6,fizz],7,8,[9,fizz],[10,buzz],11,[12,fizz],13,14,[15,fizzbuzz]]),
        表示値(N,A,N3,_表示値),
        fizzbuzz_2(N,M,R,N3,_表示値).

fizzbuzz_2(N,M,R,N3,_表示値) :-
        N3 > M.
fizzbuzz_2(N,M,R,N3,_表示値) :-
        writef('%w ',[_表示値]),
        R = [],
        N4 is N + 15,
        fizzbuzz(N4,M).

表示値(N1,[N2,A],N3,A) :-
        N3 is N1 + N2,!.
表示値(N1,N2,N3,N3) :-
        N3 is N1 + N2.

%% 4.10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        N_1 is (N - 1) // 15 + 1,
        findall([_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],between(1,N_1,_),LL),
        flatten(LL,L1),
        forall((nth1(_nth1,L1,U),_nth1 =< N,(var(U),U=_nth1;atom(U))),writef('%w ',[U])).

%% 4.11 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
findnsols(N,_,(fizzbuzz_2(B),writef('%w ',[B])),_),!.

fizzbuzz_2(B) :-
nth0(I,_,_),
member(A,[1,2,'Fizz',4,'Buzz','Fizz',7,8,'Fizz','Buzz',11,'Fizz',13,14,'FizzBuzz']),
fizzbuzz_3(A,I,B).

fizzbuzz_3(A,_,A) :-
atom(A).
fizzbuzz_3(A,I,B) :-
integer(A),
B is 15 * I + A.

%% 4.12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
findnsols(N,_,(nth0(I,_,_),fizzbuzz_2(I,B)),_),!.

fizzbuzz_2(I,B) :-
member(A,[1,2,'Fizz',4,'Buzz','Fizz',7,8,'Fizz','Buzz',11,'Fizz',13,14,'FizzBuzz']),
fizzbuzz_3(A,I,B),
writef('%w ',[B]).

fizzbuzz_3(A,_,A) :-
atom(A).
fizzbuzz_3(A,I,B) :-
integer(A),
B is 15 * I + A.

%% 4.13 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
findnsols(N,_,fizzbuzz_2(B),_),!.

fizzbuzz_2(B) :-
nth0(I,_,_),
member(A,[1,2,'Fizz',4,'Buzz','Fizz',7,8,'Fizz','Buzz',11,'Fizz',13,14,'FizzBuzz']),
fizzbuzz_3(A,I,B),
writef('%w ',[B]).

fizzbuzz_3(A,_,A) :-
atom(A).
fizzbuzz_3(A,I,B) :-
integer(A),
B is 15 * I + A.

%% 4.14 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
findnsols(N,_,fizz_buzz_numberを表示する,_),!.

fizz_buzz_numberを表示する :-
fizz_buzz_numberを得る(A),
writef('%w ',[A]).

fizz_buzz_numberを得る(A) :-
nth0(_順目,_,_),
nth1(_位置,[_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz'],A),
変数には番号を埋める(_順目,_位置,A).

変数には番号を埋める(_,_,A) :-
atom(A).
変数には番号を埋める(_順目,_位置,A) :-
A is 15 * _順目 + _位置.

%% 4.15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
'N個の変数かfizzbuzzならび'(N,L),
'N個の変数かfizzbuzzならびを変数に順序数を埋めながら表示する'(L),!.

'N個の変数かfizzbuzzならび'(N,L) :-
findnsols(N,A,変数かfizzbuzzか(A),L).

変数かfizzbuzzか(A) :-
repeat,
member(A,[_,_,'Fizz',_,'Buzz','Fizz',_,_,'Fizz','Buzz',_,'Fizz',_,_,'FizzBuzz']).

'N個の変数かfizzbuzzならびを変数に順序数を埋めながら表示する'(L) :-
forall(fizzbuzz表示情報(L,A),writef('%w ',[A])).

fizzbuzz表示情報(L,A) :-
nth1(_位置,L,A),
'Aはfizzbuzzか_位置'(_位置,A).

'Aはfizzbuzzか_位置'(_位置,A) :-
atom(A).
'Aはfizzbuzzか_位置'(_位置,_位置).

%% 4.16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
fizzbuzz(1,M,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[]),
M=N,!.

fizzbuzz(M_1,M,L,[]) :-
fizzbuzz(M_1,M,L,L).
fizzbuzz(M,M,L,[A|R]) :-
writef('%w ',[A]).
fizzbuzz(M_1,M,L,[_|R]) :- 
succ(M_1,M_2),
fizzbuzz(M_2,M,L,R).

%% 4.16 (書き直し) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :- fizzbuzz(1,M,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[]),M = N,!.

fizzbuzz(I,J,L,[])    :- fizzbuzz(I,J,L,L).
fizzbuzz(I,I,L,[A|R]) :- writef('%w ',[A]).
fizzbuzz(I,J,L,[_|R]) :- succ(I,K), fizzbuzz(K,J,L,R).

%% 4.17 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :- fizzbuzz([_],M,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[]),M = N,!.

fizzbuzz(Ln,I,L,[])    :- fizzbuzz(Ln,I,L,L).
fizzbuzz(Ln,I,L,[A|R]) :- length(Ln,I), writef('%w ',[A]).
fizzbuzz(Ln,I,L,[_|R]) :- fizzbuzz([_|Ln],I,L,R).

%% 4.18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(Max) :- fizzbuzz(M,A),writef('%w ',[A]),Max = M,!. 

fizzbuzz(M,A) :- fizzbuzz([_],M,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[],A).

fizzbuzz(Ln,I,L,[],A)    :- fizzbuzz(Ln,I,L,L,A).
fizzbuzz(Ln,I,L,[A|R],A) :- length(Ln,I).
fizzbuzz(Ln,I,L,[_|R],A) :- fizzbuzz([_|Ln],I,L,R,A).

%% 4.19 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(Max) :-
findnsols(Max,A,fizzbuzz([_],M,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[],A),L),
atomic_list_concat(L,' ',W),
writef('%w\n',[W]),!.

fizzbuzz(Ln,I,L,[],A)    :- fizzbuzz(Ln,I,L,L,A).
fizzbuzz(Ln,I,L,[A|R],A) :- length(Ln,I).
fizzbuzz(Ln,I,L,[_|R],A) :- fizzbuzz([_|Ln],I,L,R,A).

%% 4.20 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(Max) :-
findnsols(Max,A,fizzbuzz([_],M,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[],A),Y,['\n']),
atomic_list_concat(Y,' ',FizzBuzz),
write(FizzBuzz),!.

fizzbuzz(Ln,I,L,[],A)    :- fizzbuzz(Ln,I,L,L,A).
fizzbuzz(Ln,I,L,[A|R],A) :- length(Ln,I).
fizzbuzz(Ln,I,L,[_|R],A) :- fizzbuzz([_|Ln],I,L,R,A).

%% 4.21 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
fizzbuzz([_],M,A,[M,M,fizz,M,buzz,fizz,M,M,fizz,buzz,M,fizz,M,M,fizzbuzz],[]),
M=N,!.

fizzbuzz(Ln,M,A,L,[A|R]) :-
表示する(Ln,M,A).
fizzbuzz(Ln,M,A,L,[_|R]) :-
fizzbuzz([_|Ln],M,A,L,R).
fizzbuzz(Ln,M,A,L,[]) :-
fizzbuzz(Ln,M,A,L,L).

表示する(Ln,M,A) :-
length(Ln,M),
writef('%w ',[A]).

%% 4.22 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
fizzbuzz(1,_,[A|_],[_,_,fizz,_,buzz,fizz,_,_,fizz,buzz,_,fizz,_,_,fizzbuzz],M),
(A = M; atom(A)),
writef('%w ',[A]),
M = N,!.

fizzbuzz(M,[],L,L,M).
fizzbuzz(M,[A|L1],L2,[A|L3],N) :-
M_2 is M + 1,
append(L3,[A],L4),
fizzbuzz(M_2,L1,L2,L4,N).

%% 5.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(N) :-
        'fizzbuzzパターンの形成'(N,L_f,L_b),
        'fizz/buzz/fizzbuzz/順序数のどれかを表示する'(N,L_f,L_b,_順序数).

'fizzbuzzパターンの形成'(N,L_f,L_b) :-        
        N_f is (N - 1) // 3 + 1,
        findall(['','','Fizz'],between(1,N_f,_),LL_f),
        flatten(LL_f,L_f),
        N_b is (N - 1) // 5 + 1,
        findall(['','','','','Buzz'],between(1,N_b,_),LL_b),
        flatten(LL_b,L_b).

'fizz/buzz/fizzbuzz/順序数のどれかを表示する'(N,L,_順序数) :-
        nth1(_nth1,L_f,F),
        nth1(_nth1,L_b,B),
        表示項の選択(_nth1,F,B,_表示項),
        writef('%w ',[_表示項]),
        _nth1 = N,!.

表示項の選択(_nth1,'','',_nth1) :- !.
表示項の選択(_,A,B,_表示項) :-
        atomic_list_concat([A,B],_表示項).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#  
#  FizzBuzz問題の要領で、1から100までの整数を、かいぎょう区切りで出力せよ、ただし、 
#  3の倍数なら「Fizz」を、7の倍数なら「Buzz」を、13の倍数なら「hoge」を、 
#  数値の代わりに出力することとする 
#  

'FizzBuzzhoge' :-
        'FizzBuzzhoge'([],['','','Fizz'],['','','','','','','Buzz'],['','','','','','','','','','','','','hoge']).

'FizzBuzzhoge'(Ln,_,_,_) :- length(Ln,100),!.
'FizzBuzzhoge'(Ln,L1,L2,L3) :-
        'FizzBuzzhoge'([_|Ln],L1,L2,L3,_表示情報),
        writef('%w\n',[_表示情報]),
        三つのリストの左シフト(L1,L2,L3,L1_2,L2_2,L3_2),
        'FizzBuzzhoge'([_|Ln],L1_2,L2_2,L3_2).

'FizzBuzzhoge'(Ln,[''|_],[''|_],[''|_],_数値) :-
        length(Ln,_数値),!.
'FizzBuzzhoge'(Ln,[A|_],[B|_],[C|_],_FizzBuzzhoge文字列) :-
        atomic_list_concat([A,B,C],_FizzBuzzhoge文字列).

三つのリストの左シフト([A|R1],[B|R2],[C|R3],L1,L2,L3) :-
        append(R1,[A],L1),
        append(R2,[B],L2),
        append(R3,[C],L3).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fizzbuzz(_まで) :-
        fizzbuzz([],_まで,あとふたつ,あとよっつ).

fizzbuzz(L1,_まで,_,_) :-
        length(L1,_まで),!.
fizzbuzz(L1,_まで,_Fizzまであといくつ_1,_Buzzまであといくつ_1) :-
        fizzbuzz_1([_|L1],_Fizzまであといくつ_1,_Buzzまであといくつ_1,_Fizzまであといくつ_2,_Buzzまであといくつ_2,Y),
        writef('%w ',[Y]),
        fizzbuzz([_|L1],_まで,_Fizzまであといくつ_2,_Buzzまであといくつ_2).

fizzbuzz_1(_,ないよ,ないよ,あとふたつ,あとよっつ,'FizzBuzz').
fizzbuzz_1(_,ないよ,_Buzzまであといくつ_1,あとふたつ,_Buzzまであといくつ_2,'Fizz') :-
        ひとつ減らすよ(_Buzzまであといくつ_1,_Buzzまであといくつ_2).
fizzbuzz_1(_,_Fizzまであといくつ_1,ないよ,_Fizzまであといくつ_2,あとよっつ,'Buzz') :-
        ひとつ減らすよ(_Fizzまであといくつ_1,_Fizzまであといくつ_2).
fizzbuzz_1(L1,_Fizzまであといくつ_1,_Buzzまであといくつ_1,_Fizzまであといくつ_2,_Buzzまであといくつ_2,N) :-
        ひとつ減らすよ(_Fizzまであといくつ_1,_Fizzまであといくつ_2),
        ひとつ減らすよ(_Buzzまであといくつ_1,_Buzzまであといくつ_2),
        length(L1,N).

ひとつ減らすよ(あとよっつ,あとみっつ).
ひとつ減らすよ(あとみっつ,あとふたつ).
ひとつ減らすよ(あとふたつ,あとひとつ).
ひとつ減らすよ(あとひとつ,ないよ).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

佑(_丈) :-
        校([],_丈,碩,漁).

校(_里,_丈,_,_) :-
        length(_里,_丈),!.
校(_里,_丈,_部,_寓) :-
        乾([_|_里],_部,_寓,_料,_勘,_公),
        writef('%w ',[_公]),
        校([_|_里],_丈,_料,_勘).

乾(_,建,建,碩,漁,'FizzBuzz').
乾(_,建,_寓,碩,_勘,'Fizz') :-
        装(_寓,_勘).
乾(_,_発,建,_塔,漁,'Buzz') :-
        装(_発,_塔).
乾(_里,_発,_寓,_塔,_勘,_論) :-
        装(_発,_塔),
        装(_寓,_勘),
        length(_里,_論).

装(漁,宜).
装(宜,碩).
装(碩,週).
装(週,建).


%
%  述語名、変数からシンボル性を除去した述語定義。
%  一つ上のFizzBuzz定義の述語名と変数名を無作為に全角漢字を
%  引いてきて置き換えた。プログラミングにはこういう一面が常に
%  多少はある。
%
%%%%%%% デスマコロシアム(5)   fizzbuzzをFIZZBUZZと表記する(1)   %%%%%%%%%%%

fizzbuzz(M) :-
fizzbuzz(0,M,[_,_],[_,_,_,_],L),
atomic_list_concat(L,A),
write(A).

fizzbuzz(M,M,_,_,[]).
fizzbuzz(N,M,L1,L2,[A|R3]) :-
succ(N,N_2),
dt(N_2,L1,L2,R1,R2,A),
fizzbuzz(N_2,M,R1,R2,R3).

dt(_,[],[],[_,_],[_,_,_,_],'FIZZBUZZ') :- !.
dt(_,[],[_|R],[_,_],R,fizz) :- !.
dt(_,[_|R],[],R,[_,_,_,_],buzz) :- !.
dt(N,[_|R1],[_|R2],R1,R2,N).


%%%%%%% デスマコロシアム(5)   fizzbuzzをFIZZBUZZと表記する(2)   %%%%%%%%%%%

fizzbuzz(N) :-
N_1 is (N - 1) // 15 + 1,
findall([_,_,'fizz',_,'buzz','fizz',_,_,'fizz','buzz',_,'fizz',_,_,'FIZZBUZZ'],between(1,N_1,_),LL),
flatten(LL,L1),
forall((nth1(_nth1,L1,U),_nth1 =< N,(_nth1=U;atom(U))),writef('%w',[U])).

%%%%%%% デスマコロシアム(5)   fizzbuzzをFIZZBUZZと表記する(3)   %%%%%%%%%%%

fizzbuzz(N) :-
N_1 is (N - 1) // 15 + 1,
findall([_,_,'fizz',_,'buzz','fizz',_,_,'fizz','buzz',_,'fizz',_,_,'FIZZBUZZ'],between(1,N_1,_),LL),
flatten(LL,L),
表示(N,L).

表示(N,L) :-
nth1(_nth1,L,U),
表示選択(_nth1,U),
writef('%w',[U]),
_nth1=N.

表示選択(_nth1,_nth1).
表示選択(_,U) :- atom(U).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%  
%  最小文字数を競ってみよう(現在 147字)
%  

fizzbuzz(N):-between(1,N,M),put(32),g(M,S),write(S),M=N.
g(M,'Fizz'):-m(M,3).
g(M,'Buzz'):-m(M,5).
g(M,M):- \+m(M,3),\+m(M,5).
m(M,N):-0=:=M mod N.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%  
%  述語名fizzbuzzをfにして良いなら 140字 (twitterの1twit限度文字数)
%  

f(N):-between(1,N,M),put(32),g(M,S),write(S),M=N.
g(M,'Fizz'):-m(M,3).
g(M,'Buzz'):-m(M,5).
g(M,M):- \+m(M,3),\+m(M,5).
m(M,N):-0=:=M mod N.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%  IF/Prolog (for/3,if/3 を使って)
%  
%  述語名fizzbuzzをfにして良いなら 83字
%  

f(M):-for(1,N,M),nl,if((1>N mod 3,A=fizz;1>N mod 5,A=buzz),write(A),write(N)),M=N.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

f(M):-between(1,M,N),\+(forall((1>N mod 3,A=fizz;1>N mod 5,A=buzz),write(A))->write(N)),M=N.