このディレクトリの索引

#  http://pc8.2ch.net/test/read.cgi/tech/1152253441/215 
#  【 課題 】キーボードから10個の数字を入力する。 
#        隣同士の足し算をし、以下の例のように1の位の数字を次の行に出力し、 
#        最後に残った数字を出力する。 
#   
#        (例) 
#        数字を入力してください。 
#        2359318473 
#   
#        2 3 5 9 3 1 8 4 7 3 
#         5 8 4 2 4 9 2 1 0 
#         3 2 6 6 3 1 3 1 (以下略 
#   
#        最後に残った数字は 2 です。 
# 

% 言語: Prolog (IF/Prolog)

'キーボードから10個の数字を入力する。隣同士の足し算をし、1の位の数字を次の行の現在行の数字の間に全体として逆三角形を形成するように出力し、最後に残った数字を別の行に出力する。数字の間には必ずひとつ空白が入るようにすること。' :-
        キーボードから10個の数字を入力する(L),
        加算逆ピラミッド表を作る([],L,_最後に残った数字),
        write_formatted('残った数字は: %t です\n',[最後に残った数字]).

キーボードから10個の数字を入力する(L) :-
        write('10個の数字列を入力してください :'),
        n個の数字ならびを得る(10,L),

加算逆ピラミッド表を作る(Ln,[X],X) :-
        空白文字列印字(Ln),
        writef('%t\n',[X]),!.
加算逆ピラミッド表を作る(Ln,L,X) :-
        一行表示(Ln,L),
        加算逆ピラミッド表の加算処理(L,L2),
        加算逆ピラミッド表を作る([' '|Ln],L2,X).

一行表示(Ln,L) :-
        空白文字列印字(Ln),
        append(_,[A|[B|R]],L),
        writef('%t ',[A]),
        R = [],
        writef('%t\n',[B]),!.

加算逆ピラミッド表の加算処理([_],[]).
加算逆ピラミッド表の加算処理([A,B|R1],[C|R2]) :-
        C is (A+B) mod 10,
        加算逆ピラミッド表の加算処理([B|R1],R2).

n個の数字ならびを得る(N,L) :-
        length(Ln,N),
        数字ならびを得る(Ln,L).

数字ならびを得る([],[]).
数字ならびを得る([_|Ln],[N|R]) :-
        数字をひとつ得る(N),
        数字ならびを得る(Ln,R).
数字ならびを得る([_|Ln],N) :-
        数字ならびを得る([_|Ln],N).

数字をひとつ得る(N) :-
        get_code(C),
        N is C - 48,
        between(0,9,N).

空白文字列印字(L) :-
        all(L,' '),
        append(_,[A|R],L),
        writef('%t',[A]),
        R = [].

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


'対角要素は変数、対角要素より下はすべて_値1、上はすべて_値2であるようなN次の正方行列'(N,_値1,_値2,_対角以外値が埋め込まれた正方行列,_対角要素の変数ならび) :-
        integer(N),
        length(L,N),
        '一行づつ_値1+_変数+_値2のならびを構成していく'(L,_値1,_値2,LY),
        正方行列と変数ならびに分離(LY,_対角以外値が埋め込まれた正方行列,_対角要素の変数ならび).

'一行づつ_値1+_変数+_値2のならびを構成していく'(L,_値1,_値2,LY) :-
        findall([_列ならび,_対角部分の変数],(   一行取り出す(L1,A,L2,L),
                          '_値1+_変数+_値2となる行を構成'(L1,L2,_値1,_値2,_列ならび,_対角部分の変数)),
                LY).
一行取り出す(L,L1,A,L2) :- append(L1,[A|L2],L).

'_値1+_変数+_値2となる行を構成'(L1,L2,_値1,_値2,_列ならび,A) :-
        length(L1,N1),length(L11,N1),
        length(L2,N2),length(L22,N2), 
        all(L11,_値1),all(L22,_値2),
        append(L11,[A|L22],_列ならび),!.

正方行列と変数ならびに分離([],[],[]) :- !.
正方行列と変数ならびに分離([[L,V]|R1],[L|R2],[V|R3]) :- 正方行列と変数ならびに分離(R1,R2,R3).

対角要素(M,N,_,[]) :- M > N,!.
対角要素(M,N,_行列,[_要素|R]) :-
        list_nth(M,_行列,_行),
        list_length(_行,N),
        list_nth(M,_行,_要素),
        M2 is M + 1,
        対角要素(M2,N,_行列,R).

対角要素(_行列,_対角要素) :-
        length(_行列,N),
        対角要素(1,N,_行列,_対角要素).

# http://pc12.2ch.net/test/read.cgi/tech/1244449887/953
# [1] 授業単元: ピラミッドアート
# [2] 問題文(含コード&リンク): http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9534.txt
# 課題「ピラミッドアート」
# 
# 数値を一つ入力し、その個数分の'*'を1辺とする
# ?ダイヤ型、?八角形、?星型 などを描画する
# 
# 実行画面例?ダイヤ型
# 数字(2〜9)を入力してください:3
#   *
#  ***
# *****
#  ***
#   *
# 
# 実行画面例?八角形
# 数字(2〜9)を入力してください:2
#  **
# ****
# ****
#  **
# 
# 実行画面例?星型
# 数字(2〜9)を入力してください:7
# *  *  *
#  * * *
#   ***
# *******
#   ***
#  * * *
# *  *  *
# 
# ---------------------------------------------
# オプション:描画する図形の内部を空白にする
# 
# 実行画面例?ダイヤ型(中抜き)
# 数字(2〜9)を入力してください:3
#   *
#  * *
# *   *
#  * *
#   *
# 
# 実行画面例?八角形(中抜き)
# 数字(2〜9)を入力してください:2
#  **
# *  *
# *  *
#  **
# 
# 実行画面例?星型(中抜き)
# 数字(2〜9)を入力してください:7
# *  *  *
#  * * *
#   ***
# *** ***
#   ***
#  * * *
# *  *  *

ピラミットアート(ダイヤ型,N) :-
    M is 2 * N - 1,
    for(1,J,M),
    ピラミットアート行(_,M,J,L1),
    put_chars(L1),nl,
    J=M,
    M2 is M - 1,
    for(M2,K,1),
    ピラミットアート行(_,M,K,L2),
    put_chars(L2),nl,
    K = 1.

ピラミットアート(八角形,N) :-
    M is N + 2 * (N - 1),
    N2 is N - 1,
    for(1,J,N2),
    J2 is N + 2 * J,
    ピラミットアート行(_,M,J2,L1),
    put_chars(L1),nl,
    J=N2,
    for(1,J2,N),
    ピラミットアート行(_,M,M,L2),
    put_chars(L2),nl,
    J=N,
    for(N2,K,1),
    K2 is N + 2 * K,
    ピラミットアート行(_,M,K2,L3),
    put_chars(L3),nl,
    K = 1.

ピラミットアート行(_,M,J,L) :-
    length(L,M),
    length(L1,J),
    all(L1,'*'),
    append(L0,L1,L2,L),
    length(L0,Len0),
    length(L2,Len0),
    all(L0,' '),
    all(L2,' ').

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
put_chars([]) :- !.
put_chars([A|R]) :- write(A),put_chars(R).

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

append([],L1,L2,L)
  :-
    append(L1,L2,L).
append([A|R1],L1,L2,[A|R])
  :-
    append(R1,L1,L2,R).



http://pc12.2ch.net/test/read.cgi/tech/1245853701/75
# [1] 授業単元: C
# [2] 問題文(含コード&リンク):
# キーボードから入力された1以上の整数nについて、次の例に示すように行番号と*を表示するプログラムを作成せよ
# 。また、0や負の数が入力された場合はプログラムが終了するようにせよ。
# 表示結果の例
# 正の整数:6
# 1******
# 2 *****
# 3    ****
# 4     ***
# 5        **
# 6          *

t293(N) :-
    length(L,N),
    append(L1,L2,L),
    not(L2=[]),
    all(L1,'  '),
    all(L2,'*'),
    length(L1,N),
    N2 is N + 1,
    concat_atom(L,S),
    write_formatted('%t %t\n',[N2,S]),
    fail;
    true.

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


http://pc12.2ch.net/test/read.cgi/tech/1245853701/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個
# 
# という記述で表示を行なっています。

パスカルの三角形(_段) :-
    length(L,_段),
    append(L1,[1|L2],L),
    length(L1,N),
    length(L2,N),
    all(L1,0),
    all(L2,0),
    パスカルの三角形(2,_段,L,X),
    パスカルの三角形_表示(X).

パスカルの三角形(N,_段,_,[]) :-
    N > _段,!.
パスカルの三角形(N,_段,[L1|R1],[L|R2]) :-
    パスカルの三角形_1(1,_段,L1,L),
    M is N + 1,
    パスカルの三角形(M,_段,[L,L1|R1],R2).

パスカルの三角形_1(N,_段,_,[]) :-
    N > _段,!.
パスカルの三角形_1(N,_段,L1,[N|R]) :-
    パスカルの三角形_加算(N,L1,N),
    M is N + 1,
    パスカルの三角形_1(M,_段,L1,R).

パスカルの三角形_加算(N,L,N) :-
    M1 is N-1,
    パスカルの三角形_list_nth(M1,L,N1),
    M2 is N+1,
    パスカルの三角形_list_nth(M2,L,N2),
    X is N1+N2.
    
パスカルの三角形_list_nth(N,L,X) :-
    list_nth(N,L,X),!.    
パスカルの三角形_list_nth(_,_,0).

パスカルの三角形_表示(L) :-
    member(A,L),
    パスカルの三角形表示_1(A),
    write('\n'),
    fail.
パスカルの三角形_表示(_).

パスカルの三角形_表示_1([0|R]) :-
    write_formatted('%3s',[' ']),
    パスカルの三角形_表示_1(R),!.
パスカルの三角形表示_1([N|R]) :-
    write_formatted('%3d',[N]),
    パスカルの三角形_表示_1(R),!.

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


http://pc12.2ch.net/test/read.cgi/tech/1245853701/243 
# [1] 授業単元: プログラミング演習   
# [2] 問題文(含コード&リンク): http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9605.txt   
# ある宝くじ売り場は窓口が1つだけあり、10::00〜15:00の5時間営業している
# この宝くじ売り場には平均して4分に1人の客がやってくる
# また、1人の客が宝くじの購入に要する時間tは以下に従うようにする
# 
# 購入に要する時間  割合
#    1分     20%
#    3分     60%
#    5分     13%
#   10分      5%
#   15分      2%
# 
# この宝くじ売り場にできるだろう行列の変化の様子をシュミレーションし、
# 下記の実行結果のように売り場に並んでいる客の行列の状態を15分刻みで表示するプログラムを作成せよ
# 
# 実行結果
# $ ./a.out ※rand()関数を使っているため、実行環境によって全く同じ結果にはならない
# 10:00 :
# 10:15 : *
# 10:30 : 
# 10:45 : **
# 11:00 : 
# 11:15 : ***
# 11:30 : ***
# 11:45 : ****
# 12:00 : **
# 12:15 : ****
# 12:30 : *****
# 12:45 : ******
# 13:00 : *******
# 13:15 : *******
# 13:30 : *******
# 13:45 : *******
# 14:00 : *****
# 14:15 : *
# 14:30 : ****
# 14:45 : *********
# 15:00 : ******
# 時間内に来た客の数       : 92
# 時間内に対応できた客の数 : 86

宝くじ売り場にできるだろう行列の変化の様子をシュミレーションし、下記の実行結果のように売り場に並んでいる客の行列の状態を15分刻みで表示する(_レジならび記録) :-
        待ち時間付き顧客ならびの生成(_顧客ならび),
        レジのシミュレーション(0,300,L2,[],RL,_レジならび記録),
        15分ごとにグラフ表示(_レジならび記録).

待ち時間付き顧客ならびの生成(L) :-
        findall([T,W,N],(for(1,N,75),顧客ならびの生成(T,W)),L1),
        sort(L1,L).

顧客ならびの生成(_開店N分後,_購入に要する時間) :-
        _開店N分後 is random mod 300,
        購入に要する時間(_購入に要する時間).

レジのシミュレーション(N,N,,_,L,L,[[N|L]]) :- !.
レジのシミュレーション(N1,N,[[N1,W,_]|R1],L1,L2,R2) :-
        レジのシミュレーション(N1,N,R1,[W|L3],L2,R2).
レジのシミュレーション(N1,N,[[N2,W,Z]|R1],L1,L2,[[N1,L1]|R2]) :-
        N2 > N1,
        1分経過した待ち列(L1,L3),
        N3 is N1 + 1,
        レジのシミュレーション(N3,N,[[N2,W,Z]|R1],L3,L2,R2).

15分ごとにグラフ表示([]) :- !.
15分ごとにグラフ表示([[N,L]|R]) :-
        0 is N mod 15,
        時・分を得る(N,_時,_分),
        星の生成(L,_星文字列),
        write_formatted('%2d:%2d : %t\n',[_時,_分,_星文字列]),
        15分ごとにグラフ表示(R),!.
15分ごとにグラフ表示([[N,L]|R]) :-
        not(0 is N mod 15),
        15分ごとにグラフ表示(R),!.

時・分を得る(N,_時,分) :-
        D is N // 60,
        _時 is 10 + D,
        _分 is N mod 60.

星の生成(L,_星文字列) :-
        length(L,Len),
        length(L1,Len),
        all(L1,'*'),
        atom_chars(S,L1),!.

購入に要する時間(_購入に要する時間) :-
        N is random mod 100,
        乱順発生番号(A,N),
        購入に要する時間(A,_購入に要する時間).        

購入に要する時間(1分客,1).
購入に要する時間(3分客,3).
購入に要する時間(5分客,5).
購入に要する時間(10分客,10).
購入に要する時間(15分客,15).

乱順発生番号(1分客,N) :- N>=0,N=<19.
乱順発生番号(3分客,N) :- N>=20,N=<79.
乱順発生番号(5分客,N) :- N>=80,N=<92.
乱順発生番号(10分客,N) :- N>=93,N=<97.
乱順発生番号(15分客,N) :- N>=98,N=<99.

1分経過した待ち列([],[]) :- !.
1分経過した待ち列([1|R1],R2) :-
        1分経過した待つ列(R1,R2),!.\
1分経過した待ち列([N|R1],[N2|R2]) :-
        N2 is N - 1,
        1分経過した待ち列(R1,R2).

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

