Double elements in list using prolog?

北战南征 提交于 2020-01-05 07:11:11

问题


How can I double even numbers in a list in Prolog? For example:

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

The result should be:

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

Thank you!


回答1:


Even check can probably be done better, but it kinda works.

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

doubleeven([],[]).
doubleeven([H|T], [H,H|Z]) :-
    even(H),
    !,
    doubleeven(T,Z).
doubleeven([H|T], [H|Z]) :-
    doubleeven(T,Z).



回答2:


Based on iwhen/2, first define the reified test predicate eveninteger_t/2:

eveninteger_t(I, T) :- 
   iwhen(nonvar(I), ( 0 is I mod 2 -> T = true ; T = false )).

oddinteger_t(I, T) :-   % defined for the sake of completeness
   iwhen(nonvar(I), ( 1 is I mod 2 -> T = true ; T = false )).

Then, in combination with if_/3 define integers_evendups/2 like so:

integers_evendups([], []).
integers_evendups([X|Xs], [X|Zs1]) :-
   if_(evenintegers_t(X), Zs1 = [X|Zs0], Zs1 = Zs0),
   integers_evendups(Xs, Zs0).

Here's the query you gave in your question:

?- Xs = [1,2,3,5,4], integers_evendups(Xs,Zs).
Xs = [1, 2, 3,5, 4 ],
Zs = [1,2,2,3,5,4,4].

Alternative #1

Based on if_//3, define dcg evenintegerdups//1:

evenintegerdups([]) --> 
   [].
evenintegerdups([X|Xs]) -->
   if_(eveninteger_t(X), [X,X], [X]),
   evenintegerdups(Xs).

Alternative #2

Using meta-predicate foldl/4 and lambdas, the code gets even shorter:

:- use_module(library(lambda)).

evenintegerdups(Xs) -->
   foldl(\X^if_(eveninteger_t(X),[X,X],[X]),Xs).


来源:https://stackoverflow.com/questions/4218477/double-elements-in-list-using-prolog

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!