2014-11-21 5 views
5

가변 길이의리스트를 짝수 길이의 세리스트로 순서대로 나눠주는 함수를 만들려고합니다. 다음은 세 개로 분할하지만 프로세스는 한 번에 하나씩 각 목록에 삽입합니다.프롤로그를 사용하여 하나의리스트를 세 개로 나누기

내가 원하는 걸의 예는 다음과 같습니다

[1, 2, 3, 4, 5] -> [1, 2], [3, 4], [5] 

는 또 다른 예는 다음과 같습니다

div([], [], [], []). 
div([X], [X], [], []). 
div([X,Y], [X], [Y], []). 
div([X,Y,Z|End], [X|XEnd], [Y|YEnd], [Z|ZEnd]):- 
    div(End, XEnd, YEnd, ZEnd). 
:

[8, 7, 6, 5, 4, 3, 2, 1] -> [8, 7, 6], [5, 4, 3], [2, 1]. 

다음 코드는 한 번에 각 목록 하나에 삽입하여 그들을 분할

이 코드 출력은

입니다.
[1, 2, 3, 4, 5] -> [1, 4], [2, 5], [3] 

이 문제를 어떻게 해결할 수 있습니까?

답변

5

@Boris의 대답은 첫 번째 인수 목록의 길이를 알 수 없을 때 종료되지 않습니다. 이 참조하기 위해, 와 첫 번째 목표보다 더 보일 필요가 없습니다 : 한편

 
div(L, L1, L2, L3) :- 
    length(L, Len), false, 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

, 원래이 프로그램은 quite nice termination properties했다.

div(A,B,C,D) terminates_if b(A);b(B);b(C);b(D). 

는, 종료를 보장하기 위해, 당신은 단지 (중 A 또는 B 또는 C 또는 D가) (유한 접지입니다 구체적인 목록이 될 수있는 하나의 인수가 필요합니다 CTI는 다음과 같은 최적의 종료 속성을 준 그것은 무엇입니까 b(..) 의미). 그것은 매우 강한 종료 조건입니다. 인수가 맞지 않는 것은 정말 유감입니다! 왜 프로그램을 일반화하지 않습니까? 유일한 문제는 목록 요소를 제한한다는 것입니다. 그래서 _들에 의해리스트의 모든 요소 변수 이름을 대체합니다 :

gdiv([], [], [], []). 
gdiv([_], [_], [], []). 
gdiv([_,_], [_], [_], []). 
gdiv([_,_,_|End], [_|XEnd], [_|YEnd], [_|ZEnd]):- 
    gdiv(End, XEnd, YEnd, ZEnd). 

very same 종료 속성은이 프로그램십시오.

아아, 지금은 너무 일반적입니다.보리스의 솔루션은 이제 용도 변경 할 수 있습니다 동일한을 표현하는

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    append(As, BsCs, Zs), 
    append(Bs, Cs, BsCs). 

내 선호하는 방법은 오히려 것 :

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    phrase((seq(As), seq(Bs), seq(Cs)), Zs). 

seq//1의 정의에 대한 other answers를 참조하십시오.

+0

감사합니다. @ 실수. 나는 또한 당신이이 질문의 바깥에 나를 보여 주려고했는지 이해합니다. – Mocking

2
div(L, L1, L2, L3) :- 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

세 가지 목록을 어떻게 나누는 지 알고 있습니까? 이제 목록 L1, L2L3이 얼마나 오랫동안 기다릴 지 말씀하시지 않습니다. length/2을 사용하여 L의 길이를 얻고 술어가 지금처럼 일반 적이기를 원하지 않으면 세 개의 결과 길이를 설정할 수 있습니다.

상대적으로 길이가 비교적 길고 어떻게 든 해석해야하기 때문에 양의 정수 len과 n에 대해 len = 3n이면 len1 = len2 = len3 = n, k = 3n + 1 인 경우 len1 = n + 1, len2 = len3 = n, k = 3n + 2의 경우 len1 = len2 = n + 1, len3 = n이됩니다. 길이를 계산하는 방법을 알아 보도록하겠습니다.

div(L, L1, L2, L3) :- 
    length(L, Len), 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 
+0

나는 100 % 확실하지는 않지만 내 문제를 오해 한 것 같습니다. 첫 번째 목록을 3 개의 목록으로 분리하려고합니다. – Mocking

+0

@ 모킹 당신은 실제로이 술어가하는 것을 시험해 보았습니까? 또한 결과 목록의 길이에 제약이 있는지 여부는 여전히 불분명합니다. –

+0

죄송합니다, 제 문제를보다 명확하게하려고했습니다. 난 가변 길이의 목록을 3 개의 짝수 (또는 비교적 짝수) 목록으로 분할하려합니다. 이게 실제로 도움이 될까요? – Mocking

관련 문제