http://pc12.2ch.net/test/read.cgi/tech/1245853701/607 
# 簡単なデータベース機能を持つプログラムを作成しなさい.対象となるデータは自分で 
考えてください. 
#   (住所録,商品の在庫,図書,ワールドカップの勝敗....) 
#  以下の要件を示します. 
# 
# 1. ファイルからデータを読み込む機能をつけること. 
# 2. データは4つ以上の項目を保持させること. 
#  (住所録では、「名前」「住所」「郵便番号」「電話番号」等で4項目以上) 
# 3. 並び替えの機能をつけること.また並び替える項目が指定できること. 
# 4. 各項目についてデータの検索を行う機能をつけること.また,検索条件を組み合わ 
せることができること. 
#  (住所録なら,「郵便番号」が 399 で始まって,かつ,「電話番号」が 026 で始ま 
る 等) 
# 5. データは半角英数字(英語やローマ字)で扱ってよい 
# 6. データの追加ができること. 
# 7. データの削除ができること.削除は上記の検索と組み合わせることで,ある条件に 
合致したデータを削除できること. 
# 8. 追加・削除した結果をファイルに保存できること. 

鍵項目位置(書籍名,prolog関連書籍(_書籍名,_,_,_,_,_,_,_),_書籍名).
鍵項目位置(副書籍名,prolog関連書籍(_,_副書籍名,_,_,_,_,_,_),_副書籍名).
鍵項目位置(著者名,prolog関連書籍(_,_,_著者名,_,_,_,_,_),_著者名).
鍵項目位置(翻訳者名,prolog関連書籍(_,_,_,_翻訳者名,_,_,_,_),_翻訳者名).
鍵項目位置(発行年月日,prolog関連書籍(_,_,_,_,_発行年月日,_,_,_),_発行年月日).
鍵項目位置(出版社名,prolog関連書籍(_,_,_,_,_,_出版社名,_),_出版社名),
鍵項目位置(書籍コード,prolog関連書籍(_,_,_,_,_,_,_書籍コード),_書籍コード).

項目名を指定しての参照(_述語名/_引数の数,_項目名ならび,_値ならび) :-
    length(L,_引数の数),
    P =.. [_述語名|L],
    findall(_項目値,( call(P),
                      member(_項目名,_項目名ならび),
                      鍵項目位置(_項目名,P,_項目値)),_値ならび).

項目名を指定して節構造ならびの参照(_項目名ならび,_節構造ならび,_値ならび) :-
    member([_頭部,_本体],_節構造ならび),
    findall(_項目値,( call(_本体),  /* このアサーションを実行するかが大問題 */
                      member(_項目名,_項目名ならび),
                      鍵項目位置(_項目名,_頭部,_項目値)),_値ならび).

データベースへの登録(_ファイル) :-
    reconsult(_ファイル).

データベースへの追加(_項) :-
    assertz(_項).

データベースからの削除(_項) :-
    retract(_項).

データベースの保存(_述語名/_引数の数,_保存ファイル名) :-
    tell(_保存ファイル名),
    listing(_述語名/_引数の数),
    told.

節定義の並べ替え(_述語名/_引数の数,_鍵項目,上昇順) :-
    上昇順節構造(_述語名/_引数の数,_鍵項目,_上昇順に整列された節構造ならび),
    abolish(_述語名/引数の数),
    (   member([H,B],_上昇順に整列された節構造ならび),
        assertz((H :- B)),
        fail;
        true
    ).

節定義の並べ替え(_述語名/_引数の数,_鍵項目,下降順) :-
    下降順節構造(_述語名/_引数の数,_鍵項目,_上昇順に整列された節構造ならび),
    abolish(_述語名/引数の数),
    (   member([H,B],_上昇順に整列された節構造ならび),
        assertz((H :- B)),
        fail;
        true
    ).

上昇順節構造(_述語名/_引数の数,
             _鍵項目,
             _上昇順に整列された節構造ならび) :-
    節構造ならびの取得(_述語名/_引数の数,_節構造ならび),
    ならびの先頭に鍵項目を付加(_鍵項目ならび,
                               _節構造ならび,
                               _鍵付加き節構造ならび),
    上昇順整列(_鍵付加き節構造ならび,
               _上昇順に整列された鍵付き節構造ならび),
    ならびの先頭の鍵項目を除去(_上昇順に整列された鍵付き節構造ならび,
                 _上昇順に整列された節構造ならび),!.

下降順節構造(_述語名/_引数の数,_鍵項目,_下降順に整列された節構造ならび) :-
    節構造ならびの取得(_述語名/_引数の数,_節構造ならび),
    ならびの先頭に鍵項目を付加(_鍵項目ならび,
                               _節構造ならび,
                               _鍵付加き節構造ならび),
    下降順整列(_鍵付加き節構造ならび,
             _下降順に整列された鍵付き節構造ならび),
    ならびの先頭の鍵項目を除去(_下降順に整列された鍵付き節構造ならび,
                 _下降順に整列された節構造ならび),!.

節構造ならびの取得(_述語名/_引数の数,_節構造ならび) :-
    length(L,_引数の数),
    H =.. [_述語名|L],
    findall([H,B],clause(H,B),_節構造ならび),!.

ならびの先頭に鍵項目を付加(_,[],[]) :- !.
ならびの先頭に鍵項目を付加(_鍵項目ならび,
                           [[_頭部,_本体]|R1],
                           [_鍵付き節構造|R2]) :-
    findall(_値,(member(_鍵,_鍵項目ならび),鍵項目位置(_鍵,_頭部,_値)),L),
    append(L,[_頭部,_本体],_鍵付き節構造),

ならびの先頭の鍵項目を除去(_鍵項目ならび,_鍵付き節構造ならび,_節構造ならび) :-
    length(_鍵項目ならび,_除去する項数),
    ならびの先頭N個の鍵項目を除去(N,_鍵付き節構造ならび,_節構造ならび).

ならびの先頭N個の鍵項目を除去(N,[L1|R1],[L2|R2]) :-
    append(L0,L2,L1),
    length(L0,N),
    ならびの先頭N個の鍵項目を除去(N,R1,R2).

上昇順に整列(L1,L2) :-
    整列(上昇,L1,L2).

下降順に整列(L1,L2) :-
    整列(下降,L1,L2).

整列(_,[],[]) :- !.
整列(_上昇または下降,[X|Xs],Ys) :-
    配分(_上昇または下降,Xs,X,Littles,Gigs),
    整列(_上昇または下降,Littles,Ls),
    整列(_上昇または下降,Bigs,Bs),
    append(Ls,[X|Bs],Ys).

配分(_,[],Y,[],[]) :- !.
配分(上昇,[X|Xs],Y,[X|Ls],Bs) :- X @=< Y,!,配分(上昇,Xs,Y,Ls,Bs).
配分(上昇,[X|Xs],Y,Ls,[X|Bs]) :- X @> Y,!,配分(上昇,Xs,Y,Ls,Bs).
配分(下降,[X|Xs],Y,[X|Ls],Bs) :- X @>= Y,!,配分(下降,Xs,Y,Ls,Bs).
配分(下降,[X|Xs],Y,Ls,[X|Bs]) :- X @< Y,!,配分(下降,Xs,Y,Ls,Bs).

鍵項目位置定義(述語名,_項目名ならび) :-
    length(_項目名ならび,Len),
    for(1,N,Len),
    list_nth(N,_項目名ならび,_項目名),
    変数文字列の生成(Len,N,項目名,_項目変数文字列,_変数文字列),
    concat_atom(['鍵項目位置(',_項目名,述語名,'(',_変数文字列,')',
                              _項目変数文字列,')'],S),
    parse_atom(S,1,P,V),
    assertz_with_names(P,V),
    N = Len,!.

変数文字列の生成(N,Len,項目名,_項目変数文字列,_変数文字列) :-
    M is N - 1,
    length(L1,M),
    all(L1,'_'),
    M2 is Len - N,
    length(L2,M2),
    all(L2,'_'),
    atom_concat('_',項目名,_項目変数文字列),
    append(L1,[_項目変数文字列|L2],L),
    concat_atom(L,',',_変数文字列).

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


base64g(Atom,X) :-
    replace_all(Atom,' ','',Atom2),
    base64(X,Atom2) .

base64s(Atom,X) :-
    \+(var(Atom)),
    name2(Atom,L1),
    base64_2(L1,Y),
    concat_atom(Y,X) .

base64(Atom,X) :-
    \+(var(Atom)),
    atom_codes(Atom,L1),
    kjtoeuc(CodeList,L1),
    base64_2(CodeList,Y),
    concat_atom(Y,X),!.
base64(X,Atom) :-
    var(X),
    atom_chars(Atom,List),
    base64_1(Y,List),
    concat_atom(Y,Y2),
    atom_codes(Y2,Codes),
    kjtoeuc(Codes,Y3),
    atom_codes(X,Y3),!.

base64_1([],[]) :- !.
base64_1(X,[A,B,C,=]) :-
    base64_table(A1,A),
    base64_table(B1,B),
    base64_table(C1,C),
    append(A1,B1,L1),
    append(L1,C1,L),
    base64_a2b(Y,L),
    base64_1(Z,R),
    append(Y,Z,X).
base64_1(X,[A,B,=,=]) :-
    base64_table(A1,A),
    base64_table(B1,B),
    append(A1,B1,L),
    base64_a2b(Y,L),
    base64_1(Z,R),
    append(Y,Z,X).
base64_1(X,[A,B,C,D|R]) :-
    base64_table(A1,A),
    base64_table(B1,B),
    base64_table(C1,C),
    base64_table(D1,D),
    append(A1,B1,L1),
    append(L1,C1,L2),
    append(L2,D1,L),
    base64_a2b(Y,L),
    base64_1(Z,R),
    append(Y,Z,X).

base64_table([0,0,0,0,0,0],'A').
base64_table([0,0,0,0,0,1],'B').
base64_table([0,0,0,0,1,0],'C').
base64_table([0,0,0,0,1,1],'D').
base64_table([0,0,0,1,0,0],'E').
base64_table([0,0,0,1,0,1],'F').
base64_table([0,0,0,1,1,0],'G').
base64_table([0,0,0,1,1,1],'H').
base64_table([0,0,1,0,0,0],'I').
base64_table([0,0,1,0,0,1],'J').
base64_table([0,0,1,0,1,0],'K').
base64_table([0,0,1,0,1,1],'L').
base64_table([0,0,1,1,0,0],'M').
base64_table([0,0,1,1,0,1],'N').
base64_table([0,0,1,1,1,0],'O').
base64_table([0,0,1,1,1,1],'P').
base64_table([0,1,0,0,0,0],'Q').
base64_table([0,1,0,0,0,1],'R').
base64_table([0,1,0,0,1,0],'S').
base64_table([0,1,0,0,1,1],'T').
base64_table([0,1,0,1,0,0],'U').
base64_table([0,1,0,1,0,1],'V').
base64_table([0,1,0,1,1,0],'W').
base64_table([0,1,0,1,1,1],'X').
base64_table([0,1,1,0,0,0],'Y').
base64_table([0,1,1,0,0,1],'Z').
base64_table([0,1,1,0,1,0],a).
base64_table([0,1,1,0,1,1],b).
base64_table([0,1,1,1,0,0],c).
base64_table([0,1,1,1,0,1],d).
base64_table([0,1,1,1,1,0],e).
base64_table([0,1,1,1,1,1],f).
base64_table([1,0,0,0,0,0],g).
base64_table([1,0,0,0,0,1],h).
base64_table([1,0,0,0,1,0],i).
base64_table([1,0,0,0,1,1],j).
base64_table([1,0,0,1,0,0],k).
base64_table([1,0,0,1,0,1],l).
base64_table([1,0,0,1,1,0],m).
base64_table([1,0,0,1,1,1],n).
base64_table([1,0,1,0,0,0],o).
base64_table([1,0,1,0,0,1],p).
base64_table([1,0,1,0,1,0],q).
base64_table([1,0,1,0,1,1],r).
base64_table([1,0,1,1,0,0],s).
base64_table([1,0,1,1,0,1],t).
base64_table([1,0,1,1,1,0],u).
base64_table([1,0,1,1,1,1],v).
base64_table([1,1,0,0,0,0],w).
base64_table([1,1,0,0,0,1],x).
base64_table([1,1,0,0,1,0],y).
base64_table([1,1,0,0,1,1],z).
base64_table([1,1,0,1,0,0],'0').
base64_table([1,1,0,1,0,1],'1').
base64_table([1,1,0,1,1,0],'2').
base64_table([1,1,0,1,1,1],'3').
base64_table([1,1,1,0,0,0],'4').
base64_table([1,1,1,0,0,1],'5').
base64_table([1,1,1,0,1,0],'6').
base64_table([1,1,1,0,1,1],'7').
base64_table([1,1,1,1,0,0],'8').
base64_table([1,1,1,1,0,1],'9').
base64_table([1,1,1,1,1,0],+).
base64_table([1,1,1,1,1,1],/).
base64_table([A,B,C,D],X) :-
    base64_table([A,B,C,D,0,0],X).
base64_table([A,B],X) :-
    base64_table([A,B,0,0,0,0],X).

base64_a2b([],[]).
base64_a2b([Atom|R],[A,B,C,D,E,F,G,H|R2]) :-
    atob(Atom,[A,B,C,D,E,F,G,H]),
    base64_a2b(R,R2).

base64_2([],[]) :- !.
base64_2([A,B,C|R],X) :-
    base64_i2b([A,B,C],L),
    base64_3(L,Z),
    base64_2(R,R2),
    append(Z,R2,X),!.
base64_2([A,B],X) :-
    base64_i2b([A,B],L),
    base64_3(L,Z),
    append(Z,[=],X),!.
base64_2([Y],X) :-
    base64_i2b([Y],L),
    base64_3(L,Z),
    append(Z,[=,=],X),!.

base64_3([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X],[Z1,Z2,Z3,Z4]) :-
    base64_table([A,B,C,D,E,F],Z1),
    base64_table([G,H,I,J,K,L],Z2),
    base64_table([M,N,O,P,Q,R],Z3),
    base64_table([S,T,U,V,W,X],Z4),!.
base64_3([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],[Z1,Z2,Z3]) :-
    base64_table([A,B,C,D,E,F],Z1),
    base64_table([G,H,I,J,K,L],Z2),
    base64_table([M,N,O,P],Z3),!.
base64_3([A,B,C,D,E,F,G,H],[Z1,Z2]) :-
    base64_table([A,B,C,D,E,F],Z1),
    base64_table([G,H],Z2).

base64_i2b([],[]) :- !.
base64_i2b([X|R],[1,B,C,D,E,F,G,H|R2]) :-
    var(X),
    itob(X,[1,B,C,D,E,F,G,H]),
    base64_i2b(R,R2),!.
base64_i2b([X|R],[0,B,C,D,E,F,G,H|R2]) :-
    var(X),
    itob(U,[0,B,C,D,E,F,G,H]),
    X is U - 128,
    base64_i2b(R,R2),!.
base64_i2b([Code|R],[A,B,C,D,E,F,G,H|R2]) :-
    itob(Code,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,A,B,C,D,E,F,G,H]),
    base64_i2b(R,R2) .

