Max Bummer
Max Bummer

Reputation: 59

Prolog programs - how to make it work?

I have these two programs and they're not working as they should. The first without_doubles_2(Xs, Ys)is supposed to show that it is true if Ys is the list of the elements appearing in Xs without duplication. The elements in Ys are in the reversed order of Xs with the first duplicate values being kept. Such as, without_doubles_2([1,2,3,4,5,6,4,4],X) prints X=[6,5,4,3,2,1] yet, it prints false.

without_doubles_2([],[]).
without_doubles_2([H|T],[H|Y]):- member(H,T),!,
                                 delete(H,T,T1),
                                 without_doubles_2(T1,Y).

without_doubles_2([H|T],[H|Y]):-    without_doubles_2(T,Y).

reverse([],[]).
reverse([H|T],Y):- reverse(T,T1), addtoend(H,T1,Y).

addtoend(H,[],[H]).
addtoend(X,[H|T],[H|T1]):-addtoend(X,T,T1).


without_doubles_21(X,Z):-  without_doubles_2(X,Y),
                           reverse(Y,Z).

The second one is how do I make this program use a string? It's supposed to delete the vowels from a string and print only the consonants.

deleteV([H|T],R):-member(H,[a,e,i,o,u]),deleteV(T,R),!.
deleteV([H|T],[H|R]):-deleteV(T,R),!.
deleteV([],[]).

Upvotes: 1

Views: 339

Answers (2)

CapelliC
CapelliC

Reputation: 60034

deleteV/2 could make use of library(lists):

?- subtract("carlo","aeiou",L), format('~s',[L]).
crl
L = [99, 114, 108].

while to remove duplicates we could take advantage from sort/2 and select/3:

nodup(L, N) :-
    sort(L, S),
    nodup(L, S, N).

nodup([], _S, []).
nodup([X|Xs], S, N) :-
    ( select(X, S, R) -> N = [X|Ys] ; N = Ys, R = S ),
    nodup(Xs, R, Ys).

test:

?- nodup([1,2,3,4,4,4,5,2,7],L).
L = [1, 2, 3, 4, 5, 7].

edit much better, from ssBarBee

?- setof(X,member(X,[1,2,2,5,3,2]),L).
L = [1, 2, 3, 5].

Upvotes: 0

l4mpi
l4mpi

Reputation: 5148

Your call to delete always fails because you have the order of arguments wrong:

delete(+List1, @Elem, -List2)

So instead of

delete(H, T, T1)

You want

delete(T, H, T1)

Finding an error like this is simple using the trace functionality of the swi-prolog interpreter - just enter trace. to begin trace mode, enter the predicate, and see what the interpreter is doing. In this case you would have seen that the fail comes from the delete statement. The documentation related to tracing can be found here.

Also note that you can rewrite the predicate omitting the member check and thus the third clause, because delete([1,2,3],9001,[1,2,3]) evaluates to true - if the element is not in the list the result is the same as the input. So your predicate could look like this (name shortened due to lazyness):

nodubs([], []).
nodubs([H|T], [H|Y]) :- delete(T, H, T1), nodubs(T1, Y).

For your second question, you can turn a string into a list of characters (represented as ascii codes) using the string_to_list predicate.

As for the predicate deleting vovels from the string, I would implement it like this (there's probably better solutions for this problem or some built-ins you could use but my prolog is somewhat rusty):

%deleteall(+L, +Elems, -R)
%a helper predicate for deleting all items in Elems from L
deleteall(L, [], L).
deleteall(L, [H|T], R) :- delete(L, H, L1), deleteall(L1, T, R).

deleteV(S, R) :-
    string_to_list(S, L),         %create list L from input string
    string_to_list("aeiou", A),   %create a list of all vovels
    deleteall(L, A, RL),          %use deleteall to delete all vovels from L
    string_to_list(R, RL).        %turn the result back into a string

Upvotes: 2

Related Questions