このディレクトリの索引
# 出典::C/C++の宿題片付けます 128代目 #222
# [1] 授業単元:プログラミング
# [2] 問題文(含コード&リンク):
# http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9599.txt
# “パスカルの三角形”を表示するプログラムを作ってください。
# ただし、表示する段数はキー入力するようにします。 
# 
# 実行の様子はこのような感じです。 
# 
# [b8000@localhost]$ ./main
# 何段表示しますか?: 13
#                                       1   
#                                    1     1   
#                                 1     2     1   
#                              1     3     3     1   
#                           1     4     6     4     1   
#                        1     5    10    10     5     1   
#                     1     6    15    20    15     6     1   
#                  1     7    21    35    35    21     7     1   
#               1     8    28    56    70    56    28     8     1   
#            1     9    36    84   126   126    84    36     9     1   
#         1    10    45   120   210   252   210   120    45    10     1   
#      1    11    55   165   330   462   462   330   165    55    11     1   
#   1    12    66   220   495   792   924   792   495   220    66    12     1  
# 
# 
# この問題は、calloc() を使って領域確保をしてください。
# 段数を入力した後、calloc() を使って、必要分の領域確保をします。
# 
# 表示の体裁は大まかに二等辺三角形の形になっていればOKです。
# なお、上の実行例のプログラムでは、 
# 
# printf("%3d   ", 〜);
#             ↑
#    ここは半角スペース3個
# 
# という記述で表示を行なっています。

パスカルの三角形(_段) :-
パスカルの三角形(_段,LL),
パスカルの三角形_表示(_段,LL).

パスカルの三角形(_段,[[1]|LL]) :-
length([_|Ln],_段),
パスカルの三角形加算(Ln,[1,1],LL).

パスカルの三角形加算([],_,[]).
パスカルの三角形加算([_|Ln],L,[L|R2]) :-
指定された段に達するまでパスカルの三角形加算を続ける(Ln,L,R2).

指定された段に達するまでパスカルの三角形加算を続ける(Ln,L,R2) :-
パスカルの三角形一行計算(L,L1),
パスカルの三角形加算(Ln,L1,R2).

パスカルの三角形一行計算(L,L1) :-
上の行の隣り合う二項の合計を取っていく(L,L0),
両端に1を付加する(L0,L1).

上の行の隣り合う二項の合計を取っていく(L,L0) :-
findall(N,(
append(_,[A,B|_],L),N is A + B),L0).

両端に1を付加する(L0,L1) :-
append([1|L0],[1],L1).

パスカルの三角形_表示(0,_) :- !.
パスカルの三角形_表示(N,[L|R]) :-
'N>0の間、パスカルの三角形の表示'(N,L,R).

'N>0の間、パスカルの三角形の表示'(N,L,R) :-
N > 0,
succ(N_1,N),
パスカルの三角形一行表示(N_1,L),
パスカルの三角形_表示(N_1,R).

パスカルの三角形一行表示(N_1,L) :-
左端からの空白表示(N_1),
パスカルの三角形部分表示(L),
write('\n').

左端からの空白表示(N_1) :-
左端からの空白文字列の生成(N_1,_空白文字列),
writef('%w',[_空白文字列]).

左端からの空白文字列の生成(N_1,_空白文字列) :-
左端からの空白文字ならびの生成(N_1,_空白ならび),
atomic_list_concat(_空白ならび,_空白文字列).

左端からの空白文字ならびの生成(N_1,_空白ならび) :-
Len is 3 * N_1,
length(_空白ならび,Len),
all(_空白ならび,' ').

all([],_).
all([V|R],V) :- all(R,V).

パスカルの三角形部分表示(L) :-
forall(member(A,L),
writef('%5r ',[A])).