프롤로그의 목록 목록에서 산술 연산을 수행하는 방법

Nov 15 2020

목록 목록을 가져 와서 목록의 헤드 요소를 가져와 목록 목록의 다른 모든 요소와 비교하는 함수를 작성하고 있습니다. 재귀를 사용하는 것이 목록에서 대부분의 작업을 수행하는 방법이라는 것을 알고 있지만 이것을 목록 목록으로 변환하는 데 어려움을 겪었습니다. 이것이 내가 지금까지 생각 해낸 것입니다.

compareElements([H|T]) :-
    compareHeadList(H,T).

compareHeadList([H|T],RestOfList) :-
    compare(T,H,GreaterList,LesserList),
    compareRestList(RestOfList,H).

compareRestList(X,[HA|TA]) :-
    compare(HA,X,GreaterList,LesserList),
    compareRestList(X,TA).

compare([HA|TA],X,GreaterList,LesserList) :-
    X @> HA -> GreaterList = [HA|GreaterTail],
    compare(TA,X,GreaterTail,LesserList);
    LesserList = [HA|LesserTail],
    compare(TA,X,GreaterList,LesserTail).
compare([_|TA],X,GreaterList,LesserList) :-
    compare(TA,X,GreaterList,LesserList).

예를 들면 :

    compareElements(LoL).
    Where Lol = [[6,4,8],[7,9,2],[1,3,0]]
    My Goal is to compare 6 with every other element in the Lol, 
    so that GreaterList = [8,7,9], and LesserList = [4,2,1,3,0]

코드가 어떻게 실행되어야하는지에 대한 내 생각은 compareElements ()가 목록 목록을 가져온 다음 compareHeadList ()를 호출하여 첫 ​​번째 목록의 머리를 해당 목록의 나머지 요소와 비교하는 것입니다. 마지막으로 compareRestList ()는 비교할 Head 요소와 나머지 목록 목록을 가져 와서 비교 함수를 호출하고 true를 반환해야합니다.

내 문제는 내가 목록을 writeLn () 할 때 메모리 주소처럼 보이는 "9c78"과 같은 시퀀스를 출력하는 요소를 확인하는 것입니다. 요소를 적절하게 비교하고 목록에 올바로 밀어 넣고 있는지 아니면 이런 일을 일으키는 다른 부분이 있는지 궁금합니다.

답변

MaxB Nov 15 2020 at 20:16
head_head([[X|_]|_], X).

split_list(_, [], [], []).
split_list(K, [H|T],     G, S) :- H = K, split_list(K, T, G, S).
split_list(K, [H|T], [H|G], S) :- H > K, split_list(K, T, G, S).
split_list(K, [H|T], G, [H|S]) :- H < K, split_list(K, T, G, S).

split_lol(X, G, S) :- head_head(X, K), append(X, L), split_list(K, L, G, S).

테스트:

?- split_lol([[6,4,8],[7,9,2],[1,3,0]], G, S).
G = [8, 7, 9],
S = [4, 2, 1, 3, 0] .

?-

일부 kewl "뒤로"기능 Prolog는 다음을 제공합니다.

?- split_lol([[6,X,Y], [A, B]], [7, 8], [2, 1]).
X = 7,
Y = 8,
A = 2,
B = 1 ;
X = 7,
Y = 2,
A = 8,
B = 1 ;
X = 7,
Y = 2,
A = 1,
B = 8 ;
X = 2,
Y = 7,
A = 8,
B = 1 ;
X = 2,
Y = 7,
A = 1,
B = 8 ;
X = 2,
Y = 1,
A = 7,
B = 8 ;
false.

?- 
IsabelleNewbie Nov 16 2020 at 21:59

귀하의 접근 방식이 작동하도록 만들 수 있습니다. 누락 된 항목에 대한 힌트는 Prolog에서 내 보낸 다음 경고를 참조하십시오.

Warning: /home/isabelle/lol.pl:4:
    Singleton variables: [GreaterList,LesserList]
Warning: /home/isabelle/lol.pl:8:
    Singleton variables: [GreaterList,LesserList]

