このディレクトリの索引
#  c137 #534
#  [1] 授業単元: Visual Studio 入門  
#  [2] 問題 半乱順列の関数作成  
#  

:- op(300,xf,回).
:- op(700,xf,切る).

半乱順列の作成(_置換指定,_対象ならび,_半乱順列ならび) :-
        整列(_対象ならび,_整列したならび),
        整列したならび乱す(_置換指定,_整列したならび,_半乱順列ならび).

整列したならび乱す(最初と最後の要素を入れ替える,L1,L2) :-
        '最初と最後の要素を入れ替えて、整列したならびを乱す'(L1,L2).
整列したならびを乱す(N 回 切る,L1,L2) :-
        'N回切って、整列したならびを乱す'(N,L1,L2).
整列したならびを乱す([[N1,N2]|R],L1,L2) :-
        '入れ替え位置指定ならびから、整列したならびを乱す'([[N1,N2]|R],L1,L2).

'最初と最後の要素を入れ替えて、整列したならびを乱す'(L1,L2) :-
        [A|R]=L3,
        append(L4,[B],R),
        append([B|L4],[A],L2),!.

'N回切って、整列したならびを乱す'(0,L,L) :- !.
'N回切って、整列したならびを乱す'(N,L1,L2) :-
        入れ替え位置を得る(L1,N1,N2),
        ならびの交換(N1,N2,L1,L3),
        succ(N1,N),
        'N回切って、整列したならびを乱す'(N1,L1,L2).

入れ替え位置を得る(L1,N1,N2) :-
        length(L1,Len),
        N1 is random mod Len,
        N2 is random mod Len.

'入れ替え位置指定ならびから、整列したならびを乱す'([],L,L) :- !.
'入れ替え位置指定ならびから、整列したならびを乱す'([[N1,N2]|R],L1,L2) :-
        ならびの交換(N1,N2,L1,L3),
        '入れ替え位置指定ならびから、整列したならびを乱す'(R,L3,L2).

ならびの交換(M,N,_対象ならび,_交換したならび) :-
        'M番目の要素と前後'(M,L1,A,R1),
        'N番目の要素と前後'(N,L2,B,R2),
        要素を入れ替えながらならびの再構成(L1,A,R1,L2,B,R2).

'M番目の要素と前後'(M,L1,A,R1) :-
        M1 is M - 1,
        append(L1,[A|R1],_対象ならび),
        length(L1,M1),!.

'N番目の要素と前後'(N,L2,B,R2) :-
        N1 is N - 1,
        append(L2,[B|R2],_対象ならび),
        length(L2,N1),!.

要素を入れ替えながらならびの再構成(L1,A,R1,L2,B,R2) :-
        append(L1,[B|R1],L3),
        append(L4,[_|R3],L3),
        length(L4,N1),
        append(L4,[A|R3],_交換したならび),!.