name2(X,Y) :-
    atom(X),
    strlen(X,Len),
    findall(N,(for(1,M,Len) , char_code1(X,M,N1) , (N1 < 0 , N is N1 + 256 ; N1 >= 0 , N = N1)),Y),!.
name2(A,[N]) :-
    atomic(A),
    name(A,[N]),!.
name2(A,L) :-
    var(A),
    name21(L,L2),
    atom_codes(A,L2),!.

name21([],[]) :- !.
name21([N1,N2|R],[N|R2]) :-
    N1 > 127,
    N2 > 127,
    N is N1 * 256 + N2,
    name21(R,R2),!.
name21([N1,N2|R],[N|R2]) :-
    N1 > 127,
    N2 < 128,
    N is N1 * 256 + N2,
    name21(R,R2),!.
name21([N1|R],[N1|R2]) :-
    name21(R,R2).

itob(N,L) :-
    itob(N,[],L1),
    length(L1,Len),
    Len2 is 8 - Len,
    length(L2,Len2),
    all(L2,0),
    append(L2,L1,L).

itob(0,X,X) :- !.
itob(N,Y,X) :-
    M is N mod 2,
    N2 is N // 2,
    itob(N2,[M|Y],X).


'CRC-16'(L,BCC1,BCC2) :-
        'CRC16'(L,0xa001,0,CRC,BCC1,BCC2).

'CRC16-CCITT'(L,BCC1,BCC2) :-
        'CRC16'(L,0x8408,0,CRC,BCC1,BCC2).

'CRC16'([],_生成多項式,CRC,CRC,BCC1,BCC2) :-
        ビット列を反転した数(CRC,N),
        BCC1 is N // 256,
        BCC2 is N mod 256,!.
'CRC16'([N|R1],_生成多項式,CRC1,CRC,BCC1,BCC2) :-
        'CRC16_2'([_,_,_,_,_,_,_,_],_生成多項式,N,CRC1,CRC2),
        'CRC16'(R1,_生成多項式,CRC2,CRC,BCC1,BCC2).

'CRC16_2'([],_,_,CRC,CRC) :- !.
'CRC16_2'([_|Ln],_生成多項式,D,CRC1,CRC) :-
        'CRC16_3'(D,CRC1,Lsb,CRC3),
        'CRC16_4'(Lsb,_生成多項式,CRC3,CRC4),
        D3 is (D << 1) /\ 0x00ff,
        'CRC16_2'(Ln,_生成多項式,D3,CRC4,CRC).

'CRC16_3'(D,CRC1,Lsb,CRC3) :-
        N is (D >> 7) /\ 0xff,
        R is CRC1 /\ 1,
        Lsb is R # N,
        CRC2 is CRC1 >> 1,
        CRC3 is CRC2 /\ 0x7fff.

'CRC16_4'(Lsb,_生成多項式,CRC3,CRC4) :-
        \+(Lsb = 0),
        CRC4 is _生成多項式 # CRC3.
'CRC16_4'(Lsb,_生成多項式,CRC3,CRC4) :-
        Lsb = 0,
        CRC4 = CRC3.

% *** user: i2b / 3 ***
i2b(_ビット数,_整数表現,_二進数リスト) :-
        var(_ビット数),
        integer(_整数表現),
        i2b_2(_整数表現,[],_二進数リスト).
i2b(_ビット数,_整数表現,_二進数リスト) :-
        integer(_ビット数),
        integer(_整数表現),
        i2b_2(_整数表現,[],L2),
        length(_二進数リスト,_ビット数),
        append(L1,L2,_二進数リスト),
        L1 all 0,!.
i2b(_ビット数,_整数表現,_二進数リスト) :-
        var(_整数表現),
        length(_二進数リスト,_ビット数),
        i2b_3(_ビット数,_二進数リスト,_実数表現),
        _整数表現 is truncate(_実数表現).

% *** user: i2b_2 / 3 ***
i2b_2(0,L,L) :- !.
i2b_2(N,Y,X) :-
        N1 is N // 2,
        N2 is N mod 2,
        i2b_2(N1,[N2|Y],X).

% *** user: i2b_3 / 4 ***
i2b_3(N,N,[],0) :- !.
i2b_3(M,N,[I|R],X) :-
        M2 is M + 1,
        i2b_3(M2,N,R,Y),
        X is 2 ^ M + Y + I,!.

% *** user: i2b_3 / 3 ***
i2b_3(1,[I],I) :- !.
i2b_3(M,[I|R],X) :-
        M2 is M - 1,
        i2b_3(M2,R,Y),
        X is 2 ^ M2 * I + Y,!.

% *** user: i2b_3 / 2 ***
i2b_3([],0) :- !.
i2b_3([0|R],X) :-
        i2b_3(R,Y),
        X is Y * 2,!.
i2b_3([1|R],X) :-
        i2b_3(R,Y),
        X is Y * 2 + 1.


http://pc12.2ch.net/test/read.cgi/tech/1232627790/958 
# 【 課題 】テキストファイルから文字列5行を読み込み、別のテキストへ縦書きで書き出す 
# 【 形態 】1. Javaアプリケーション(main()で開始) 
# 【 期限 】7/14 am6:00 
# 【 Ver  】Eclipse Version: 3.4.2 
# 【 補足 】 
# あいう 
# かきく 
# さしす 
# 上記のようなテキストファイルを読み込み、 
# あかさ 
# いきし 
# うくす 
# のように別のテキストファイルに書き出す感じです。 

テキストファイルから文字列5行を読み込み、別のテキストへ縦書きで書き出す(InFile,OutFile) :-
    open(InFile,read,Input),
    open(OutFile,write,Output),
    findall(Chars,(for(1,N,5),get_line(InFile,_行),atom_chars(_行,Chars)),LL),
    max(Chars,Max),
    空白文字を付加して文字数一致させる(Max,LL,LL2),
    行列の転置(LL2,LL3),
    出力ファイルに書き出す(Output,LL3).

出力ファイルに書き出す(Output,[]) :- close(Output),!.
出力ファイルに書き出す(Output,[L|R]) :-
    concat_atom(L,S),
    write_formatted(Output,'%t\n',[S]),
    出力ファイルに書き出す(Output,R).

空白文字を付加して文字数を一致させる(Max,LL1,LL2) :-
    findall(L,(member(L1,LL1),length(L,Max),append(L1,L2,L),all(L2,' ')),LL2).

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


http://pc12.2ch.net/test/read.cgi/tech/1232627790/958 
# 【 課題 】テキストファイルから文字列5行を読み込み、別のテキストへ右縦書きで書き出す 
# 【 形態 】1. Javaアプリケーション(main()で開始) 
# 【 期限 】7/14 am6:00 
# 【 Ver  】Eclipse Version: 3.4.2 
# 【 補足 】 
# あいう 
# かきく 
# さしす 
# 上記のようなテキストファイルを読み込み、 
# さかあ 
# しきい 
# すくう 
# のように別のテキストファイルに書き出す感じです。 

テキストファイルから文字列5行を読み込み、別のテキストへ右縦書きで書き出す(InFile,OutFile) :-
    open(InFile,read,Input),
    open(OutFile,write,Output),
    findall(Chars,(for(1,N,5),get_line(InFile,_行),atom_chars(_行,Chars)),LL),
    findmax(Len,length(Chars,Len),Max),
    空白文字を付加して文字数一致させる(Max,LL,LL2),
    行列の転置(LL2,LL3),
    右書き用に反転して出力ファイルに書き出す(Output,LL3).

右書き用に反転して出力ファイルに書き出す(Output,[]) :- close(Output),!.
右書き用に反転して出力ファイルに書き出す(Output,[L|R]) :-
    reverse(L,L1),
    concat_atom(L1,S),
    write_formatted(Output,'%t\n',[S]),
    右書き用に反転して出力ファイルに書き出す(Output,R).

空白文字を付加して文字数を一致させる(Max,LL1,LL2) :-
    findall(L,(member(L1,LL1),length(L,Max),append(L1,L2,L),all(L2,' ')),LL2).

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


http://pc12.2ch.net/test/read.cgi/tech/1153585095/904
# [課題]  
# ・23本のマッチ棒からなる山があり,2人のプレーヤが山から交互にマッチ棒を
# 取り除く  
# ・一度に取ることのできるマッチ棒は1から3本  
# ・山を空にしたプレーヤが勝ち  
# 人間2人でこのゲームを行なうプログラムを作成せよ.  
# 
# プログラムでは各プレーヤの手がルールに反していないかどうかのチェックと,
# 勝負がついたかどうかのチェックを行なうこと。 
# また,最初に山にある本数と,各回に取ることができる最大の本数をプログラムの
# 最初に変数にセットしておき,そこを変えるだけで本数の変化に対応できるような
# プログラムにすること。  

プレーヤ(1,山下).
プレーヤ(2,太田).
プレーヤのデバイス(1,入力,'/dev/tty1').
プレーヤのデバイス(2,入力,'/dev/tty2').
プレーヤのデバイス(1,出力,'/var/tmp/player1').
プレーヤのデバイス(2,出力,'/var/tmp/player2').

マッチ棒の山([_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_]).

マッチ棒('|').

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

マッチ棒の山崩し :-
    プレーヤ(1,_プレーヤ1),
    プレーヤ(2,_プレーヤ2),
    マッチ棒の山(L),
    デバイスを開く(Instream1,Instream2,Outstream1,Outstream2),
    ゲームの案内(Outstream1,Outstream2),
    マッチ棒の山崩し(_プレーヤ1,_プレーヤ2,Instream1,Instream2,Outstream1,Outstream2,L),
    デバイスを閉じる(Insteam1,Instream2,Outstream1,Outstream2).

マッチ棒の山崩し(_,_プレーヤ,_,_,OutstreamA,OutstreamB,[]) :-
    concat_atom([_プレーヤ,さんの勝ちです,'\n'],S),
    同報(OutstreamA,OutstreamB,S),!.
マッチ棒の山崩し(_プレーヤA,_プレーヤB,InstreamA,InstreamB,OutstreamA,OutstreamB,L) :-
    取り棒の案内(_マッチ棒,L,_取り棒の案内),
    write_formatted(OutstreamA,'君の番だよ( %t ) : ',[_取り棒の案内]),
    マッチ棒を取る(InstreamA,OutstreamA,L,L1,L2),
    マッチ棒の山の変化を同報する(OutstreamA,OutstreamB,L,L1,L2),
    マッチ棒の山崩し(_プレーヤB,_プレーヤA,InstreamB,InstreamA,OutstreamB,OutstreamA,L2),!.

マッチ棒を取る(Instream,_,L,L1,L2) :-
    get_line(Instream,S),
    変数ならびに変換(S,L1),
    取ったマッチ棒の診断(L,L1,L2),!.
マッチ棒を取る(Instream,Outstream,L,L1,L2) :-
    マッチ棒を取る(Instream,Outstream,L,L1,L2). 

取ったマッチ棒の診断(L,L1,L2) :-
    append(L1,L2,L2),!.
取ったマッチ棒の診断(L,L1,L2) :-
    取り棒の案内(L,_取り棒の案内),    
    write(Outstream,'入力形式が正しくありません。\n'),
    write(Outstream,'(%t) : ',[_取り棒の案内]),
    fail.

変数ならびに変換(S,L) :-
     マッチ棒(_マッチ棒),
     変数ならびに変換(_マッチ棒,Chars,L),
     atom_chars(S,Chars).

変数ならびに変換(_マッチ棒,[_マッチ棒],[_]).
変数ならびに変換(_マッチ棒,[_マッチ棒|R1],[_|R2]) :-
    変数ならびに変換(_マッチ棒,R1,R2).    

取り棒の案内(L,_取り棒の案内) :-
    マッチ棒(_マッチ棒),
    取り棒の案内(_マッチ棒,L,_取り棒の案内).

取り棒の案内(_マッチ棒,[_],_マッチ棒).
取り棒の案内(_マッチ棒,[_,_],S) :-
    concat_atom([_マッチ棒,' or ',_マッチ棒],S).
取り棒の案内(_マッチ棒,[_,_,_|_],S) :-
    concat_atom([_マッチ棒,' or ',_マッチ棒,' or ',_マッチ棒],S).

マッチ棒の山の変化を同報する(Outstream1,Outstream2,L0,L1,L) :-
    マッチ棒(_マッチ棒),
    all(L0,_マッチ棒),concat_atom(L0,' ',S0),
    all(L1,_マッチ棒),concat_atom(L1,' ',S1),
    all(L,_マッチ棒),concat_atom(L,' ',S),
    concat_atom([S1,'\n','↑\n',S,'\n現在の山は ',S,'\n'],S2),
    同報(Outstream1,Outstream2,S2),
    fail.
マッチ棒の山の変化を同報する(_,_,_,_,_).

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

ゲームの案内(Outstream1,Outstream2) :-
    同報(Outstream1,Outstream2,'マッチの本数の入力は\n1本 -> |<改行>\n'),
    同報(Outstream1,Outstream2,'2本 -> ||<改行>\n'),
    同報(Outstream1,Outstream2,'3本 -> |||<改行> という表現でお願いします\n').

同報(Outsteam1,Outstream2,_項) :-
    write(Outstream1,_項),
    write(Outstream2,_項),!.

デバイスを開く(Instream1,Instream2,Outstream1,Outstream2) :-
    プレーヤのデバイス(1,入力,Indevice1),
    プレーヤのデバイス(2,入力,Indevice2),
    プレーヤのデバイス(1,出力,Outdevice1),
    プレーヤのデバイス(2,出力,Outdevice2),
    open(Indevice1,read,Instream1),
    open(Outdevice1,append,Outstream1),
    open(Indevice2,read,Instream2),
    open(Outdevice2,append,Outstream2),!.

デバイスを閉じる(Instream1,Instream2,Outstream1,Outstream2) :-
    close(Insteam1),
    close(Outstream1),
    close(Instream2),
    close(Outstream2),!.

マッチ棒の山の初期状態の設定(N) :-
    integer(N),
    retract(マッチ棒の山(_)),
    length(L,N),
    asserta(マッチ棒の山(L)).

プレーヤの入出力デバイスの設定(_プレーヤ1の入力デバイス,_プレーヤ2の入力デバイス,_プレーヤ1の出力デバイス,_プレーヤ2の出力デバイス) :-
    abolish(プレーヤのデバイス/3),
    assertz(プレーヤのデバイス(1,入力,_プレーヤ1の入力デバイス)),
    assertz(プレーヤのデバイス(2,入力,_プレーヤ2の入力デバイス)),
    assertz(プレーヤのデバイス(1,出力,_プレーヤ1の出力デバイス)),
    assertz(プレーヤのデバイス(2,出力,_プレーヤ2の出力デバイス)),!.