싱글 톤 변수 경고는 심각 합니다. 그들은 일반적으로 프로그램을 무의미하게 만드는 종류의 오타를 만들었거나 (이 경우와 같이) 계산의 일부 부분을 아직 다른 부분과 연결하지 않았다고 말합니다. 프로그램에서 중첩 된 목록 중 하나에 대해 더 큰 / 작은 목록을 계산할 때도이를 다른 중첩 된 목록의 더 큰 / 작은 목록과 연결하지 않으므로 완전한 답을 얻을 수 없습니다.

목록 중 하나의 더 큰 목록이 [8]이고 다른 목록의 [7, 9]경우이면 전체 더 큰 목록을 구성하고 싶습니다 [8, 7, 9]. Prolog의 일반적인 방법은 실제로 부분 목록 만 계산 하는 것입니다. 꼬리가 []변수 가 아닌 목록 입니다. 이 예에서 부분 목록을 [8 | Tail]계산 한 다음 다음 계산이와 통합되도록 요청 Tail하면의 결합 된 부분 목록을 얻습니다 [8, 7, 9 | Tail2]. Tail2와 통합 []하면 결국 목록이 닫힙니다.

다음은이 접근 방식에 적용되고 좀 더 명시적인 이름을 사용하는 코드입니다.

list_element_greater_smaller([], _Y, GreaterTail, GreaterTail, SmallerTail, SmallerTail).
list_element_greater_smaller([X | Xs], Y, Greater, GreaterTail, Smaller, SmallerTail) :-
    (   X > Y
    ->  Greater = [X | Greater1],
        list_element_greater_smaller(Xs, Y, Greater1, GreaterTail, Smaller, SmallerTail)
    ;   Smaller = [X | Smaller1],
        list_element_greater_smaller(Xs, Y, Greater, GreaterTail, Smaller1, SmallerTail) ).

lists_element_greater_smaller([], _Y, GreaterTail, GreaterTail, SmallerTail, SmallerTail).
lists_element_greater_smaller([Xs | Xss], Y, Greater, GreaterTail, Smaller, SmallerTail) :-
    list_element_greater_smaller(Xs, Y, Greater, GreaterTail1, Smaller, SmallerTail1),
    lists_element_greater_smaller(Xss, Y, GreaterTail1, GreaterTail, SmallerTail1, SmallerTail).

lists_greater_smaller([[Y | Xs] | Xss], Greater, Smaller) :-
    lists_element_greater_smaller([Xs | Xss], Y, Greater, [], Smaller, []).

시간을내어 Tail모든 계산을 통해 변수가 스레드 된 다음 [].

이것은 다음과 같이 작동합니다.

?- lists_greater_smaller([[6,4,8],[7,9,2],[1,3,0]], Greater, Smaller).
Greater = [8, 7, 9],
Smaller = [4, 2, 1, 3, 0].

목록의 중첩 깊이가 고정되어있는 한,이 모든 것을 작성하는 더 간단한 방법도 있습니다 . "플랫"목록에 대한 재귀를 수행하는 방법과 매우 유사하게 중첩 된 목록에 단일 재귀 술어를 작성할 수 있습니다 . 구별 할 세 가지 경우가 있습니다.

  • 전체 외부 목록이 비어 있습니다
  • 첫 번째 중첩 목록이 비어 있습니다.
  • 첫 번째 중첩 목록에는 머리와 꼬리가 있습니다.

이 접근 방식은 다음과 같습니다.

lists_greater_smaller2([[Y | Xs] | Xss], Greater, Smaller) :-
    lists_element_greater_smaller2([Xs | Xss], Y, Greater, Smaller).

lists_element_greater_smaller2([], _Y, [], []).
lists_element_greater_smaller2([[] | Xss], Y, Greater, Smaller) :-
    lists_element_greater_smaller2(Xss, Y, Greater, Smaller).
lists_element_greater_smaller2([[X | Xs] | Xss], Y, Greater, Smaller) :-
    (   X > Y
    ->  Greater = [X | Greater1],
        lists_element_greater_smaller2([Xs | Xss], Y, Greater1, Smaller)
    ;   Smaller = [X | Smaller1],
        lists_element_greater_smaller2([Xs | Xss], Y, Greater, Smaller1) ).

다시 한번:

?- lists_greater_smaller2([[6,4,8],[7,9,2],[1,3,0]], Greater, Smaller).
Greater = [8, 7, 9],
Smaller = [4, 2, 1, 3, 0] ;
false.