このディレクトリの索引
2ch「プログラムのお題スレ」 #228
#  お題: 任意の数の自然数を与えた時、それらの自然数を四則演算した結果が、 
#  期待した自然数になる式を全て列挙するコードを作成しなさい。 
#  ただし、式中の乗除算は加減算より先に計算するものとする。 
#  また数の並びは変更出来ず、括弧は使わないものとする。 
#  
#  例: 1 5 3 6 : 10 
#  
#  1 * 5 / 3 * 6 
#  1 + 5 * 3 - 6 
#  
#  1 5 3 6 7 : 10 
#  -> 
#  1 + 5 + 3 - 6 + 7 

'任意の数の自然数を与えた時、それらの自然数を四則演算した結果が、
期待した自然数になる式を全て列挙するコードを作成しなさい。
ただし、式中の乗除算は加減算より先に計算するものとする。
また数の並びは変更出来ず、括弧は使わないものとする。'(_自然数ならび,_期待した自然数,_式) :-
        findall(X,(
                    append(_,[_自然数|R],_自然数ならび),
                    自然数と変数を交互に(_自然数,R,X)),
                _自然数の間に変数が挿入されたならび),
        変数に演算子を当て嵌める(_自然数の間に変数が挿入されたならび),
        式を計算する(_自然数の間に変数が挿入されたならび,_期待した自然数,_式).

自然数と変数を交互に(_自然数,[],_自然数) :- !.
自然数と変数を交互に(_自然数,_,_自然数).
自然数と変数を交互に(_自然数,_,_).

変数に演算子を当て嵌める(_自然数の間に変数が挿入されたならび) :-
        変数のみ取り出して(_自然数の間に変数が挿入されたならび,_変数ならび),
        変数に演算子を当て嵌める(_変数ならび).

変数のみ取り出して(_自然数の間に変数が挿入されたならび,_変数ならび) :-
        findall(_変数,(
                    member(_変数,_自然数の間に変数が挿入されたならび),
                    var(_変数)),
                _変数ならび).

変数に演算子を当て嵌める([]).
変数に演算子を当て嵌める([_変数|R]) :-
        member(_演算子,[+,-,*,//]),
        変数に演算子を当て嵌める(R).

式を計算する(_自然数の間に変数が挿入されたならび,_期待した自然数,_式) :-
        一旦文字列に変換して(_自然数の間に変数が挿入されたならび,_式文字列),
        文字列から式を生成する(_式文字列,_式),
        _期待した自然数 is _式,!.

一旦文字列に変換して(_自然数の間に変数が挿入されたならび,_式文字列) :-
        atomic_list_concat(_自然数の間に変数が挿入されたならび,_式文字列).

文字列から式を生成する(_式文字列,_式) :-
        read_term_from_atom(_式文字列,_式,[]).