Пролог: Как удалить каждый второй элемент списка - PullRequest
4 голосов
/ 09 мая 2011

Мне нужно написать программу на Прологе, которая должна удалять каждый второй элемент списка. Должно сработать так: [1,2,3,4,5,6,7] -> [1,3,5,7]

пока у меня есть это, но оно просто возвращает "ложь".

r([], []). 
r([H|[T1|T]], R) :- del(T1,[H[T1|T]], R), r(R).

del(X,[X|L],L).
del(X,[Y|L],[Y|L1]):- del(X,L,L1).

Ответы [ 5 ]

7 голосов
/ 09 мая 2011

Это в значительной степени ответ Ландеи в определенном синтаксисе Пролога:

r([], []).
r([X], [X]).
r([X,_|Xs], [X|Ys]) :- r(Xs, Ys).

Второй предикат не требуется.

4 голосов
/ 20 октября 2017

Альтернативное решение с использованием foldl / 4 :

fold_step(Item, true:[Item|Tail], false:Tail).
fold_step(_Item, false:Tail, true:Tail).

odd(List, Odd) :-
    foldl(fold_step, List, true:Odd, _:[]).

Использование:

?- odd([1, 2, 3, 4, 5, 6, 7], Odd).
Odd = [1, 3, 5, 7]

Идея состоит в том, чтобы пройти по списку, сохраняя флаг "нечетный / четный" и переключая его значение (false -> true, true -> false) на каждый элемент. Мы также постепенно строим список, добавляя те элементы, у которых флаг «нечетный / четный» равен true, и пропуская другие.

3 голосов
/ 25 октября 2017

Этот точный ответ @ code_x386 использует и foldl/4.

Давайте использовать только одно fold_step/3 предложение и , чтобы сделать отношение более общим, например:

fold_step(X, [X|Xs]+Ys, Ys+Xs).

list_odds_evens(List, Odds, Evens) :-
   foldl(fold_step, List, Odds+Evens, []+[]).

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

?– list_odds_evens([a,b,c,d,e,f], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e]
?– list_odds_evens([a,b,c,d,e,f,g], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e,g]

Редактировать

Почему бы не использовать на один пункт меньше и покончить с предикатом fold_step/3? на помощь!

:- use_module(<a href="http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl" rel="nofollow noreferrer">library(lambda)</a>).

list_odds_evens(List, Odds, Evens) :-
   foldl(\X^([X|Xs]+Ys)^(Ys+Xs)^true, List, Odds+Evens, []+[]).
2 голосов
/ 28 октября 2017

Другая возможность состоит в использовании DCG, они, как правило, заслуживают внимания при описании списков:

list_oddindices(L,O) :-
   phrase(oddindices(L),O).  % the list O is described by oddindices//1

oddindices([]) -->           % if L is empty
   [].                       % O is empty as well
oddindices([X]) -->          % if L has just one element
   [X].                      % it's in O
oddindices([O,_E|OEs]) -->   % if L's head consists of at least two elements
   [O],                      % the first is in O
   oddindices(OEs).          % the same holds for the tail

Это, конечно, менее элегантно, чем решения, использующие foldl / 4, но код очень легко читается, ноон решает задачу, описанную ОП, и работает в обоих направлениях:

?- list_oddindices([1,2,3,4,5,6,7],O).
O = [1, 3, 5, 7] ;
false.

?- list_oddindices(L,[1,3,5,7]).
L = [1, _G4412, 3, _G4418, 5, _G4424, 7] ;
L = [1, _G4412, 3, _G4418, 5, _G4424, 7, _G4430] ;
false.
0 голосов
/ 09 мая 2011

У меня нет Пролога, чтобы попробовать его, и я немного заржавел, но это должно быть в духе

r([]) :- [].
r([X]) :- [X].
r([X,Y|Z]) :- R=r(Z),[X|R].

[Изменить]

Конечно, подушка верна. Мое решение будет работать на функциональных языках, таких как Haskell или Erlang:

--Haskell
r [] = []
r [x] = [x]
r (x:_:xs) = x : (r xs)

В Прологе вы должны «вытянуть» правые стороны в список аргументов, чтобы вызвать объединение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...