プレーヤの設定(_プレーヤ1,_プレーヤ2) :-
    abolish(プレーヤ/2),
    assertz(プレーヤ(1,_プレーヤ1)),
    assertz(プレーヤ(2,_プレーヤ2)),!.

get_line(Instream,X)
  :-
    get_char(Instream,C),
    get_line_3(Instream,C,Chars),
    atom_chars(X,Chars).

get_line_3(_,'\n',[]) :- !.
get_line_3(Instream,end_of_file,[e,n,d,'_',o,f,'_',f,i,l,e]) :- !.
get_line_3(Instream,C,[C|R]) :-
    get_char(Instream,C2),
    get_line_3(Instream,C2,R).


http://pc12.2ch.net/test/read.cgi/tech/1247438792/457
# [1] 授業単元 C++ 
# 
# [2] 問題文(含コード&リンク)  
# テキストファイルの中のタブコードをそれぞれ、空白N個に置き換えて、 
# 新たなファイルに書き出しなさい。ただし、N≧0とする。 
# コマンドパラメーター:入力ファイル名、出力ファイル名、N 
# 
# <解答例> 
# Hello( )Bye←入力ファイル 
# N=3の場合 
# Hello(   )Bye←出力ファイル 

t554(_入力ファイル,_出力ファイル,_空白文字数) :-
    length(L,_空白文字数),
    all(L,' '),
    get_chars(_入力ファイル,Chars),
    replace_chars(Chars,['\t'],L,Chars2),
    put_chars(_出力ファイル,Chars2).

replace_chars([],_,_,[]) :- !.
replace_chars(L1,L2,L3,L4) :-
    append(L2,R1,L1),
    replace_chars(R1,L2,L3,L5),
    append(L3,L5,L4),!.
replace_chars([A|R1],L2,L3,[A|R4]) :-
    replace_chars(R1,L2,L3,R4).

get_chars(File,L) :-
    open(File,read,Input),
    get_char(Input,X),
    get_chars(Input,X,L),
    close(Input),!.

get_chars(Input,end_of_file,[]) :- !.
get_chars(Input,X,[X|R]) :-
    get_char(Input,Y),
    get_chars(Input,Y,R) .

put_chars(F,L) :-
    open(F,write,Output),
    stream_put_chars(Output,L),
    close(Output),!.

stream_put_chars(_,[]) :- !.
stream_put_chars(Stream,[Char|R]) :-
    put_char(Stream,Char),
    stream_put_chars(Stream,R),!.

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


# [1] 授業単元: プログラミング
# [2]問題文:以下の2つの構造体を用い,sample_data2.txt を単方向連結リストに
# 保存するプログラム extra8 を作成せよ.item_list 中の item は各行中の数値を
# 保持し,t_list 中の itemset は1行分のデータを保持するものとする.
# struct item_list {
# int item;
# struct item_list *next;
# };
# struct t_list {
# struct item_list itemset;
# struct t_list *next
# };
# ソースファイルの名前は extra8.c とする.また,extra8.c には,
# 生成した単方向連結リストの内容を標準出力に出力する関数 print_tlist を
# 含むものとし,以下の実行例のように print_tlist により各行の内容を出力
# するものとする.
# なお,入力ファイル名はコマンドライン引数で指定するものとし,入力ファイルが
# オープンできなかった場合の処理も含めること.また,プログラム自身を除く
# 引数の数が0個,もしくは2個以上の場合は,何もせず適切なメッセージを出力して
# 終了するものとする.
# (実行例1)
# > .\extra8 sample_data2.txt
# Itemset: 1,3,9,13,23,25,34,36
# Itemset: 2,3,9,14,23,26,34,36,39,40,52,55,59

extra8 :-
    ユーザパラメータの取得(_ファイル名),
    get_lines(_ファイル名,Lines),
    findall(Item_list,(member(Line,Lines),split(Line,[','],Item_list)),T_list),
    assertz(t_list(T_list)).

print_tlist :-
    t_list(T_list),
    member(Item_list,T_list),
    print_tlist_format(Item_list,Format),
    write_formatted(Format,Item_list),
    fail.
print_tlist.

print_tlist_format(Item_list,Format) :-
    length(Item_list,Len),
    length(L,Len),
    all(L,'%t'),
    concat_atom(L,',',S),
    concat_atom(['Items : ,S,'\n'],Format),!.

ユーザパラメータの取得(_ファイル名) :-
    user_parameters([_ファイル名]),!.
ユーザパラメータの取得(_) :-
    error_tell(Output),
    write(Output,'パラメータで適切なファイル名が与えられませんでした\n'),
    errot_told(Output).

http://pc12.2ch.net/test/read.cgi/tech/1247438792/574 
# [1] 授業単元:プログラミング序論演習 
# [2] 問題文(含コード&リンク): CUI上で動くメーラーを作れ 

:- op(850,fx,rm).
rm(File) :-
        concat_atom(['rm -f ',File],S),
        system(S),!.

% *** user: mail / 1 ***
mail(max) :-
        'メール数の確認'(N),
        mail(N),!.
mail(0) :-
        reconsult('listing/最終メール番号#1.pro'),
        'メール数の確認'(N),
        '最終メール番号'(N2),
        M is N2 - N,
        (
                M < 0,
                mail(M),
                retract('最終メール番号'(_)),
                asserta('最終メール番号'(N)),
                '最終メール番号の保存'
        ;
                M = 0
        ;
                M > 0,
                retract('最終メール番号'(_)),
                asserta('最終メール番号'(N)),
                '最終メール番号の保存'
        ),
        !.
mail(0) :-
        !.
mail(N) :-
        N < 0,
        !,
        'メール数の確認'(Max),
        rm tempmsg,
        abolish('受信先アドレス' / 1),
        reconsult('listing/最終メール番号#1.pro'),
        for(-1,M,N),
        open(tempmsg,append,Output),
        M2 is Max + M + 1,
        write(Output,'\n\n'),
        '返信入力表示'(Output,M2),
        close(Output),
        M = N,
        exists(tempmsg,read),
        cat tempmsg,
        '最終メール番号の保存',
        !.
mail(N) :-
        N > 0,
        rm tempmsg,
        rm tempmsg2,
        rm tempmsg3,
        myhostname(Myhostname),
        'メールを読む'(N),
        ! 'cat tempmsg | nkf -We',
        write('\n'),
        !.
mail(N) :-
        \+(N = 0),
        exists(tempmsg,read),
        ! 'cat tempmsg | nkf -We',
        write('\n'),
        !.

% *** user: mail10 / 1 ***
mail10(N) :-
        integer(N),
        N < 0,
        'メールの数を調べる'(Max),
        S is Max + N + 1,
        for(S,M,Max),
        write_formatted('\n#%t\n',[M]),
        mail10(M),
        M = Max,
        !.
mail10(S - E) :-
        for(S,N,E),
        write_formatted('\n#%t\n',[N]),
        mail10(N),
        N = E,
        !.
mail10(N) :-
        integer(N),
        \+(N = 0),
        N > 0,
        rm tempmsg,
        rm tempmsg2,
        rm tempmsg3,
        myhostname(Myhostname),
        'メールを読む'(N),
        shs('cat tempmsg | nkf -We',L),
        member(A,L,R2),
        subatomic(A,1,7,'Status:'),
        for(1,M,10),
        list_nth(M,R2,X),
        write_formatted('%t\n',[X]),
        M = 10,
        !.

% *** user: 'メール数の確認' / 2 ***
'メール数の確認'(_メールボックス,_メール数) :-
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        repeat,
        get_line(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メール数),
        \+(_メール数 = 'lock.'),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メール数の確認' / 1 ***
'メール数の確認'(_メール数) :-
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        repeat,
        stream_read(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メール数),
        \+(_メール数 = 'lock.'),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メールの数を調べる' / 1 ***
'メールの数を調べる'(_メールの数) :-
        'メールサーバ'(_メールサーバ),
        'クライアント通信確立'(_メールサーバ,110,_差し込み口),
        (
                error_protect('私書箱'(_私書箱),fail)
        ;
                \+(error_protect('私書箱'(_),fail)),
                _私書箱 = takao
        ),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        get_line(_入力,A),
        write_formatted(_出力,'USER %t\r\n',[_私書箱]),
        flush_output(_出力),
        'メールパスワードの送付'(_メールボックス,_入力,_出力),
        repeat,
        get_line(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メールの数),
        \+(_メールの数 = 'lock.'),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        ! .

% *** user: 'メールを読む' / 6 ***
'メールを読む'(_メールボックス,N,A,B,C,X) :-
        integer(N),
        N > 0,
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_メールボックス,_入力,_出力),
        'メールパスワードの送付'(_メールボックス,_入力,_出力),
        get_line(_入力,C),
        write_formatted(_出力,'RETR %t\r\n',[N]),
        flush_output(_出力),
        pop3_message_get(_入力,X),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        get_line(_入力,D),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.


% *** user: 'メールを読む' / 5 ***
'メールを読む'(L,A,B,C,X) :-
        list(L),
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        (
                error_protect('私書箱'(_私書箱),fail)
        ;
                \+(error_protect('私書箱'(_私書箱),fail)),
                _私書箱 = default
        ),
        open(_差し込み口,read,_入力,A),
        open(_差し込み口,write,_出力,B),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        get_line(_入力,C),
        (
                member(N,L),
                write_formatted(_出力,'RETR %t\r\n',[N]),
                flush_output(_出力),
                pop3_message_get(_入力,X),
                write(_出力,'QUIT\r\n'),
                flush_output(_出力),
                fail
        ;
                true
        ),
        get_line(_入力,D),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

'メールを読む'(N,A,B,C,X) :-
        integer(N),
        N > 0,
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        (
                error_protect('私書箱'(_私書箱),fail)
        ;
                \+(error_protect('私書箱'(_私書箱),fail)),
                _私書箱 = default
        ),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        pop3_message_get(_入力,X),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        get_line(_入力,D),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メールを読む' / 2 ***
'メールを読む'(N,X) :-
        var(X),
        integer(N),
        N =< 0,
        'メール数の確認'(_メール数),
        M is _メール数 + N + 1,
        'メールを読む'(M,_,_,_,X),
        concat_atom(X,'\n',_文),
        open(tempmsg,append,_出力2),
        write_formatted(_出力2,'%t',[_文]),
        flush_output(_出力2),
        close(_出力2),
        !.
'メールを読む'(N,FILE) :-
        \+(var(FILE)),
        integer(N),
        N =< 0,
        'メールサーバアドレス'(_メールサーバアドレス),
        'クライアント通信確立'(_メールサーバアドレス,110,_差し込み口),
        (
                FILE = '',
                tmpnam(FILE_1)
        ;
                \+(FILE = ''),
                FILE = FILE_1
        ),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールを読むの一'(N,FILE_1,_入力,_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メールを読むの一' / 4 ***
'メールを読むの一'(N,FILE,_入力,_出力) :-
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        'メール数の取得'(_入力,_メール数),
        _限界数 is _メール数 + N + 1,
        'メールの取得'(_入力,_出力,FILE,_メール数,_限界数),
        'メールサーバを切り離す'(_入力,_出力),
        !.

% *** user: 'メールの取得' / 5 ***
'メールの取得'(_入力,_出力,FILE,Max,M) :-
        open(FILE,append,_出力2),
        for(Max,U,M),
        write_formatted(_出力,'RETR %t\r\n',[U]),
        flush_output(_出力),
        pop3_message_rw(_入力,_出力2),
        write(_出力2,'.\n'),
        U = M,
        close(_出力2),
        !.

% *** user: pop3_message_rw / 2 ***
pop3_message_rw(Input,Output) :-
        repeat,
        get_line(Input,S),
        replace_all(S,'\r','',S2),
        (
                subatomic(S,1,1,'.')
        ;
                S = end_of_file
        ;
                S2 = [],
                write(Output,'\n'),
                fail
        ;
                \+(S2 = []),
                write_formatted(Output,'%t\n',[S2]),
                fail
        ),!.

% *** user: pop3_message_get / 2 ***
pop3_message_get(A,B) :-
        findall(E,(repeat ,
                           get_line(A,C) ,
                           replace_all(C,'\r','',D) ,
                           (sub_atom(C,0,1,'.') , (!) , fail ;
                                C = end_of_file , (!) , fail ;
                                D = [] , E = '\n' ;
                                not D = [] , E = D)),B),!.

% *** user: 'メール数の取得' / 2 ***
'メール数の取得'(_入力,_メール数) :-
        get_line(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メール数).

% *** user: 'メールパスワードの送付' / 3 ***
'メールパスワードの送付'(_メールボックス,_入力,_出力,B) :-
        メールパスワード(_メールボックス,_メールパスワード),
        get_line(_入力,B),
        write_formatted(_出力,'PASS %t\r\n',[_メールパスワード]),
        flush_output(_出力).

% *** user: 'メールパスワードの送付' / 2 ***
'メールパスワードの送付'(_入力,_出力) :-
        メールパスワード(_メールパスワード),
        get_line(_入力,B),
        write_formatted(_出力,'PASS %t\r\n',[_メールパスワード]),
        flush_output(_出力).

% *** user: 'メールユーザ名の送付' / 3 ***
'メールユーザ名の送付'(_メールボックス,_入力,_出力,A) :-
        メールユーザ(_メールボックス,_メールユーザ),
        get_line(_入力,A),
        write_formatted(_出力,'USER %t\r\n',[_メールボックス]),
        flush_output(_出力).

'メールユーザ名の送付'(_入力,_出力) :-
        メールユーザ(_メールユーザ),
        get_line(_入力,A),
        write_formatted(_出力,'USER %t\r\n',[_メールユーザ]),
        flush_output(_出力).

% *** user: 'メールサーバを切り離す' / 2 ***
'メールサーバを切り離す'(_入力,_出力) :-
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        get_line(_入力,D),!.

smtp_iso(From,To,Subject,'文'(_文)) :-
        tmpnam(TMPNAM),
        tmpnam(TMPNAM2),
        open(TMPNAM,write,Output),
        write_formatted(Output,'%t\n',[_文]),
        close(Output),
        concat(['nkf -e -j ',TMPNAM,' >',TMPNAM2],S),
        system(S),
        smtp_iso(Input,Output,From,To,Subject,TMPNAM2,_診断),
        unlink(TMPNAM),
        unlink(TMPNAM2),!.
smtp_iso(From,To,Subject,File) :-
        \+(list(File)),
        tmpnam(TMPFILE),
        concat(['nkf -e -j ',File,' >',TMPFILE],S1),
        base64(Subject,Subject64),
        sprintf('=?iso-2022-jp?B?%t?=',[Subject64],MimeSubject),
        smtp_server(Host),
        smtp_iso(Host,From,To,MimeSubject,TMPFILE,_診断),
        unlink(TMPFILE),!.

smtp_iso(From,To,Subject,Files) :-
        list(Files),
        smtp_plus(Files,File1,Boundary),
        tmpnam(TMPFILE),
        concat(['cat ',File1,' | nkf -e -j >',TMPFILE],S1),
        base64(Subject,Subject64),
        sprintf('=?iso-2022-jp?B?%t?=',[Subject64],MimeSubject),
        smtp_server(Host),
        stmp_iso(Host,From,To,MimeSubject,TMPFILE,Boundary,_診断),!.

% *** user: smtp_iso / 2 ***
smtp_iso(To,(?- _質問)) :-
        tmpnam(TMPNAM),
        tell(TMPNAM),
        write_formatted('%q.\n',[(?- _質問)]),
        told,
        smtp_iso(To,'prolog@takao.ozaki.name','質問',TMPNAM),
        ! .

% *** user: smtp_iso / 6 ***
smtp_iso(_送信元,_送信先,MimeSubject,File,Data,_診断) :-
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,38,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_メールボックス,_入力,_出力),
        'メールパスワードの送付'(_メールボックス,_入力,_出力),
        send_helo(Input,Output,Domain),
        send_from_to(Input,Output,_送信元,_送信先),
        send_data(Input,Output,Subject,_送信元,_送信先,Data),
        send_quit(Input,Output),
        shutdown(_差し込み口),!.

