2013-09-03 1 views
2

Ну, в течение последних нескольких часов я пытался поменять второй элемент данного списка его предпоследним элементом (вторым последним). Дайте список [a,b,c,d,e,f], я хочу получить [a,e,c,d,b,f]. Например:Сменить второй элемент и элемент prelast из списка пролог

correct(List1,X,List2) 
?-correct([a,y,b,c,d,e,x,f],x,List2). 
List2[a,x,b,c,d,e,y,f]. 
  • List1 список я должен поменять второй и предпоследний (второй) последний элемент.
  • X - предпоследний элемент.
  • List2 - новый список с замененными элементами.

ответ

1

Это будет работать для списков длины 4 или больше:

correct([H1|[H2|T1]], X, [H1|[X|T2]]) :- 
    reverse(T1, [HR|[X|TR]]), 
    reverse([HR|[H2|TR]], T2). 

| ?- correct([1,2,3,4,5,6], X, L). 

L = [1,5,3,4,2,6] 
X = 5 

(1 ms) yes 
| ?- 

Вы можете включать короткие случаи, если это намерение, добавив еще два предиката, в результате чего решение:

correct([A,X], X, [X,A]). 
correct([A,X,B], X, [A,X,B]). 
correct([H1|[H2|T1]], X, [H1|[X|T2]]) :- 
    reverse(T1, [HR|[X|TR]]), 
    reverse([HR|[H2|TR]], T2). 
+0

спасибо большое за ваш быстрый answer.Now я понимаю, как я могу решить эту проблему. – John

+0

Предикат 'correct/2' может быть определен таким образом, чтобы список ввода проходил только один раз и не дважды вызывал предикат' reverse/2' (что, btw, не является стандартным предикатом, хотя часто определяется в библиотеке утилиты список предикатов). –

+0

@PauloMoura Согласен, хотя 'reverse/2' определен в GNU Prolog и SWI Prolog. Это был «простой», если менее эффективный подход. – lurker

1

другой доступный встроенный является добавление/2:

3 ?- [user]. 
correct(L, X, R) :- append([[A,B],C,[X,E]], L), append([[A,X],C,[B,E]], R). 
|: 
% user://2 compiled 0.02 sec, 2 clauses 
true. 

4 ?- correct([1,2,3,4,5,6], X, L). 
X = 5, 
L = [1, 5, 3, 4, 2, 6] ; 

Мне нравится mbratch one (+1), может быть, это решение более интуитивное.

+0

Это хорошо, CapelliC, я добирался до «append», и вы его нашли. :) – lurker

2

Решения, которые разместили mbratch и CapelliC как неудача в течение следующего базового случая:

?- correct([a,y], X, List2). 
false. 

Следующее решение заботится об этом базовом случае и не полагаться на список предикатах, которые могут или не могут быть доступны , Он проходит список раз и является более эффективным, чем другие два решения:

correct([PreLast, Second], Second, [Second, PreLast]) :- 
    !. 
correct([First, Second, Last], Second, [First, Second, Last]) :- 
    !. 
correct([First, Second| InRest], PreLast, [First, PreLast| OutRest]) :- 
    correct_aux(InRest, Second, PreLast, OutRest). 

correct_aux([PreLast, Last], Second, PreLast, [Second, Last]) :- 
    !. 
correct_aux([Other| InRest], Second, PreLast, [Other| OutRest]) :- 
    correct_aux(InRest, Second, PreLast, OutRest). 

Примеры запросов:

?- correct([a,b], X, List). 
X = b, 
List = [b, a]. 

?- correct([a,b,c], X, List). 
X = b, 
List = [a, b, c]. 

?- correct([a,b,c,d], X, List). 
X = c, 
List = [a, c, b, d]. 

?- correct([a,b,c,d,e], X, List). 
X = d, 
List = [a, d, c, b, e]. 
+0

Хорошее решение, Пауло (+1). Я думаю, что вы оставили список случаев с длиной 3. – lurker

+0

Хороший улов. Самое простое решение состоит в том, чтобы также добавить список длины три в качестве второго базового варианта. Я отредактировал код соответственно. Но можно ли это решение упростить? Все эти сокращения беспокоят меня. –

+0

Этот ответ завершается также для 'правильных (L, X, [a, b, c, d, e])'. Сокращения, однако, вызывают неполноту: 'correct (L, X, L)' имеет более одного ответа. – false

 Смежные вопросы

  • Нет связанных вопросов^_^