2014-02-19 2 views
2

프롤로그에서이 문제를 해결하고 싶습니다. 목록 [3,2,4,1,5,7,8,9,10,8]을주고 예를 들어목록의 각 요소에 대한 설명 프롤로그

All elements on the left of it are smaller than it and all the elements on the right of it are larger than it.

이 대답은 지금까지 내가했습니다 5,7

될 것이다 : 나는이 조건을 만족 목록의 모든 요소를 ​​찾기 위해 자연수의 목록을 제공합니다 엘리먼트가 위에 설명 된 조건을 만족하면 true 또는 false를 반환하는리스트의 엘리먼트가 주어진다면이 함수를 만들도록한다.

check(Elem, List) :- 
    seperate(Elem, List, List1, List2), 
    lesser(Elem, List1, X1), 
    bigger(Elem, List2, X2), 
    size(X1, L1), 
    size(X2, L2), 
    size(List, L3), 
    match(L1, L2, L3), 

이제 목록이 주어진 다른 조건부를 만들고 싶습니다. 목록의 각 요소에 대해 위 계산을 수행합니다. 사실 하나 이상의 요소가 그것을 만족시킬 수 있기 때문에 문제를 만족시키는 모든 요소를 ​​가진 또 다른 목록을 만들고 싶습니다.

질문은 ?-predicate_name([[3,2,4,1,5,7,8,9,10,8],N).과 같으며 결과는 요소 목록입니다.

Sry Prolog의 올바른 용어를 사용하지 않는 경우입니다. 순차 논리 언어로하고 싶은 것이 더 구체적이라는 것을 설명 할 것입니다. 그러나 그렇게 생각하는 것은 좋지 않습니다. 술어 검사가 목록의 목록과 요소를 제공하는 함수로 간주되면 요소가 문제의 조건을 충족시키는 지 여부에 상관없이 참 또는 거짓을 반환합니다. 이제 목록의 각 요소를 구문 분석하고 각각에 대해 함수 검사를 호출하려고합니다. 그게 사실이라면 나는 다른 요소에 a.k.a 결과를 추가 할 것이다. 프롤로그에서이 작업을 수행하려고하지만 목록을 반복하는 방법을 모르겠습니다.

+1

'check' 관계에는 세 개의 인수가 있지만'check2' 관계는 두 개의 인수로 호출합니다. 'check'가 변수'List2'에서 하나의 항목, 즉'Elem'을 포함하는 목록으로 돌아가 길 원합니까? – traitor

+1

작성한 것은 모든 요소에 대해 점검이 사실인지 여부를 테스트합니다. 정확히 무엇을 원하니? "Do this Do that"에서 "do that do"와 함께 더 자세히 설명하십시오. – User

+0

@alpha 나는 포스트를 편집했는데, 나는 한 가지 주장을 잊어 버렸습니다. – JmRag

답변

2

나는이 문제에 대해 다른 접근법을 취할 것입니다.

"중간"값의 기준을 충족하는 모든 값을 찾고 싶습니다.이 값은 목록에있는 값보다 큰 값으로 정의 된 값과 이후의 모든 값보다 작은 값으로 정의됩니다.

의미 M 같은 조건 mid(L, M) 정의는 L의 "중간"값입니다

mid([X|T], X) :-   % The first element of a list is a "mid" if... 
    less(X, T).   % it is less than the rest of the list 
mid([X|T], M) :-   % M is a "mid" of [X|T] if... 
    mid(T, X, M).  % M is a "mid" > X 
         % (NOTE: first element is not a "mid" by definition) 

mid([X|T], LastM, X) :- % X is a "mid" > Y if... 
    X > LastM,   % X > the last "mid" 
    less(X, T).   % X < the rest of the list, T 
mid([X|T], LastM, M) :- % Also, M is a "mid" if... 
    Z is max(X, LastM), % Z is the larger of X and the last "mid" 
    mid(T, Z, M).  % M is the "mid" of T which is > Z 

less(X, [Y|T]) :-  % X is less than the list [Y|T] if... 
    X < Y,    % X < Y, and 
    less(X, T).   % X < the tail, T 
less(_, []).    % An element is always less than the empty list 
각 쿼리는 다음 "중간"발견 할 것이다

: 다음

| ?- mid([3,2,4,1,5,7,8,9,10,8], M). 

M = 5 ? ; 

M = 7 ? ; 

no 

그들이 캡처 할 수 있습니다 a findall :

mids(L, Ms) :- 
    findall(M, mid(L, M), Ns). 

| ?- mids([3,2,4,1,5,7,8,9,10,8], Ms). 

Ms = [5,7] 

yes 

| ?- mids([2], L). 

L = [2] 

(1 ms) yes 

이것은 "중역 (mids)"의 몇 가지 속성을 이용하지 않기 때문에 아마도 가장 계산 상 효율적인 솔루션은 아닙니다. 예를 들어, "mids"는 모두 함께 연속적으로 클러스터링됩니다. 따라서 "mid"가 발견되면 자체적으로 "중간"이 아닌 요소가 계속 발생하면 검색을 계속하는 것이 의미가 없습니다. 효율성이 목표라면, 이러한 종류의 아이디어는 논리적 인 과정에 적용될 수 있습니다. 대한 maplist 날을 생각 나게 @false하는 신용와

부칙

은, 위의 선언문 호출 less(X, T) 위의 구현에 less의 정의를 제거 maplist(<(X), T)로 대체 될 수있다.

+0

감사하다는 말을 찾을 수 없습니다! 너의 시간과 노력을 많이 Thx – JmRag

+0

@ 마리오 아무런 문제. 프롤로그와 잘 어울리는 논리적 인 언어로 문제를 표현하는 것은 솔루션을 찾는 데 많은 도움이됩니다. – lurker

+0

내가보기에 나는 프롤로그에서 배울 것이 많다 :) – JmRag

3

여기는 DCG를 사용하는 버전이며 산술적으로 비교한다고 가정합니다.

list_mid(L, M) :- 
    phrase(mid(M), L). 

mid(M) --> 
    seq(Sm), 
    [M], 
    {maplist(>(M),Sm)}, 
    seq(Gr), 
    {maplist(<(M),Gr)}. 

seq([]) --> 
    []. 
seq([E|Es]) --> 
    [E], 
    seq(Es). 

종종 더 이상 최적화 할 가치가 없습니다. 첫 번째 seq(Sm)과 그 뒤의 maplist/2은 함께 병합 될 수 있습니다. 이것은 조금 까다 롭습니다. 왜냐하면 Sm = []Sm = [_|_]을 별도로 처리해야하기 때문입니다.

mid(M) --> 
    ( [M] 
    | max(Mx), 
     [M], 
     {Mx < M} 
    ), 
    min(M). 

max(M) --> 
    [E], 
    maxi(E, M). 

maxi(E, E) --> 
    []. 
maxi(E, M) --> 
    [F], 
    {G is max(F,E)}, 
    maxi(G, M). 

min(_) --> 
    []. 
min(M) --> 
    [E], 
    {M < E}, 
    min(M). 
+1

쿨 (+1). 나는 DCG 접근법을 시도하려고 생각하고 그것에 도달하지 못했습니다. – lurker

+1

죄송합니다. maplist (> (M), Sm) 및 maplist (<(M), Gr)를 의미한다고 생각합니다. – lurker

+1

@mbratch : 고마워요! – false

관련 문제