send_helo(Input,Output,Domain) :-
        write_formatted(Output,'HELO %t\r\n',[Domain]),
        read(Input,_),
        write_formatted(Output,'EHLO %t\r\n',[Domain]),
        read(Input,_),!.

send_from_to(Input,Output,From,To) :-
        write_formatted(Output,'MAIL FROM: %t\r\n',[From]),
        stream_read(Input,_),
        write_formatted(Output,'RCPT TO: %t\r\n',[To]),
        stream_read(Input,_),!.

send_data(Input,Output,Subject,From,To,Data) :-
        write_formatted('DATA\r\n',[]),
        stream_read(Input,_),
        write_formatted(Output,'Subject: %t\r\nFrom: %t\r\nTo: %t\r\n\r\n',[Subject,From,To]),
        write_formatted(Output,'%t',[Data]),
        get_line(Input,_),!.

send_quit(Input,Output) :-
        write_formatted(Output,'QUIT\r\n'),
        get_line(Input,_),!.

% *** user: smtp_plus / 3 ***
smtp_plus(FileList,File,Boundary) :-
        FileList = [File1|R],
        tmpnam(A1),
        tmpnam(A2),
        tmpnam(A3),
        Boundary = '------------000402050407020604050408',
        smtp_plus_base64_encode(R,FileList2),
        tmpnam(File),
        tell(File),
        write('This is a multi-part message in MIME format.\n'),
        smtp_plus_1(Boundary,File1),
        smtp_plus_2(Boundary,FileList2,R),
        told,!.

% *** user: smtp_plus_1 / 2 ***
smtp_plus_1(Boundary,File) :-
        write_formatted('--%t\n',[Boundary]),
        write('Content-Type: text/plain; charset=EUC-JP\n'),
        write('Content-Transfer-Encoding: 8bit\n\n'),
        open(File,read,Fp),
        repeat,
        get_code(Fp,X),
        (
                X = -1
        ;
                name(Y,[X]),
                write_formatted('%t',[Y]),
                fail
        ),
        write('\n'),
        write('\n'),
        close(Fp),!.

% *** user: smtp_plus_2 / 3 ***
smtp_plus_2(Boundary,[],_) :-
        write_formatted('\n--%t--\n',[Boundary]),
        write('.\n\n'),!.
smtp_plus_2(Boundary,[File|R],[File_1|R2]) :-
        smtp_file_suffix(File,Suffix),
        smtp_file_mime(Suffix,Mime),
        write_formatted('\n--%t\n',[Boundary]),
        write_formatted('Content-Type: %t;\n',[Mime]),
        write_formatted(' name="%t"\n',[File_1]),
        write('Content-Transfer-Encoding: base64\n'),
        write('Content-Disposition: inline;\n'),
        write_formatted(' filename="%t"\n\n',[File_1]),
        open(File,read,Fp),
        repeat,
        get_code(Fp,X),
        (
                X = -1
        ;
                name(Y,[X]),
                write_formatted('%t',[Y]),
                fail
        ),
        close(Fp),
        smtp_plus_2(Boundary,R,R2).

% *** user: smtp_plus_2 / 2 ***
smtp_plus_2(_,[]) :-
        write('.\n\n'),!.
smtp_plus_2(Boundary,[File|R]) :-
        smtp_file_suffix(File,Suffix),
        smtp_file_mime(Suffix,Mime),
        write_formatted('--%t\n',[Boundary]),
        write_formatted('Content-Type: %t;\n',[Mime]),
        write_formatted(' name="%t"\n',[File]),
        write('Content-Transfer-Encoding: base64\n'),
        write('Content-Disposition: inline;\n'),
        write_formatted(' filename="%t"\n\n',[File]),
        open(File,read,Fp),
        repeat,
        get_code(Fp,X),
        (
                X = -1
        ;
                name(Y,[X]),
                write_formatted('%t',[Y]),
                fail
        ),
        close(Fp),
        write_formatted('\n--%t--\n',[Boundary]),
        smtp_plus_2(Boundary,R).

% *** user: smtp_plus / 2 ***
smtp_plus(FileList,File) :-
        FileList = [File1|R],
        tmpnam(A1),
        tmpnam(A2),
        tmpnam(A3),
        concat([--------------------,A1,A2,A3],AX),
        replace_all(AX,'/tmp/','',Boundary),
        smtp_plus_base64_encode(R,FileList2),
        tmpnam(File),
        tell(File),
        write('Content-Type: multipart/mixed;\n'),
        write_formatted(' boundary="%t"\n\n',[Boundary]),
        write('This is multi-part message in MIME format.\n'),
        smtp_plus_1(Boundary,File1),
        smtp_plus_2(Boundary,FileList2),
        told,
        !.

% *** user: smtp_file_mime / 2 ***
smtp_file_mime(jpg,'image/jpeg') :- !.
smtp_file_mime(jpeg,'image/jpeg') :- !.
smtp_file_mime(txt,'text/plain') :- !.
smtp_file_mime(xls,xls) :- !.
smtp_file_mime(csv,csv) :- !.
smtp_file_mime(ps,'application/postscript') :- !.
smtp_file_mime(pdf,'application/postscript') :- !.
smtp_file_mime(_,'text/plain') :- !.

% *** user: smtp_file_suffix / 2 ***
smtp_file_suffix(File,Suffix) :-
        decompcons(File,L),
        (
                smtp_file_suffix_2(L,L2),
                concat(L2,Suffix)
        ;
                \+(smtp_file_suffix_2(L,_)),
                Suffix = txt
        ),!.

% *** user: smtp_file_suffix_2 / 2 ***
smtp_file_suffix_2(['.'|R],R) :- !.
smtp_file_suffix_2([_|R1],R2) :-
        smtp_file_suffix_2(R1,R2).

% *** user: smtp_plus_base64_encode / 2 ***
smtp_plus_base64_encode([],[]) :-!.
smtp_plus_base64_encode([File1|R1],[File2|R2]) :-
        base64_file_encode(File1,File2),
        smtp_plus_base64_encode(R1,R2).

% *** user: 'クライアント通信確立' / 3 ***
'クライアント通信確立'(_ホスト,_サービス,_差し込み口) :-
        '定数'(_サービス),
        !,
        net_service(_サービス,tcp,_舫),
        socket(internet,stream,_差し込み口),
        host_addr(_ホスト,Addr),
        socket_connect(_差し込み口,Addr : _舫).
'クライアント通信確立'(_ホスト,_舫,_差し込み口) :-
        '整数'(_舫),
        !,
        socket(internet,stream,_差し込み口),
        socket_connect(_差し込み口,_ホスト : _舫).

% *** user: get_line / 2 ***
get_line(Stream,S) :-
        error_protect(get_code(Stream,X_4),X_4 = -1),
        get_line_1(Stream,X_4,L_4,[]),
        atom_codes(S,L_4),
        ! .

get_line_1(Stream,10,[],[]) :- !.
get_line_1(Stream,10,L,L2) :-
        !,
        reverse(L2,L).
get_line_1(Stream,10,L_4,[13|L1_4]) :-
        !,
        reverse(L1_4,L_4).
get_line_1(Stream,31,L_4,L1_4) :-
        !,
        reverse(L1_4,L_4).
get_line_1(Stream,-1,L,[A|L1]) :-
        reverse([A|L1],L).
get_line_1(Stream,-1,[101,110,100,95,111,102,95,102,105,108,101],L2) :-
        !.
get_line_1(Stream,X_4,L_4,L1_4) :-
        error_protect(get_code(Stream,Y_4),Y_4 = -1),
        !,
        get_line_1(Stream,Y_4,L_4,[X_4|L1_4]).

base64g(Atom,X) :-
        replace_all(Atom,' ','',Atom2),
        base64(X,Atom2) .

base64s(Atom,X) :-
        \+(var(Atom)),
        name2(Atom,L1),
        base64_2(L1,Y),
        concat_atom(Y,X) .

base64(Atom,X) :-
        \+(var(Atom)),
        atom_codes(Atom,L1),
        kjtoeuc(CodeList,L1),
        base64_2(CodeList,Y),
        concat_atom(Y,X),!.
base64(X,Atom) :-
        var(X),
        atom_chars(Atom,List),
        base64_1(Y,List),
        concat_atom(Y,Y2),
        atom_codes(Y2,Codes),
        kjtoeuc(Codes,Y3),
        atom_codes(X,Y3),!.

base64_1([],[]) :- !.
base64_1(X,[A,B,C,=]) :-
        base64_table(A1,A),
        base64_table(B1,B),
        base64_table(C1,C),
        append(A1,B1,L1),
        append(L1,C1,L),
        base64_a2b(Y,L),
        base64_1(Z,R),
        append(Y,Z,X).
base64_1(X,[A,B,=,=]) :-
        base64_table(A1,A),
        base64_table(B1,B),
        append(A1,B1,L),
        base64_a2b(Y,L),
        base64_1(Z,R),
        append(Y,Z,X).
base64_1(X,[A,B,C,D|R]) :-
        base64_table(A1,A),
        base64_table(B1,B),
        base64_table(C1,C),
        base64_table(D1,D),
        append(A1,B1,L1),
        append(L1,C1,L2),
        append(L2,D1,L),
        base64_a2b(Y,L),
        base64_1(Z,R),
        append(Y,Z,X).

base64_table([0,0,0,0,0,0],'A').
base64_table([0,0,0,0,0,1],'B').
base64_table([0,0,0,0,1,0],'C').
base64_table([0,0,0,0,1,1],'D').
base64_table([0,0,0,1,0,0],'E').
base64_table([0,0,0,1,0,1],'F').
base64_table([0,0,0,1,1,0],'G').
base64_table([0,0,0,1,1,1],'H').
base64_table([0,0,1,0,0,0],'I').
base64_table([0,0,1,0,0,1],'J').
base64_table([0,0,1,0,1,0],'K').
base64_table([0,0,1,0,1,1],'L').
base64_table([0,0,1,1,0,0],'M').
base64_table([0,0,1,1,0,1],'N').
base64_table([0,0,1,1,1,0],'O').
base64_table([0,0,1,1,1,1],'P').
base64_table([0,1,0,0,0,0],'Q').
base64_table([0,1,0,0,0,1],'R').
base64_table([0,1,0,0,1,0],'S').
base64_table([0,1,0,0,1,1],'T').
base64_table([0,1,0,1,0,0],'U').
base64_table([0,1,0,1,0,1],'V').
base64_table([0,1,0,1,1,0],'W').
base64_table([0,1,0,1,1,1],'X').
base64_table([0,1,1,0,0,0],'Y').
base64_table([0,1,1,0,0,1],'Z').
base64_table([0,1,1,0,1,0],a).
base64_table([0,1,1,0,1,1],b).
base64_table([0,1,1,1,0,0],c).
base64_table([0,1,1,1,0,1],d).
base64_table([0,1,1,1,1,0],e).
base64_table([0,1,1,1,1,1],f).
base64_table([1,0,0,0,0,0],g).
base64_table([1,0,0,0,0,1],h).
base64_table([1,0,0,0,1,0],i).
base64_table([1,0,0,0,1,1],j).
base64_table([1,0,0,1,0,0],k).
base64_table([1,0,0,1,0,1],l).
base64_table([1,0,0,1,1,0],m).
base64_table([1,0,0,1,1,1],n).
base64_table([1,0,1,0,0,0],o).
base64_table([1,0,1,0,0,1],p).
base64_table([1,0,1,0,1,0],q).
base64_table([1,0,1,0,1,1],r).
base64_table([1,0,1,1,0,0],s).
base64_table([1,0,1,1,0,1],t).
base64_table([1,0,1,1,1,0],u).
base64_table([1,0,1,1,1,1],v).
base64_table([1,1,0,0,0,0],w).
base64_table([1,1,0,0,0,1],x).
base64_table([1,1,0,0,1,0],y).
base64_table([1,1,0,0,1,1],z).
base64_table([1,1,0,1,0,0],'0').
base64_table([1,1,0,1,0,1],'1').
base64_table([1,1,0,1,1,0],'2').
base64_table([1,1,0,1,1,1],'3').
base64_table([1,1,1,0,0,0],'4').
base64_table([1,1,1,0,0,1],'5').
base64_table([1,1,1,0,1,0],'6').
base64_table([1,1,1,0,1,1],'7').
base64_table([1,1,1,1,0,0],'8').
base64_table([1,1,1,1,0,1],'9').
base64_table([1,1,1,1,1,0],+).
base64_table([1,1,1,1,1,1],/).
base64_table([A,B,C,D],X) :-
        base64_table([A,B,C,D,0,0],X).
base64_table([A,B],X) :-
        base64_table([A,B,0,0,0,0],X).

base64_a2b([],[]).
base64_a2b([Atom|R],[A,B,C,D,E,F,G,H|R2]) :-
        atob(Atom,[A,B,C,D,E,F,G,H]),
        base64_a2b(R,R2).

base64_2([],[]) :- !.
base64_2([A,B,C|R],X) :-
        base64_i2b([A,B,C],L),
        base64_3(L,Z),
        base64_2(R,R2),
        append(Z,R2,X),!.
base64_2([A,B],X) :-
        base64_i2b([A,B],L),
        base64_3(L,Z),
        append(Z,[=],X),!.
base64_2([Y],X) :-
        base64_i2b([Y],L),
        base64_3(L,Z),
        append(Z,[=,=],X),!.

base64_3([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X],[Z1,Z2,Z3,Z4]) :-
        base64_table([A,B,C,D,E,F],Z1),
        base64_table([G,H,I,J,K,L],Z2),
        base64_table([M,N,O,P,Q,R],Z3),
        base64_table([S,T,U,V,W,X],Z4),!.
