Пролог: получить список из двух подсписков, содержащий нечетные элементы позиции и четные элементы позиции.Как улучшить этот код - PullRequest
1 голос
/ 11 июня 2019

Я хотел бы спросить, если кто-нибудь знает, как улучшить (если это не оптимально) этот код.

Идея в том, что у вас есть список элементов, и я хочу вернуть список с двумя подсписками внутри него, первый подсписок должен содержать элементы, которые содержатся в нечетных позициях списка, а второй подсписок должен содержать элементы, которые содержатся в четных позициях списка.

Некоторые примеры:

?-evenAndOdd([1,2,3,4,5],[[1,3,5],[2,4]])
True.

?-evenAndOdd([a,b,c,d,e],[[a,c,e],[b,d]]).
True.

Код, который я реализовал, следующий:

evenAndOdd([],[]).

evenAndOdd([H|R],NL):-
    evenAndOddRec([H|R], [[],[]],1,NL).


evenAndOddRec([], [LOdd,LEven],_,[LOdd,LEven]).

evenAndOddRec([H|R],[LOdd,LEven],Pos,NL):-
    \+ even(Pos),
    !,
    NPos is Pos +1,
    append(LOdd,[H],NLOdd),
    evenAndOddRec(R,[NLOdd,LEven],NPos,NL).

evenAndOddRec([H|R],[LOdd,LEven],Pos,NL):-
    NPos is Pos + 1,
    append(LEven, [H], NLEven),
    evenAndOddRec(R,[LOdd, NLEven],NPos,NL).



even(N):-
    N mod 2 =:=0.

Ответы [ 2 ]

4 голосов
/ 11 июня 2019

Вы можете неявно определять четные и нечетные значения при рекурсии, беря два элемента за раз (и принимая во внимание, когда у них есть нечетное количество элементов):

evenAndOdd(L, [LOdd, LEven]):-
  evenAndOdd(L, LOdd, LEven).

evenAndOdd([], [], []).
evenAndOdd([Odd], [Odd], []).
evenAndOdd([Odd,Even|Tail], [Odd|LOdd], [Even|LEven]):-
  evenAndOdd(Tail, LOdd, LEven).
3 голосов
/ 11 июня 2019

Один из признаков того, что код не является оптимальным, заключается в том, что он убежит в лес, если вы попросите дополнительное решение в шаблоне -, +, +:

?- evenAndOdd(X, [[1,3,5], [2,4,6]]).
X = [1, 2, 3, 4, 5, 6] ;
<time passes>

Такого рода вещиявляется частым явлением, когда вручную пытаюсь сопоставить списки с индексами в Прологе.

Стилистически, я бы не стал возвращать список, содержащий ровно два списка, когда у меня могло бы быть только три аргумента вместо двух;это, в конце концов, связь между тремя списками, объединенным списком и четными и нечетными элементами.

Кроме того, просто замечая это, я не уверен, зачем здесь нужна какая-либо арифметика или какие-либо сокращения.Вот как я бы это реализовал:

evenAndOdd([], [], []).
evenAndOdd([O], [O], []).
evenAndOdd([O,E|Rest], [O|ORest], [E|ERest]) :- evenAndOdd(Rest, ORest, ERest).

Это работает со многими экземплярами:

?- evenAndOdd([1,2,3,4,5,6], O, E).
O = [1, 3, 5],
E = [2, 4, 6].

?- evenAndOdd([1,2,3,4,5], O, E).
O = [1, 3, 5],
E = [2, 4] ;
false.

?- evenAndOdd(X, [1,3,5], [2,4]).
X = [1, 2, 3, 4, 5] ;
false.

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

?- evenAndOdd(X, [1,3,5], [2,4,6,8]).
false.

?- evenAndOdd([1,2,3,4,5,6], X, [2,4,6,8]).
false.

?- evenAndOdd([1,2,3,4,5,6], X, [2,4,6]).
X = [1, 3, 5].
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...