このディレクトリの索引
#  お題: 
#  例:数列[3,1,-7,1,5]について、 
#  ->[4,-3,-2,3] (累計) 
#  ->12 (絶対値の合計) 
#  のように計算する。 
#  最初の数列の並び順を変えると、最後の合計計も変わる。 
#  任意数列について、上記合計が最小になるように並び替える関数を作成

'例:数列[3,1,-7,1,5]について、
->[4,-3,-2,3] (累計)
->12 (絶対値の合計)
のように計算する。
任意数列について、上記合計が最小になるように並び替える'(_数列,_最小となる数列) :-
        絶対値の合計が最小になるように並び替える(_数列,_,_最小となる数列).

絶対値の合計が最小になるように並び替える(_数列,_最小の絶対値,_絶対値の合計が最小となる数列) :-
        length(_数列,_要素数),
        setof([_絶対値の合計,_順列],
                [_数列,_要素数,_順列,_絶対値の合計] ^ 並べ替える(_数列,_要素数,_順列,_絶対値の合計),_絶対値_数列ならび),
        絶対値の合計が最小となる数列を得る(_絶対値_数列ならび,_最小の絶対値,_絶対値の合計が最小となる数列).

並べ替える(_数列,_要素数,_順列,_絶対値の合計) :-
        順列(_数列,_要素数,_順列),
        絶対値の合計(_順列,_絶対値の合計).

絶対値の合計が最小となる数列を得る(_絶対値_数列ならび,_最小の絶対値,_絶対値の合計が最小となる数列) :-
        findmin(_絶対値,(
                            member([_絶対値,_],_絶対値_数列ならび)),
                _最小の絶対値),
        member([_最小の絶対値,_絶対値の合計が最小となる数列],_絶対値_数列ならび).

絶対値の合計([_値],_絶対値の合計) :-
        _絶対値の合計 is abs(_値),!.
絶対値の合計(_値ならび,_絶対値の合計) :-
        累計の途中経過を得る(_値ならび,_累計の途中経過ならび),
        要素の絶対値の合計(_累計の途中経過ならび,_絶対値の合計).

累計の途中経過を得る([_],[]).
累計の途中経過を得る([_数_1,_数_2|R1],[_累計の途中経過|R2]) :-
        _累計の途中経過 is _数_1 + _数_2,
        累計の途中経過を得る([_累計の途中経過|R1],R2).

要素の絶対値の合計(_累計の途中経過ならび,_絶対値の合計) :-
        findsum(_絶対値,(
                    member(_値,_累計の途中経過ならび),
                    _絶対値 is abs(_値)),
                _絶対値の合計).

順列(_,0,[]).
順列(L1,N,[A|R]) :-
        select(A,L1,R1),
        N_1 is N - 1,
        順列(R1,N_1,R).

findmin(V,P,Min) :-
        findall(V,P,L),
        min_list(L,Min).

findsum(V,P,Sum) :-
        findall(V,P,L),
        sum_list(L,Sum).