base64_3([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],[Z1,Z2,Z3]) :-
        base64_table([A,B,C,D,E,F],Z1),
        base64_table([G,H,I,J,K,L],Z2),
        base64_table([M,N,O,P],Z3),!.
base64_3([A,B,C,D,E,F,G,H],[Z1,Z2]) :-
        base64_table([A,B,C,D,E,F],Z1),
        base64_table([G,H],Z2).

base64_i2b([],[]) :- !.
base64_i2b([X|R],[1,B,C,D,E,F,G,H|R2]) :-
        var(X),
        itob(X,[1,B,C,D,E,F,G,H]),
        base64_i2b(R,R2),!.
base64_i2b([X|R],[0,B,C,D,E,F,G,H|R2]) :-
        var(X),
        itob(U,[0,B,C,D,E,F,G,H]),
        X is U - 128,
        base64_i2b(R,R2),!.
base64_i2b([Code|R],[A,B,C,D,E,F,G,H|R2]) :-
        itob(Code,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,A,B,C,D,E,F,G,H]),
        base64_i2b(R,R2) .

name2(X,Y) :-
        atom(X),
        strlen(X,Len),
        findall(N,(for(1,M,Len) , char_code1(X,M,N1) , (N1 < 0 , N is N1 + 256 ; N1 >= 0 , N = N1)),Y),!.
name2(A,[N]) :-
        atomic(A),
        name(A,[N]),!.
name2(A,L) :-
        var(A),
        name21(L,L2),
        atom_codes(A,L2),!.

name21([],[]) :- !.
name21([N1,N2|R],[N|R2]) :-
        N1 > 127,
        N2 > 127,
        N is N1 * 256 + N2,
        name21(R,R2),!.
name21([N1,N2|R],[N|R2]) :-
        N1 > 127,
        N2 < 128,
        N is N1 * 256 + N2,
        name21(R,R2),!.
name21([N1|R],[N1|R2]) :-
        name21(R,R2).

itob(N,L) :-
        itob(N,[],L1),
        length(L1,Len),
        Len2 is 8 - Len,
        length(L2,Len2),
        all(L2,0),
        append(L2,L1,L).

itob(0,X,X) :- !.
itob(N,Y,X) :-
        M is N mod 2,
        N2 is N // 2,
        itob(N2,[M|Y],X).


http://pc12.2ch.net/test/read.cgi/tech/1250204272/974
#  [1] 授業単元:プログラミング 
#  [2] 問題文(含コード&リンク): 
#  new と deleteを使ったプログラムの作成 
#   人数、名前、点数を入力し、横棒グラフを表示するプログラムを作りなさい。 
#  ただし、グラフは5点刻みとし、点数は0点から100点の範囲とする。 
#  <実行画面> 
#  人数 : 3 
#  1人目の名前 : A  
#  1人目の点数 : 80 
#  2人目の名前 : B 
#  2人目の点数 : 55 
#  3人目の名前 : C 
#  3人目の点数 : 95 
#   
#  名( 点 )|         50       100 
#  --------+---------+---------+ 
#  A  ( 80)|**************** 
#  B  ( 55)|*********** 
#  C  ( 95)|******************* 
#  平均  77|*************** 
#

:- op(800,xfx,人目の名前).
:- op(800,xfx,人目の点数).
1人目の名前 'A'.
1人目の点数 80.
2人目の名前 'B'.
2人目の点数 55.
3人目の名前 'C'.
3人目の点数 95.

t786 :-
    write('  名(点)|        50       100\n--------+---------+---------+\n'), 
    N 人目の名前 _名前,
    N 人目の点数 _点数,
    星表現(_点数,_星表現),
    write_formatted('%4s(%2d)|%t\n',[_名前,_点数,_星表現]),
    fail.
t786 :-
    findavg(V,_ 人目の点数 V,_平均点),
    星表現(_平均点,_星表現),
    write_formatted('平均(%2d)|%t\n',[_平均点,_星表現]).

星表現(_点数,_星表現) :-
    Y is _点数 // 5,
    all(Y,L,'*'),
    concat_atom(Y,_星表現).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all(Length,L,A) :-
    length(L,Length),
    all(L,A).

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

findavg(_集約項,_項,_算術平均) :-
    findall(_集約項,_項,_値ならび),
    '加算'(_値ならび,_合計値),
    length(_値ならび,_ならびの長さ),
    _算術平均 is _合計値 / _ならびの長さ,!.

加算([],0.0).
加算([A|R1],X) :-
    加算(R1,Y),
    X is A + Y.

concat_atom([],'') :- !.
concat_atom([Atom],Atom) :- !.
concat_atom([Atom1|R1],Atom) :-
    concat_atom(R1,Atom2),
    atom_append(Atom1,Atom2,Atom).

concat_atom([],_,'') :- !.
concat_atom([Atom],_,Atom) :- !.
concat_atom([Atom1|R1],_区切り文字,Atom) :-
    concat_atom(R1,_区切り文字,Atom2),
    atom_append(Atom1,_区切り文字,Atom3),
    atom_append(Atom3,Atom2,Atom).


http://pc12.2ch.net/test/read.cgi/tech/1255709298/160# [1] 授業単元: プログラミング言語
# [2] 問題文(含コード&リンク):
#   問1、符号無し整数xを右にnビット回転した値を返す関数
#      unsigned right(unsigned x,int n)
# {
# }
# を作成せよ

符号無し整数を右にnビット回転(_整数,N,X) :-
    i2b(32,_整数,L1),
    ならびの回転(右方向,N,L1,L2),
    i2b(32,X,L2).

% *** user: i2b / 3 ***
i2b(_ビット数,_整数表現,_二進数リスト) :-
    var(_ビット数),
    integer(_整数表現),
    i2b_2(_整数表現,[],_二進数リスト) .
i2b(_ビット数,_整数表現,_二進数リスト) :-
    integer(_ビット数),
    integer(_整数表現),
    i2b_2(_整数表現,[],L2),
    length(_二進数リスト,_ビット数),
    append(L1,L2,_二進数リスト),
    L1 all 0,
    ! .
i2b(_ビット数,_整数表現,_二進数リスト) :-
    var(_整数表現),
    length(_二進数リスト,_ビット数),
    i2b_3(_ビット数,_二進数リスト,_実数表現),
    _整数表現 is truncate(_実数表現) .

% *** user: i2b_3 / 4 ***
i2b_3(N,N,[],0) :-
    ! .
i2b_3(M,N,[I|R],X) :-
    M2 is M + 1,
    i2b_3(M2,N,R,Y),
    X is 2 ^ M + Y + I,
    ! .

% *** user: i2b_3 / 3 ***
i2b_3(1,[I],I) :-
    ! .
i2b_3(M,[I|R],X) :-
    M2 is M - 1,
    i2b_3(M2,R,Y),
    X is 2 ^ M2 * I + Y,
    ! .

% *** user: i2b_3 / 2 ***
i2b_3([],0) :-
    ! .
i2b_3([0|R],X) :-
    i2b_3(R,Y),
    X is Y * 2,
    ! .
i2b_3([1|R],X) :-
    i2b_3(R,Y),
    X is Y * 2 + 1 .

% *** user: i2b_2 / 3 ***
i2b_2(0,L,L) :-
    ! .
i2b_2(N,Y,X) :-
    N1 is N // 2,
    N2 is N mod 2,
    i2b_2(N1,[N2|Y],X) .

% *** user: 'ならびの回転' / 4 ***
'ならびの回転'('左方向',1,[A|R],L) :-
    append(R,[A],L) .
'ならびの回転'('左方向',N,[A|R],L) :-
    N > 1,
    append(R,[A],L1),
    N1 is N - 1,
    'ならびの回転'('左方向',N1,L1,L) .
'ならびの回転'('右方向',1,L1,L2) :-
    append(L0,[A],L1),
    append([A],L0,L2) .
'ならびの回転'('右方向',N,L1,L2) :-
    N > 1,
    append(L0,[A],L1),
    append([A],L0,L3) .

% *** user: 'ならびの回転' / 3 ***
'ならびの回転'('右方向',[A|R],L) :-
    append(R,[A],L) .
'ならびの回転'('右方向',[A|R],L) :-
    append(R,[A],L1),
    'ならびの回転'('右方向',L1,L) .



http://pc12.2ch.net/test/read.cgi/tech/1255709298/131
# C++です。
#
#   x[0] = rand()%6;
#   x[1] = rand()%6;
#   x[2] = rand()%6;
#   y =x[0] + x[1] + x[2];
#   z[y] = z[y]+1;
#
# 変数がわかりにくくてすみません。
# xの配列に0〜5の値を保存して合計してyに入れます。
# それからzの配列(15こぶん)に入れたいのですが、うまくできません。


'1-15の乱数ごとに出現度数を取る'(_試行回数,_z) :- !.
        length(_z_1,15),
        all(_z_1,0),
        '1-15の乱数ごとに出現度数を取る'(_試行回数,_z_1,_z).

'1-15の乱数ごとに出現度数を取る'(0,_z,_z) :- !.
'1-15の乱数ごとに出現度数を取る'(_n,_z_1,_z) :-
        'xの配列に0〜5の値を保存して合計してyに入れます。'(_n,_n_1,_y),
        'それからzの配列(15こぶん)に入れたい。'(_y,_z_1,_z_2),
        '1-15の乱数ごとに出現度数を取る'(_n_1,_z_2,_z).

'xの配列に0〜5の値を保存して合計してyに入れます。'(_n,_n_1,_y) :-
        _n_1 is _n - 1,
        X_0 is random(6),
        X_1 is random(6),
        X_2 is random(6),
        _y is X_0 + X_1 + X_2 + 1.

'それからzの配列(15こぶん)に入れたい。'(_y,_z_1,_z_2) :-
        nth1(_y,_z_1,_yの度数_1),
        _yの度数_2 is _yの度数_1 + 1,
        ならびの位置指定置換(_y,_yの度数_2,_z_1,_z_2).

ならびの位置指定置換(1,A,[_|R],[A|R]) :- !.
ならびの位置指定置換(N,A,[B|R1],[B|R2]) :-
        N1 is N - 1,
        ならびの位置指定置換(N1,A,R1,R2).


http://pc12.2ch.net/test/read.cgi/tech/1255709298/326
#  [1] 授業単元:C言語とアルゴリズム 
#  [2] 問題文: http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10008.txt
# ●問題1−1 反復型処理(ビット列の表示)
#  符号なし32bit整数を入力して、その数を2進表示するプログラムを作成しなさい。
# さらに0のビットと1のビットの数を教示しなさい。ただし、2進表示は実行例のように4桁ずつ区切ること。
# 
# [実行例]
# 符号なし32bit整数を入力してください.
# 987654321
# 987654321 は2進表示で 0011 1010 1101 1110 0110 1000 1011 0001 です.
# 0のビット数は15,1のビット数は17です.
# 
# ●問題1−2 
#  符号なし32bit整数を2つ入力して、それらを2進表示するプログラムを作成しなさい。
# さらに、実行例のようにビット反転(1の補数表示〜),ビットシフト(<<, >>), ビット論理積(&),ビット論理和(|),
# ビット排他的論理和(^)を表示しなさい。ただし2進表示は4桁ずつ区切ること.
# また問題1−1で作成した2進表示の関数を再利用すること。
# 
# [実行例]
# 符号なし32bit整数2つを入力してください.
# 987654321 123456789
# 987654321 は2進表示で 0011 1010 1101 1110 0110 1000 1011 0001 ,
# 123456789 は2進表示で 0000 0111 0101 1011 1100 1101 0001 0101 です.
# 〜987654321 は2進表示で 1100 0101 0010 0001 10010111 0100 1110 ,
# 〜123456789 は2進表示で 1111 1000 1010 0100 0011 0010 1110 1010 です.
# 987654321 << 1は2進表示で 0111 0101 1011 1100 1101 0001 0110 0010 ,
# 123456789 >> 1は2進表示で 0000 0011 1010 1101 1110 0110 1000 1010 です.
# 987654321 & 123456879 は2進表示で 0000 0010 0101 1010 0100 1000 0001 0001 です.
# 987654321 | 123456879 は2進表示で 0011 1111 1101 1111 1110 1101 1011 0101 です.
# 987654321 ^ 123456879 は2進表示で 0011 1101 1000 0101 1010 0101 1010 0100 です.

符号なし32bit整数を入力して、その数を2進表示する(_10進数) :-
    二進数(_10進数,L),
    '4文字区切り'(L,S),
    findsum(1,member(0,L),S0),
    findsum(1,member(1,L),S1),
    write_formatted('%t は2進表示で %t です\n0のビット数は%t,1のビット数は%tです.\n',[_10進数,S,S0,S1]).

符号なし32bit整数を2つ入力して、論理和を2進表示する(_10進数_1,_10進数_2) :-
    二進数(_10進数_1,L_1),
    二進数(_10進数_2,L_2),
    ビットの論理和(L_1,L_2,L_3),
    '4文字区切り'(L_3,S),
    write_formatted('%t は2進表示で %t ,\n%t は2進表示で %t です.\n',[_10進数_1,S_1,_10進数_2,S_2]).

ビットを反転して表示(_10進数) :-
    二進数(_10進数,L),
    ビットの反転(L,L1),
    '4文字区切り'(L1,S),
    write_formatted('〜%t は2進表示で %t です.\n',[_10進数,S]).

ビットを左シフトして表示(_10進数,_シフト数) :-
    二進数(_10進数,L),
    ビットの左シフト(_シフト数,L,L1),
    '4文字区切り'(L1,S),
    write_formatted('%t >> %t は2進表示で %t です.\n',[_10進数,_シフト数,S]).

ビットを右シフトして表示(_10進数,_シフト数) :-
    二進数(_10進数,L),
    ビットの右シフト(_シフト数,L,L1),
    '4文字区切り'(L1,S),
    write_formatted('%t >> %t は2進表示で %t です.\n',[_10進数,_シフト数,S]).

符号なし32bit整数を2つ入力して、論理和を2進表示する(_10進数_1,_10進数_2) :-
    二進数(_10進数_1,L_1),
    二進数(_10進数_2,L_2),
    ビットの論理和(L_1,L_2,L_3),
    '4文字区切り'(L_3,S),
    write_formatted('%t | %t は2進表示で %t です.\n',[_10進数_1,_10進数_2,S]).

符号なし32bit整数を2つ入力して、論理積を2進表示する(_10進数_1,_10進数_2) :-
    二進数(_10進数_1,L_1),
    二進数(_10進数_2,L_2),
    ビットの論理積(L_1,L_2,L_3),
    '4文字区切り'(L_3,S),
    write_formatted('%t & %t は2進表示で %t です.\n',[_10進数_1,_10進数_2,S]).

