このディレクトリの索引
http://hibari.2ch.net/test/read.cgi/tech/1322562648/17
#  前スレの未解決問題。(ほかにあったら転記してね) 
#  979 :デフォルトの名無しさん:2011/11/29(火) 21:17:42.06 
#      [1] 授業単元:コマンドライン引数 
#      [2] 問題文(含コード&リンク): 
#      コマンドライン引数を用いて,以下の計算ができる簡易電卓プログラムを作成せよ. 
#      1. 2 〜5項式までの四則演算(計算順もちゃんと考慮すること) 
#      (出力例)C :¥Programming>dentaku 2 + 5 / 5 + 4 * 2 + 1 
#      答えは 12 
#   
#      C :¥Programming>dentaku 2 * 3 + 1 
#      答えは 7 
#   
#      2.()を用いた演算(かっこの中の計算を最優先する) 
#      (出力例)C :¥Programming>dentaku ( 2 + 3 ) * 7 * ( 3 - 1 ) 
#      答えは 70 
#   
#      3. (sin, cos, tan)の演算 
#      (出力例)C :¥Programming>dentaku sin(90) * 2 + 1 - 2 
#      答えは 1 
#   
#      4.logの演算 
#      (出力例)C :¥Programming>dentaku log(3) * 2 + 1 
#      答えは 1.9542425094 
#   
#      5. 半角スペースを入れ忘れても演算可能 
#      (出力例)C :¥Programming>dentaku 1-2*(3+1)-2 
#      答えは 9 
#      

電卓 :-
        式の入力(Line),
        項に分解(Line,_項ならび),
        '2. () を用いた演算'(_項ならび,X),
        writef('%12r\n',[X]).

式の入力(Line) :-
        writef('%12r\n',[0]),
        get_line(Line),!.

項に分解(Line,_項ならび) :-
        atom_chars(Line,Chars),
        一旦空白要素を削除する(Chars,Chars1),
        '先頭の符号に注意して、演算子の前後に空白を入れる'(Chars1,Chars2),
        atom_chars(Line2,Chars2),
        split(Line2,[' '],_項ならび).

一旦空白要素を削除する([],[]).
一旦空白要素を削除する([' '|R1],R2) :-
        一旦空白要素を削除する(R1,R2),!.
一旦空白要素を削除する([A|R1],[A|R2]) :-
        一旦空白要素を削除する(R1,R2),!.

'先頭の符号に注意して、演算子の前後に空白を入れる'(['-'|R1],['-'|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
'先頭の符号に注意して、演算子の前後に空白を入れる'(L1,L2) :-
        演算子の前後に空白を入れる(L1,L2),!.

演算子の前後に空白を入れる([],[]),!.
演算子の前後に空白を入れる(['(','-'|R1],[' ','(',' '|R2]) :-
        演算子の前後に空白を入れる(['-'|R1],R2),!.
演算子の前後に空白を入れる([')','-'|R1],[' ',')',' ','-',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['+','-'|R1],[' ','+',' ','-'|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['-','-'|R1],[' ','-',' ','-'|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['*','-'|R1],[' ','*',' ','-'|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['/','-'|R1],[' ','/',' ','-'|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['('|R1],[' ','(',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる([')'|R1],[' ',')',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['+'|R1],[' ','+',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['-'|R1],[' ','-',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['*'|R1],[' ','*',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる(['/'|R1],[' ','/',' '|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.
演算子の前後に空白を入れる([A|R1],[A|R2]) :-
        演算子の前後に空白を入れる(R1,R2),!.

'2. () を用いた演算'(_項ならび,X) :-
        '先に()グループを演算する'(_項ならび,_項ならびの一),
        '+,-でグループ化する'(_項ならびの一,_項ならびの二),
        '要素の四則演算'(_項ならびの二,X).

'先に()グループを演算する'([],[]).
'先に()グループを演算する'(['('|R1],[X|R2]) :-
        '()グループを演算して置換'(R1,X),
        '先に()グループを演算する'(R1,R2),!.
'先に()グループを演算する'([A|R1],[A|R2]) :-
        '先に()グループを演算する'(R1,R2),!.

'()グループを演算して置換'([],LX,X,[]) :-
        '+,-でグループ化する'(_項ならびの一,_項ならびの二),
        '要素の四則演算'(_項ならびの二,X),!.
'()グループを演算して置換'([')'|R],LX,X,R) :-
        '+,-でグループ化する'(LX,_項ならびの二),
        '要素の四則演算'(_項ならびの二,X),!.
'()グループを演算して置換'(['('|R],LX,X,R) :-
        '()グループを演算して置換'(['('|R],[],Y,R1),
        append(LX,[Y],LY),
        '()グループを演算して置換'(R1,LY,X,R),!.
'()グループを演算して置換'([A|R1],LX,X,R) :-
        append(LX,[A],LY),
        '()グループを演算して置換'(R1,LY,X,R).

'+,-でグループ化する'(L,[L0,A|R2]) :-
        append(L0,[A|R],L),
        '+か-'(A),
        '+,-でグループ化する'(R,R2),!.
'+,-でグループ化する'(L,[L]).

'+か-'(+).
'+か-'(-).

'要素の四則演算'([L],X) :-
        ならび評価(L,X),!.
'要素の四則演算'([L1,'+'|R1],X) :-
        ならび評価(L1,A),
        '要素の四則演算'(R1,Y),
        X is A + Y.
'要素の四則演算'([L1,'-',L2|R1],[C|R2]) :-
        ならび評価(L1,A),
        '要素の四則演算'(R1,Y),
        X is A - Y.

ならび評価([A],A) :- !.
ならび評価([A,'*'|R1],X) :-
        ならび評価(R1,Y),
        X is A * Y.
ならび評価([A,'/'|R1],X) :-
        ならび評価(R1,Y),
        X is A // Y.