Return vowels from word - prolog

I've got this work to do and my teacher gave me a prolog file with the following facts:
vowel(a).
vowel(e).
vowel(i).
vowel(o).
vowel(u).
consonant(b).
consonant(c).
consonant(d).
consonant(f).
consonant(g).
consonant(h).
consonant(j).
consonant(k).
consonant(l).
consonant(m).
consonant(n).
consonant(p).
consonant(q).
consonant(r).
consonant(s).
consonant(t).
consonant(v).
consonant(w).
consonant(x).
consonant(y).
consonant(z).
And I need to create a rule that is able to return the vowels. How can I do that?
The output would be something like this:
blafoo([s,a,r,a], X).
X = [a].
I can't use any prolog predicate.

If you are mentioning both vowel/1 and consonant/1, you might be expected to write a pure, monotonic version. After all, why do you mention consonant/1?
word_vowels([], []).
word_vowels([C|Xs], Vs) :-
consonant(C),
word_vowels(Xs, Vs).
word_vowels([V|Xs], [V|Vs]) :-
vowel(V),
word_vowels(Xs, Vs).
?- word_vowels([a,m,a,z,o,n],Vs).
Vs = [a,a,o]
; false.
Alternatively using tfilter/3:
vowel_truth(C,true) :-
vowel(C).
vowel_truth(V,false) :-
consonant(V).
?- tfilter(vowel_truth,[a,m,a,z,o,n],Vs).
Vs = [a,a,o]
; false.

setof/3 could be a good choice here:
?- setof(X,(member(X,[a,m,a,z,o,n]),vowel(X)),L).
L = [a, o].

If your Prolog implements it, I would go with standard ISO sub_atom/5
?- W = amazon, sub_atom(W, _,1,_, C).
W = amazon,
C = a ;
W = amazon,
C = m ;
...
then
blafoo(Word, Wovel) :- sub_atom(Word, _,1,_, Wovel), vowel(Wovel).
edit after comment
Prolog doesn't 'returns' things, but you could always use a more appropriate naming and implementation for the relation, for instance like
word_vowels(Word, Wovels) :-
findall(Wovel, (sub_atom(Word, _,1,_, Wovel), vowel(Wovel)), Wovels).

Related

Is there a non-unifying alternative to member/2 in SWI-Prolog?

In prolog, the difference between A = B and A == B is that = tries to unify A with B, while == will only succeed if A and B are already unified.
member/2 does seem to perform unification.
Example session:
?- A = B.
A = B.
?- A == B.
false.
?- member(A, [B]).
A = B.
I have been looking but I can't find a non-unifying alternative to member/2, but not found anything. Is there something built in or do I have to invent my own thing? As I'm rather new to Prolog I don't trust myself with writing a performant version of this.
EDIT:
I came up with the following, though I don't know if the cut is correct. Without it, it seems to deliver two answers for that branch of the code (true, followed by false) though. I'd also still like to know if there is a standard library function for this.
member_eq(_, []) :-
false.
member_eq(X, [H|_]) :-
X == H,
!.
member_eq(X, [_|T]) :-
member_eq(X, T).
You may slightly modify builtin predicate member/2 to use ==/2 instead of unification:
member_not_bind(X, [H|T]) :-
member_not_bind_(T, X, H).
member_not_bind_(_, X, Y):- X==Y.
member_not_bind_([H|T], X, _) :-
member_not_bind_(T, X, H).
Sample run:
?- L=[a,b,c(E)], member_not_bind(A, L).
false.
?- A=c(E),L=[a,b,c(E)], member_not_bind(A, L).
A = c(E),
L = [a, b, c(E)].
I leave this here as it solves a related question (checking if X may unify with any item in L without actually performing the bindings)
You can use double negation like this:
member_not_bind(X, L):- \+(\+(member(X, L))).
Sample runs:
?- A=c(e),L=[a,b,c(E)], member_not_bind(A, L).
A = c(e),
L = [a, b, c(E)].
?- A=d(E),L=[a,b,c(E)], member_not_bind(A, L).
false.

Prolog: "Vanilla" metainterpreter with builtins

This answer by Jan Burse shows one of the simplest implementations of a metainterpreter in Prolog:
solve(true) :- !.
solve((A,B)) :- !, solve(A), solve(B).
solve(H) :- clause(H,B), solve(B).
I would like to extend this interpreter so that it can call builtins. The vanilla one isn't able to handle calls such as solve(member(X, [1,2,3,4])). Is this possible using ISO predicates? If not, is it possible using SWI-Prolog predicates?
I think predicate_property/2 may be useful for your task.
As the name already implies, this predicate relates a predicate (head) to one ore more properties.
For example:
?- predicate_property((A,B), P).
P = interpreted ;
P = visible ;
P = built_in ;
P = static ;
P = imported_from(system) ;
etc.
From such properties, you can deduce whether a predicate is built-in, and the call it directly.
It is also available in SICStus.
Beware though: Not all built-in predicates retain their semantics when called directly. I think discussing what they are and how to interpret them would be well worth its own question.
Stackoverflow is refusing to accept my answer :) that was
Just call/1 them
Edit
For instance
?- [user].
solve(true) :- !.
|: solve((A,B)) :- !, solve(A), solve(B).
|: solve(H) :- clause(H,B), solve(B).
|: solve(T) :- call(T).
|: ^Dtrue.
?- solve(member(X, [1,2,3,4])).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4.
The only addition: solve(T) :- call(T).

Change name of predicate/functor in prolog