符号なし32bit整数を2つ入力して、排他的論理和を2進表示する(_10進数_1,_10進数_2) :-
    二進数(_10進数_1,L_1),
    二進数(_10進数_2,L_2),
    ビットの排他的論理和(L_1,L_2,L_3),
    '4文字区切り'(L_3,S),
    write_formatted('%t ^ %t は2進表示で %t です.\n',[_10進数_1,_10進数_2,S]).

ビットの反転([],[]).
ビットの反転([0|R1],[1|R2]) :- ビットの反転(R1,R2).
ビットの反転([1|R1],[0|R2]) :- ビットの反転(R1,R2).

ビットの右回転(_シフト数,_ビットならび,_シフトしたビットならび) :-
    ならびの回転(右方向,_シフト数,_ビットならび,_シフトしたビットならび).

ビットの左回転(_シフト数,_ビットならび,_シフトしたビットならび) :-
    ならびの回転(左方向,_シフト数,_ビットならび,_シフトしたビットならび).

ビットの左シフト(_シフト数,_ビットならび,_シフトしたビットならび) :-
    length(L1,_シフト数),
    length(L2,_シフト数),
    all(L2,0),
    append(L1,L3,_ビットならび),
    append(L3,L2,_シフトしたビットならび).

ビットの右シフト(_シフト数,_ビットならび,_シフトしたビットならび) :-
    length(L1,_シフト数),
    length(L2,_シフト数),
    all(L2,0),
    append(L3,L1,_ビットならび),
    append(L2,L3,_シフトしたビットならび).

ビットの論理和([],[],[]).
ビットの論理和([0|R1],[0|R2],[0|R3]) :- ビットの論理和(R1,R2,R3).
ビットの論理和([1|R1],[0|R2],[1|R3]) :- ビットの論理和(R1,R2,R3).
ビットの論理和([0|R1],[1|R2],[1|R3]) :- ビットの論理和(R1,R2,R3).
ビットの論理和([1|R1],[1|R2],[1|R3]) :- ビットの論理和(R1,R2,R3).

ビットの論理積([],[],[]).
ビットの論理積([0|R1],[0|R2],[0|R3]) :- ビットの論理積(R1,R2,R3).
ビットの論理積([1|R1],[0|R2],[0|R3]) :- ビットの論理積(R1,R2,R3).
ビットの論理積([0|R1],[1|R2],[0|R3]) :- ビットの論理積(R1,R2,R3).
ビットの論理積([1|R1],[1|R2],[1|R3]) :- ビットの論理積(R1,R2,R3).

ビットの排他的論理和([],[],[]).
ビットの排他的論理和([0|R1],[0|R2],[0|R3]) :- ビットの排他的論理和(R1,R2,R3).
ビットの排他的論理和([1|R1],[0|R2],[1|R3]) :- ビットの排他的論理和(R1,R2,R3).
ビットの排他的論理和([0|R1],[1|R2],[1|R3]) :- ビットの排他的論理和(R1,R2,R3).
ビットの排他的論理和([1|R1],[1|R2],[0|R3]) :- ビットの排他的論理和(R1,R2,R3).

二進数(_10進数,L) :-
    length(L,32),
    二進数(_10進数,[],X),
    append(L1,X,L),
    all(L1,0).

二進数(J,Y,[J|Y]) :- J < 2.
二進数(J,Y,X) :- J >= 2,J2 is J // 2,M is J mod 2,二進数(J2,[M|Y],X).


'4文字区切り'([],'').
'4文字区切り'([A,B,C,D|R],S) :-
    '4文字区切り'(R,S1),
    concat_atom([A,B,C,D,' ',S1],S).


http://pc12.2ch.net/test/read.cgi/tech/1248012902/444
# 【課題】課題は3つあります。
# http://www.dotup.org/uploda/www.dotup.org318192.zip
% 問題1 星ピラミットの表示

入力された段数になるように星文字でピラミッドを築く :-
    write('段数を入れてください : '),
    get_integer(_段数),
    _最終行の星数 is (_段数 - 1) * 2 + 1,
    length(L,_最終行の星数),
    for(1,N,_段数),
    length(L1,N),
    all(L1,'*'),
    append(L0,L1,L0,L),
    all(L0,' '),
    atom_chars(Atom,L),
    write_formatted('   %t   \n',[Atom]),
    N = _段数.


乱数を使って発生させた2つの整数のたし算を5問示しそれぞれの回答診断と5問答えるのに要した時間を表示 :-
    _開始時刻 is time,
    for(1,N,5),
    一問答える,
    N = 5,
    _終了時刻 is time,
    _回答するのに要した時間 is _終了時刻 - _開始時刻,
    write_formatted('5問回答までの時間は%t秒でした。\n',[_回答するのに要した時間]).

一問答える :-
    A is random mod 100,
    B is random mod 100,
    write_formatted('%t + %t =? ',[A,B]),get_integer(_答え),
    _正解 is A + B,
    回答診断(_正解,_答え,_診断),
    write_formatted('%t\n',[_診断]).

回答診断(_正解,_正解,'正解です!!').
回答診断(_正解,_答え,_診断) :-
    1 is abs(_正解 - _答え),
    concat_atom(['惜しいです。正解は',_正解],_診断).
回答診断(_正解,_答え,_診断) :-
    \+(_答え=_正解),
    \+(1 is abs(_正解 - _答え)),
    concat_atom(['間違いです。正解は',_正解],_診断). 

'ファイル名を入力させてそのファイルの行数その中に現れる小文字、大文字、その他の文字数を表示する' :-
    write('ファイル名を入力してください\n'),
    get_line(_ファイル名),
    get_chars(_ファイル名,Chars),
    '行数、小文字数、大文字数、その他文字数の集計'(Chars,_行数,_小文字数,_大文字数,_その他文字数),
    write_formatted('%t行ありました\n',[_行数]),
    write_formatted('小文字の数は%t\n',[_小文字数]),
    write_formatted('大文字の数は%t\n',[_大文字数]),
    write_formatted('その他の数は%t\n',[_その他文字数]).

'行数、小文字数、大文字数、その他文字数の集計'([],0,0,0,0).
'行数、小文字数、大文字数、その他文字数の集計'(['\n'|R],S1,S2,S3,S4) :-
    '行数、小文字数、大文字数、その他文字数の集計'(R,S11,S2,S3,S4),
    S1 is S11 + 1,!.
'行数、小文字数、大文字数、その他文字数の集計'([A|R],S1,S2,S3,S4) :-
    A @>= 'a',A @=< 'x',
    '行数、小文字数、大文字数、その他文字数の集計'(R,S1,S21,S3,S4),
    S2 is S21 + 1,!.
'行数、小文字数、大文字数、その他文字数の集計'([A|R],S1,S2,S3,S4) :-
    A @>= 'A',A @=< 'Z',
    '行数、小文字数、大文字数、その他文字数の集計'(R,S1,S2,S31,S4),
    S3 is S31 + 1,!.
'行数、小文字数、大文字数、その他文字数の集計'([_|R],S1,S2,S3,S4) :-
    '行数、小文字数、大文字数、その他文字数の集計'(R,S1,S2,S3,S41),
    S4 is S41 + 1,!.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_integer(N) :-
    repeat,
    get_line(Line),
    atom_to_term(Line,M,_),
    get_integer_診断(M,N),!.

get_integer_診断(end_of_file,-1).
get_integer_診断(N,N) :- integer(N).

get_line(X) :-
    get_char(C),
    get_line_1(C,Chars),
    atom_chars(X,Chars).

get_line_1('\n',[]) :- !.
get_line_1(end_of_file,[]) :- !.
get_line_1(C,[C|R]) :-
    get_char(C2),
    get_line_1(C2,R).

http://pc12.2ch.net/test/read.cgi/tech/1255709298/615 
#  C++で10進数を2進数に変換するプログラムを配列使って 
#  順番通りに表示できるようにするのってどうするんですか 

t2_49 :- 
    write('10進数をスペースで区切って何個か入力してください : '), 
    get_line(Line), 
    split(Line,[' '],L), 
    member(N,L), 
    二進数(N,L), 
    wrln(L), 
    fail. 
t2_49.

二進数(_10進数,L) :- 
    length(L,32), 
    二進数(_10進数,[],X), 
    append(L1,X,L), 
    all(L1,0). 

二進数(J,Y,[J|Y]) :- J < 2. 
二進数(J,Y,X) :- J >= 2,J2 is J // 2,M is J mod 2,二進数(J2,[M|Y],X). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
wrln([]) :- nl. 
wrln([A|R]) :- write(A),wrln(R). 

http://pc12.2ch.net/test/read.cgi/tech/1248012902/463 
# 【課題】 
#  http://ime.nu/www51.tok2.com/home/rg550/cgi-bin/hosoku/img0047.zip 
# 【課題1】 
# 実行例のようにキーボードから文字列を読み込み、文字型の配列に一文字づつ格納 
# した後、整列し(順番はどちらでもかまいません)、出力するプログラムを 
# 作成しなさい。 
# 【課題2】 
# 0から9までの整数乱数を100個発生させ、実行例のようにその出現分布を棒グラフと 
# 値で出力するプログラムを作成しなさい。また、100個の乱数の平均値も合わせて 
# 出力しなさい。 
# ただし、0から9 それぞれの個数を数えるための変数に必ず配列を用いてください。 
# (出現個数カウント用の変数を10個用意してはいけません。) 例えば、出現個数 
# カウント用の配列 count[] を用意すると、 count[0] に0が出現した回数が 
# 格納される。もし0が10回出現した場合、count[0]=10となる。) 

% 課題1
'実行例のようにキーボードから文字列を読み込み、文字型の配列に一文字づつ格納した 後、整列し(順番はどちらでもかまいません)、出力する' :- 
    get_chars(_文字ならび), 
    sort(_文字ならび,_整列した文字ならび), 
    atom_chars(_整列した文字列,_整列した文字ならび), 
    write_formatted('%t\n',[_整列した文字列]).

% 課題2
'0から9までの整数乱数を100個発生させ、実行例のようにその出現分布を棒グラフと値 で出力する' :- 
    findall([N,0,[]],for(0,N,9),_出現個数カウント用ならび), 
    '0から9までの整数乱数を100個発生させ'(1,L1), 
    'その出現分布を棒グラフと値で出力する'(L1,_出現個数カウント用ならび). 

'0から9までの整数乱数を100個発生させ'(N,[]) :- N > 100,!. 
'0から9までの整数乱数を100個発生させ'(N,[_乱整数|R]) :- 
    _乱整数 is random mod 10, 
    N2 is N + 1, 
    '0から9までの整数乱数を100個発生させ'(N2,R). 

'その出現分布を棒グラフと値で出力する'([],L) :- 
    'グラフと値で出力'(L),!. 
'その出現分布を棒グラフと値で出力する'([N|R],L) :- 
    member([N,_カウント,L1],L), 
    _カウント2 is _カウント + 1, 
    ならびの置換([N,_カウント,L1],[N,_カウント2,[_|L1]],L,L2),
    'その出現分布を棒グラフと値で出力する'(R,L2). 

グラフと値で出力([]). 
グラフと値で出力([[N,C,L]|R]) :- 
    all(L,'*'), 
    write_formatted(' %t: %t %t\n',[N,L,C]), 
    グラフと値で出力(R).


http://pc12.2ch.net/test/read.cgi/tech/1255709298/752 
#  正の整数nを2乗して得られる4桁の整数のうち、 
#  2種類の数字しか現れないものをすべて挙げなさい 

t2_93 :- 
    '正の整数nを2乗して得られる4桁の整数のうち、2種類の数字しか現れないものをすべて挙げる'(N),     
    write_formatted('%t\n',[N]), 
    fail. 
t2_93. 

'正の整数nを2乗して得られる4桁の整数のうち、2種類の数字しか現れないものをすべて挙げる'(N) :- 
    Max is trunscate(sqrt(9999)), 
    for(1,N,Max), 
    N1 is N * N, 
    number_chars(N1,L), 
    '2種類の数文字しか現れない'(L). 

'2種類の数文字しか現れない'([A|R]) :- 
    ならびから削除(A,R,R1), 
    \+(R1=[]), 
    all(R1,_).  

% *** user: 'ならびから削除' / 3 *** 
ならびから削除(_,[],[]) :- !. 
ならびから削除(_削除する要素,[_削除する要素|_残り対象ならび],_削除されたなら 
び) :- 
    ならびから削除(_削除する要素,_残り対象ならび,_削除されたならび),!. 
ならびから削除(_削除する要素,[_要素|_残り対象ならび],[_要素|_残り削除ならび]) 
:- 
    ならびから削除(_削除する要素,_残り対象ならび,_残り削除ならび),!. 

http://pc12.2ch.net/test/read.cgi/tech/1258158172/236
#  [1] C言語プログラミング演習 
#  [2] 標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換するプログラム 
#  (コマンドラインに 2 4 2 4 を与えた場合タブを入力したら3 7 10 17 20 27...が桁位置に 
#  なるようスペースを挿入する) 
#  入力は半角文字に限って良い。またコマンドラインからは正の整数を表すものが 
#  与えられるとして良い 
#  [3] Windows vista/Borland C++ 5.5/C言語でコード 
#  制限:fgetsを使う。 
#  [4] できるだけ早く 
# 
# 

標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する :-
    user_paramegers(L),
    findall(N,(member(A,L),atom_to_term(A,N,_)),L2),
    get_chars(Chars),
    標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する(_タブストップサイクル,_タブストップサイクル,Chars,X).

標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する([],_タブストップサイクル,L2,L3) :-
    標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する(_タブストップサイクル,_タブストップサイクル,L2,L3),!.

標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する(_,_,[],[]) :- !.
標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する([N|R1],_タブストップサイクル,['\t'|R2],L) :-
    length(L2,N),
    all(L2,' '),
    append(L2,L3,L),
    標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する(R1,_タブストップサイクル,R2,L3),!.
標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する([N|R1],_タブストップサイクル,[A|R2],[A|R3]) :-
    \+(A='t'),
    標準入力の文字列に含まれるタブをコマンドラインで与えたサイクルのタブストップでスペースに変換する([N|R1],_タブストップサイクル,R2,R3).

http://pc12.2ch.net/test/read.cgi/tech/1258158172/407
#  [1] 授業単元: C言語 
#  [2] 問題文(含コード&リンク):  
#  課題1、文字列、と2つの整数(それぞれ n, m とする)を入力すると 
#  n文字目から m文字 *に変えるプログラムを書け。 
#   
#     実行例 
#    文字を入力して下さい 
#     Toshidaigaku 
#     nを入力して下さい 
#     4 
#     mを入力して下さい 
#     2 
#     出力は 
#     Tos**daigaku 
#   
#  課題2、文字列を入力すると、全ての文字を次の文字コードの文字に 
#  変えて、結果を表示するプログラムを書け。 
#   
#     実行例 
#   
#     文字を入力して下さい 
#     Toshidaigaku 
#     出力は 
#     Uptijebjhblv 
# 
# 

'文字列と2つの整数(それぞれ n, m とする)を入力するとn文字目からm文字*に変える'(_文字列,N,M) :-
    sub_atom(_文字列,N - 1,M,R,_),
    length(L,M),
    all(L,*),
    concat_atom(L,S),
    sub_atom(_文字列,0,N,_,S1),
    sub_atom(_文字列,N + M,R,_,S2),
    concat_atom([S1,S,S2],X).

http://pc12.2ch.net/test/read.cgi/tech/1258158172/438
#  1] 授業単元: プログラミング実習  
#  [2] 問題文(含コード&リンク):  
#  http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10181.txt
#   
# 〜課題2〜
# 変数nを入力すると、以下の図のような表示を行うプログラムをそれぞれ作成せよ。ただし、図はn=5の場合である。
# 1つのプログラムとして作成せよ。
# 
#          *  
#     ***
#        *****
#       *******
#      *********

ピラミッド(N) :- 
    length(L1,N), 
    all(L1,' '), 
    ピラミッド(L1,[*]). 

ピラミッド([],HL) :- concat_atom(HL,S),write_formatted('%t\n',[S]). 
ピラミッド([_|L1],HL) :- 
    append(L1,HL,L1,L2), 
    concat_atom(L2,S), 
    write_formatted('%t\n',[S]), 
    ピラミッド(L1,['**'|HL]).


http://pc12.2ch.net/test/read.cgi/tech/1258158172/754 
#  [1] 授業単元:C 
#  [2] 問題文(含コード&リンク): 
#  入力されたデータをもとに売上明細を作成して表示する。 
#  入力データは商品名と金額で、最大20件とし、^zで終了する。 
#  入力されたデータは構造体配列に記録し、 
#  入力終了後金額を集計して合計を表示する。 
#  <構造体メンバ> 
#  商品名:char型10桁 
#  金額:long型 
#  <実行結果> 
#  ^z 
#  商品名    金額 
#  パソコン   248500 
#  ラジオ     3200 
#  テレビ    120500 
#  オーディオ  314000 
#  レイゾウコ   65800 
#  クーラー    79000 
#  合計    831000 
#  

入力されたデータをもとに売上明細を作成して表示する :- 
    売上データの収集(_収集されたデータ), 
    findsum(_金額,member([_,_金額],_収集されたデータ),_金額合計), 
    write('商品名     金額\n'), 
    明細表の印刷(_収集されたデータ,_金額合計),!. 

売上データの収集(_収集されたデータ) :- 
    write('商品名と金額をカンマで区切って入力してください\n'). 
    findall([A2,B], 
           (    for(1,N,10),get_line(Line), 
                (  Line=end_of_file,!,fail; 
                   split(Line,[','],[A,B]), 
                   '10桁の文字列'(A,A2))),_収集されたデータ),!. 

明細表の印刷([],_金額合計) :- write_formatted('%10s %10d\n',[金額合計,_金額合計]). 
明細表の印刷([[_商品名,_金額]|R],_金額合計) :- 
    write_formatted('%10s %10d\n',[_商品名,_金額]), 
    明細表の印刷(R,_金額合計). 

'10桁の文字列'(_文字列,_10桁の文字列) :- 
    atom_chars(_文字列,Chars), 
    length(L,10), 
    apend(Chars,L1,L), 
    all(L1,' '), 
    atom_chars(_10桁の文字列,L),!. 
'10桁の文字列'(_文字列,_10桁の文字列) :- sub_atom(_文字列,0,10,_,_10桁の文字列).


'LU分解'(L1,L,U) :-
        'LU分解(L1,L2),
        'LとU、二つの行列に分離する'(L2,L,U).

'LU分解'([L],[L]) :- !.
'LU分解'(LL,LU) :-
        第一行と第一列を切り取り第一列には除算処理を施す(LL,L1,L2,LL_1),
        '第一行と第一列を使ってLL_1をの値を更新する'(LL_1,L1,L2,LL2),
        'LU分解'(LL2,LU2),
        第一行と第一列を付加する(LU2,L1,L2,LU).

第一行と第一列を切り取り第一列には除算処理を施す(LL,L1,L2,LL_2) :-
        第一行を切り取る(LL,_除数,L1,LL_1),
        第一列と第二列以降を分離する(LL_1,L2_1,LL_2),
        第一列を除算する(_除数,L2_1,L2).

第一行を切り取る([[A|R1]|LL_1],A,[A|R1],LL_1).

第一列と第二列以降を分離する([],[],[]).
第一列と第二列以降を分離する([A|R1],[A|R2],[R1|R3]) :-
        第一列と第二列以降を分離する(R1,R2,R3).

第一列を除算する(_,[],[]).
第一列を除算する(V1,[V2|R1],[V3|R2]) :-
        分数を含む除算(V2,V1,V3),
        第一列を除算する(V1,R1,R2).

'第一行と第一列を使ってLL_1をの値を更新する'([],_,_,[]).
'第一行と第一列を使ってLL_1をの値を更新する'([L|R1],[A|R2],L2,[L4|R4]) :-
        行を更新する(L,A,L2,L4),
        '第一行と第一列を使ってLL_1をの値を更新する'(R1,R2,L2,R4).

行を更新する([],_,_,[]).
行を更新する([V1|R1],A,[B|R3],[V|R4]) :-
        'Vの更新'(V1,A,B,V),
        行を更新する(R1,A,R3,R4).

'Vの更新'(V1,A,B,V) :-
        分数を含む乗算(A,B,C),
        分数を含む減算(V1,C,V),!.

第一行と第一列を付加する(LU2,L1,L2,LU) :-
        第一列を付加する(L2,LU2,LU1),
        LU = [L1|LU1].

第一列を付加する([],[],[]).
第一列を付加する([A|R1],[L2|R2],[[A|L2]|R3]) :-
        第一列を付加する(R1,R2,R3).

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

'LとU、二つの行列に分離する'(LU,L,U) :-
        'Lを分離する'(LU,L),
        'Uを分離する'(LU,U).

'Lを分離する'(LU,LL) :-
        findall(L2,(
                   member(L1,LU),
                   append(L0,[A|R],L1),
                   'L0の全要素をAで割る'(L0,A,L0_1),
                   '対角要素Aを1として残り要素Rをすべて0に置き換える'(L0_1,R,L2)),
                LL).
                   
'L0の全要素をAで割る'([],_,[]).
'L0の全要素をAで割る'([N|R1],A,[M|R2]) :-
        分数を含む除算(N,A,M),
        'L0の全要素をAで割る'(R1,A,R2).

'対角要素Aを1として残り要素Rをすべて0に置き換える'(L0,R,L2) :-
        length(R,Len),
        length(R1,Len),
        all(R1,0),
        append(L0,[1|R1],L2),!.

'Uを分離する'(LU,UU) :-
        findall(L2,(
                   member(L,LU),
                   append(L0,[A|R1],L),
                   'L0の全要素を0に置き換える'(L,L0,[A|R1],L2)),
                UU).

'L0の全要素を0に置き換える'(L,L0,[A|R1],L2) :-
        length(L0,Len),
        length(L01,Len),
        all(L01,0),
        'L1を先頭要素で割る'(L1,L1_2),
        append(L01,L1_2,L2),!.

'L1を先頭要素で割る'([_先頭要素|R1],[1|R2]) :-
        findall(M,(
                    member(A,R1),
                    分数を含む除算(A,_先頭要素,M)),
                R2).

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

分数を含む乗算(A1/B1,A2/B2,C) :-
        B3 is B1 * B2,
        A3 is A1 * A2,
        約分(A3/B3,C),!.
分数を含む乗算(V,A2/B2,C) :-
        number(V),
        A3 is V * A2,
        約分(U/B2,C),!.
分数を含む乗算(A1/B1,V,C) :-
        number(V),
        A3 is A1 * V,
        約分(A3/B1,C),!.
分数を含む乗算(A,B,C) :-
        C is A * B.

分数を含む除算(A,B,C) :-
        number(A),
        number(B),
        約分(A/B,C),!.
分数を含む除算(V,A2/B2,C) :-
        number(V),
        分数を含む乗算(V,B2/A2,C),!.
分数を含む除算(A1/B1,A2/B2,C) :-
        分数を含む乗算(A1/B1,B2/A2,C),!.
分数を含む除算(A1/B1,V,C) :-
        number(V),
        B2 is V * B1,
        約分(A1/B2,C),!.

分数を含む減算(A,B,C) :-
        number(A),
        number(B),
        C is A - B,!.        
分数を含む減算(A1/B1,A2/B2,C) :-
        A3 is A1 * B2 - A2 * B1,
        B3 is B1 * B2,
        約分(A3/B3,C),!.
分数を含む減算(A1/B1,V,C) :-
        number(V),
        A2 is V * B1,
        C3 is A1 - A2,
        約分(C3/B1,C),!.
分数を含む減算(V,A2/B2,C) :-
        number(V),
        A1 is V * B2,
        C3 is A1 - A2,
        約分(C3/B2,C),!.


'LU分解'(L1,L,U) :-
        'LU分解(L1,L2),
        'LとUに二つの行列に分離する'(L2,L,U).

'LU分解'([L],[L]) :- !.
'LU分解'(LL,LU) :-
        第一行と第一列を切り取り第一列には除算処理を施す(LL,L1,L2,LL_1),
        '第一行と第一列を使って残り行列の値を更新する'(LL_1,L1,L2,LL2),
        'LU分解'(LL2,LU2),
        第一行と第一列を付加する(LU2,L1,L2,LU).

第一行と第一列を切り取り第一列には除算処理を施す(LL,_第一行,_更新された第二行以下の第一列,_残り行列) :-
        第一行を切り取る(LL,_左上角要素,_第一行,_第二行以下の行列),
        第一列と第二列以降を分離する(_第二行以下の行列,_第二行以下の第一列,_残り行列),
        左上角要素を除数として第一列を除算する(_左上角要素,_第二行以下の第一列,_更新された第二行以下の第一列).

第一行を切り取る([[A|R1]|LL_1],A,[A|R1],LL_1).

第一列と第二列以降を分離する([],[],[]).
第一列と第二列以降を分離する([A|R1],[A|R2],[R1|R3]) :-
        第一列と第二列以降を分離する(R1,R2,R3).

左上角要素を除数として第一列を除算する(_,[],[]).
左上角要素を除数として第一列を除算する(_除数,[_第一列要素|R1],[_更新される第一列要素|R2]) :-
        分数を含む除算(_第一列要素,_除数,_更新される第一列要素),
        左上角要素を除数として第一列を除算する(_除数,R1,R2).

'第一行と第一列を使って残り行列の値を更新する'([],_,_,[]).
'第一行と第一列を使って残り行列の値を更新する'([L|R1],[A|R2],L2,[L4|R4]) :-
        行を更新する(L,A,L2,L4),
        '第一行と第一列を使って残り行列の値を更新する'(R1,R2,L2,R4).

行を更新する([],_,_,[]).
行を更新する([V1|R1],A,[B|R3],[V|R4]) :-
        'Vの更新'(V1,A,B,V),
        行を更新する(R1,A,R3,R4).

'Vの更新'(V1,A,B,V) :-
        分数を含む乗算(A,B,C),
        分数を含む減算(V1,C,V),!.

第一行と第一列を付加する(LU2,L1,L2,LU) :-
        第一列を付加する(L2,LU2,LU1),
        LU = [L1|LU1].

第一列を付加する([],[],[]).
第一列を付加する([A|R1],[L2|R2],[[A|L2]|R3]) :-
        第一列を付加する(R1,R2,R3).

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

'LとUに二つの行列に分離する'(LU,L,U) :-
        'Lを分離する'(LU,L),
        'Uを分離する'(LU,U).

'Lを分離する'(LU,LL) :-
        findall(LL,(
                   member(L1,LU),
                   append(L0,[A|R],L1),
                   '対角要素Aを1として残り要素Rをすべて0に置き換える'(L1,L0,R,L3),
                LL).
                   
'対角要素Aを1として残り要素Rをすべて0に置き換える'(L1,L0,R,L2) :-
        length(R,Len),
        length(R1,Len),
        all(R1,0),
        append(L0,[1|R1],L2),!.

'Uを分離する'(LU,UU) :-
        findall(L2,(
                   member(L,LU),
                   append(L0,L1,L),
                   'L0の全要素を0に置き換える'(L,L0,L1,L2)),
                UU).

'L0の全要素を0に置き換える'(L,L0,L1,L2) :-
        length(L0,Len),
        length(L01,Len),
        all(L01,0),
        append(L01,L1,L2),!.

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

分数を含む乗算(A1/B1,A2/B2,C) :-
        B3 is B1 * B2,
        A3 is A1 * A2,
        約分(A3/B3,C),!.
分数を含む乗算(V,A2/B2,C) :-
        number(V),
        A3 is V * A2,
        約分(U/B2,C),!.
分数を含む乗算(A1/B1,V,C) :-
        number(V),
        A3 is A1 * V,
        約分(A3/B1,C),!.
分数を含む乗算(A,B,C) :-
        C is A * B.

分数を含む除算(A,B,C) :-
        number(A),
        number(B),
        約分(A/B,C),!.
分数を含む除算(V,A2/B2,C) :-
        number(V),
        分数を含む乗算(V,B2/A2,C),!.
分数を含む除算(A1/B1,A2/B2,C) :-
        分数を含む乗算(A1/B1,B2/A2,C),!.
分数を含む除算(A1/B1,V,C) :-
        number(V),
        B2 is V * B1,
        約分(A1/B2,C),!.

分数を含む減算(A,B,C) :-
        number(A),
        number(B),
        C is A - B,!.        
分数を含む減算(A1/B1,A2/B2,C) :-
        A3 is A1 * B2 - A2 * B1,
        B3 is B1 * B2,
        約分(A3/B3,C),!.
分数を含む減算(A1/B1,V,C) :-
        number(V),
        A2 is V * B1,
        C3 is A1 - A2,
        約分(C3/B1,C),!.
分数を含む減算(V,A2/B2,C) :-
        number(V),
        A1 is V * B2,
        C3 is A1 - A2,
        約分(C3/B2,C),!.


ヒストグラム(_サンプルならび) :-
   for(0,N,9),
   count(member(N,_サンプルならび),_度数),
   length(L,_度数),
   要素はすべてアスタリスクである(L),
   concat_atom(L,_星表示アトム),
   write_formatted('%t %t\n',[N,_星表示アトム]),
   N=9.

要素はすべてアスタリスクである(L) :- all(L,'*').


hX 


7A