I am writing a module which uses term_expansion/2 to process a prolog source file. While doing so, I deconstruct predicates using =.. or project to its name using functor/3.
For example:
?- functor(pred(foo, bar), N, _).
N = pred.
?- pred(foo, bar) =.. L.
L = [pred, foo, bar].
Now I want to change the name of pred to (for example) pred_expanded and make it a term again, so that pred(foo, bar) becomes pred_expanded(foo, bar).
I tried append(pred, "_expanded", F) and append(pred, '_expanded', F) without success.
change_functor(Term,NewFunctor,NewTerm) :-
Term =.. [_|Args],
NewTerm =.. [NewFunctor|Args].
term_expansion(Term,ExpandedTerm) :-
functor(Term,pred,2),
change_functor(Term,pred_expanded,ExpandedTerm).
For example:
?- term_expansion(pred(foo,bar),T).
T = pred_expanded(foo, bar).
Illustrates how to use the "univ" predefined predicate. However, this is the best solution:
term_expansion(pred(A,B),pred_expanded(A,B)).
If you need to translate any functor, use atom_concat/3 as stated before:
term_expansion(Term,ExpandedTerm) :-
functor(Term,F,_),
atom_concat(F,'_expanded',NewF),
change_functor(Term,NewF,ExpandedTerm).
Example:
?- term_expansion(kk(1,2,3),N).
N = kk_expanded(1, 2, 3).

flatten in prolog - something like else

Look at my implementation of flatten : Generally, it is working. Only problem is for my_flatten([], F) - it gives F=[]; F=[[]] instead of F=[].
my_flatten(L, X) :-
my_flatten(L, X, []). %, reverse(F, X).
my_flatten([], Acc, Acc).
my_flatten([H|T], F, Acc) :-
my_flatten(H, F1, Acc),
my_flatten(T, F, F1), !.
my_flatten(X, [X|Acc], Acc).
For my_flatten(X, [1,2,3]) this program loops - it is OK, because there exist infinitely many answers, as: [[],[],[],[],1,2,3].
However, the same problem as above - for my_flatten(X, []) it should be also looping, but gives []; [[]].
Moreover result is reverser - but I don't care about it - if I uncomment reverse it will be OK - but then instead of looping mentioned above it returns false.
Can you help me change this code in such way that it returns [] for my_flatten([], X) ?
I implemented suggestions of #lurker:
my_flatten(L, F) :-
my_flatten(L, X, []),
reverse(F, X).
my_flatten([], Acc, Acc).
my_flatten([H|T], F, Acc) :-
is_list(H),
my_flatten(H, F1, Acc),
my_flatten(T, F, F1).
my_flatten([X|T], F, Acc) :-
not(is_list(X)),
my_flatten(T, F, [X|Acc]).
Before I answer your actual question, I have one comment on using flatten/2:
Don't.
Reason: flatten/2 is not a true relation. For example, we have:
?- X = [a], flatten(X, Ls).
X = [a],
Ls = [a].
but:
?- flatten(X, Ls), X = [a].
X = [a],
Ls = [[a]].
This obviously makes no sense from a logical point of view.
Please, use append/2 instead to remove precisely one level of nesting, and try implementing that.
Hint: Use dcg!
I know that flatten/2 is shown or asked for in many Prolog courses. That doesn't mean that it's useful, valuable, instructive or anything like that.
Now, to your actual question:
Always also try the most general query:
?- my_flatten(X, Ls).
X = Ls, Ls = [] ;
X = [[]],
Ls = [].
Start taking it from there: Is this answer too general, too specific or both? Think about this.
Then, think about what must hold about the arguments for this to even make sense, i.e., under what conditions can we even give sound answers that cannot be rendered non-sensical with further instantiations?
It will help you to read about instantiation-error in Prolog.

Split list on given element

I have a list C and I want to split the list using the element c in the list.
The expected results are as example:
?- split([a,c,a,a,c,a,a,a],X).
X = [[a],[a,a],[a,a,a]].
Can anybody help? Thanks in advance.
I can remove the c in the list now and here is my codes.
split([],[]).
split([H|T],[H|S]) :- H=a,split(T,S).
split([H|T],S) :- H=c,split(T,S).
Your "remove c" predicate would look better like this:
remove_c([c|T], S) :-
remove_c(T, S).
remove_c([a|T], [a|S]) :-
remove_c(T, S).
This still only works for lists that have only c and a in them.
If you want to "split", this means you at least need another argument, to collect the a's between the c's. For example:
split_on_c(List, Split) :-
split_on_c_1(List, Split, []).
split_on_c_1([], [Acc], Acc).
split_on_c_1([c|Rest], [Acc|Split], Acc) :-
split_on_c_1(Rest, Split, []).
split_on_c_1([a|Rest], Split, Acc) :-
split_on_c_1(Rest, Split, [a|Acc]).
Again, this expects lists of a and c only. It could also be done in different ways, but this is a start.
While learning a language you need to get accomplished to common abstractions already established (in simpler terms, use libraries). What about
split(In, Sep, [Left|Rest]) :-
append(Left, [Sep|Right], In), !, split(Right, Sep, Rest).
split(In, _Sep, [In]).
to be used like
?- split([a,c,a,a,c,a,a,a],c,R).
R = [[a], [a, a], [a, a, a]].
Use the meta-predicate splitlistIf/3 together with reified term equality
(=)/3, like this:
Here is the query the OP gave in the question:
?- splitlistIf(=(c),[a,c,a,a,c,a,a,a],Xs).
Xs = [[a],[a,a],[a,a,a]].
Note that above code is monotone, so the following query gives reasonable results:
?- splitlistIf(=(X),[Y,X,Y,Y,X,Y,Y,Y],Xs), Y = a, X = c.
X = c,
Y = a,
Xs = [[a],[a, a],[a, a, a]].

Resources