Related
The problem is; I have a list of mixed elements [Y, donkey, horse, 30, father(max)]. I want to make a new list out of this with exclusively atoms.
I want to write a Prolog predicate called atoms/2 that, when supplied with a list in the first argument position, will instantiate the variable provided in the second argument position with the list of all atoms occurring in the inputlist (including any possible duplicate elements).
Like this:
?- atoms([Y, donkey, horse, 30, father(max)], Result).
Result = [donkey, horse].
I'm assuming that this is for schoolwork, and that your instructor would like you to roll your own code, rather than using the in-built, member/2 and findall/3.
Prolog has an in-built predicate, atom/1, that we'll use to identify atoms.
And prolog is a recursive language. The trick is to learn to think recursively. Most recursive problems can be broken down into 1 or 2 special cases, and then the more general recursive case.
So...
We have one special case, the empty list:
atoms( [] , [] ).
and we have two general, recursive cases. One is the case where the head (1st item) of the list is an atom, which case we add the list item to the result list and recurse down:
atoms( [X|Xs], [X|Atoms] ) :- atom(X), !, atoms(Xs,Atoms) .
The other/last case is the case where the current list item is something other than an atom, in which case we simply discard the list item and recurse down.
atoms( [X|Xs], Atoms ) := \+atom(X), atoms(Xs,Atoms) .
Putting it all together, you get
atoms( [] , [] ) .
atoms( [X|Xs] , [X|Atoms] ) :- atom(X), atoms(Xs,Atoms) .
atoms( [X|Xs] , Atoms ) :- \+ atom(X), atoms(Xs,Atoms) .
Note that this can be simplified to eliminate the redundant test for atomicity. The identification a list item as an atom is deterministics, that is, the list item isn't going to stop being an atom is we look at it again, so we can use the cut (!) operator to prune the search tree:
atoms( [] , [] ) .
atoms( [X|Xs] , [X|Atoms] ) :- atom(X), !, atoms(Xs,Atoms) .
atoms( [X|Xs] , Atoms ) :- atoms(Xs,Atoms) .
As most Prolog systems implement a member/2 list membership predicate and also the standard atom/1 and findall/3 predicates, a simple portable solution is:
atoms(List, Atoms) :-
findall(
Atom,
(member(Atom, List), atom(Atom)),
Atoms
).
Sample call:
| ?- atoms([Y, donkey, horse, 30, father(max)], Atoms).
Atoms = [donkey,horse]
yes
Install SWI-Prolog.
Start it.
Type, on the ?- prompt: edit(include/3). and hit Enter.
Marvel as you see the library definition of include/3.
Use this as the starting point of your predicate.
Ponder the importance of open source.
Alternatively, check out this answer: How do I make a new filtered list out of existing list in Prolog?
the Prolog notation of prefix/suffix is a quite easy one:
It pretty much puts all the work on append.
For those who don't know:
prefix(P,L):-append(P,_,L).
suffix(S,L):-append(_,S,L).
Now this means, that the result for prefix(X,[a,b,c,d]).
will be: X=[];X=[a];X=[a,b];X=[a,b,c];X=[a,b,c,d]
Here is my problem with this: I want a "real" prefix. Hence, a prefix cannot be empty, nor can the part following it be empty.
So the result to the query prefix(X,[a,b,c,d]). should be
X=[a];X=[a,b];X=[a,b,c]
and that's it.
Unfortunately, the real beaty of the standard-built in prefix predicate is, that it can use the termination of append, which is append([],Y,Y).
So it is pretty easy to know when to stop, picking the list apart one by one till the list is empty.
My termination means: Stop if there is exactly one element left in your list.
How do I do this?
My naive result would be:
prefix(P,L):-
length(P,1),append(P,E,L),E/=[].
This feels wrong though. I'm at work so I haven't checked if this actually works, but it should:
Is there any more convenient way to do this?
Same goes for suffix, which will be even harder since you do not have a way to adress the Tail as specific as the Head, I guess I'd just reverse the whole thing and then call prefix on it.
Infix will just be a combination of two.
I hope it is clear what I mean. Thanks for your input!
tl;dr: How to write a predicate prefix/2 which only filters real prefixes, so the prefix itself can not be empty, nor can the list followed by it be empty.
For the real prefix, you can try to do it like this:
list_prefix(List, [H|T]) :-
append([H|T], [_|_], List).
This just says that the first argument must have at least one element, and the rest of the list must have at least one element.
And following the suggestion by #false to make it more explicit:
list_real_prefix(List, Prefix) :-
Prefix = [_|_],
Rest = [_|_],
append(Prefix, Rest, List).
The "real" suffix will be exactly the same:
list_real_suffix(List, Suffix) :-
Front = [_|_],
Suffix = [_|_],
append(Front, Suffix, List).
You can also use a DCG for this, which is descriptive:
list_prefix(P) --> non_empty_seq(P), non_empty_seq(_).
non_empty_seq([X]) --> [X].
non_empty_seq([X|Xs]) --> [X], non_empty_seq(Xs).
| ?- phrase(list_pref(P), [a,b,c,d]).
P = [a] ? a
P = [a,b]
P = [a,b,c]
no
| ?-
You can define the suffix similarly:
list_suffix(S) --> non_empty_seq(_), non_empty_seq(S).
I have a predicate, which is true, if passed such list of pairs, for instance:
translatable([(dog,perro)], [(perro,hund)], [(dog,hund)])
Means - if "dog" translates to "perro", and "perro" translates to "hund", then it is true that "dog" translates to "hund".
Here follows full code. Returns/suggests first member of pair - given ((a, b), a) returns true, given ((a, b), X) returns X = a:
first((First, _), First).
Similar to "first", but for second pair member:
second((_, Second), Second).
This returns true if translatable word exists in list of tuples, and saves translation to Translation: (dog, Translation, [(bed,cama),(dog,perro)]
translation_exists(Word, Translation, [H|T]) :-
first(H, Word), second(H, Translation), !;
translation_exists(Word, Translation, T).
And resulting:
translatable(EnglishSpanish, SpanishGerman, EnglishGerman) :-
forall(member(Pair, EnglishGerman), (
first(Pair, Word),
second(Pair, ResultTranslation),
translation_exists(Word, Translation, EnglishSpanish),
translation_exists(Translation, ResultTranslation, SpanishGerman)
)).
This code returns true/false correctly.
But why, given
translatable([(dog,perro)], [(perro,hund)], X).
It does not returns X = [(dog,hund)]?
EDIT
To be more specific, actual goal is:
to find out if LAST dictionary has translatable pairs (and them only).
Daniel, thanks a lot, I have adopted your suggested member function - great simplification, thank you! This is all the code I have now:
lastIsTranslatable(_, _, []).
lastIsTranslatable(EngSpan, SpanGerm, [(Eng, Germ) | T]) :-
member((Eng, Span), EngSpan),
member((Span, Germ), SpanGerm),
% this is to protect endless [(dog,hund), (dog, hund), ...]
not(member((Eng, Germ), T)),
lastIsTranslatable(EngSpan, SpanGerm, T),
!.
And still, this works great finding True & False:
lastIsTranslatable([(a,b)], [(b,c)], [(a,c)]).
lastIsTranslatable([(a,b)], [(b,c)], [(a,no)]).
But for
lastIsTranslatable([(a,b)], [(b,c)], X).
result is X= [], then, after hitting ";" - false. Why?
Well, running with trace option, I see execution is failing on
not(member((Eng, Germ), T))
But otherwise resulting X will be endlessly filled with (a,c), (a,c)... Maybe there is better way to protect from duplicates?
The reason, basically, is that because EnglishGerman is uninstantiated, member/2 is free to come up with possible lists for it:
?- member((perro,X), List).
member((perro,X), List).
List = [ (perro, X)|_G18493911] ;
List = [_G18493910, (perro, X)|_G18493914] ;
List = [_G18493910, _G18493913, (perro, X)|_G18493917] ;
List = [_G18493910, _G18493913, _G18493916, (perro, X)|_G18493920]
...
This is the most direct issue, but even if you change the flow of data I think you'll still have problems:
translatable1(EnglishSpanish, SpanishGerman, EnglishGerman) :-
member((English,Spanish), EnglishSpanish),
member((Spanish,German), SpanishGerman),
member((English,German), EnglishGerman).
Note that I have foregone your first/2 and second/2 predicates in favor of pattern matching; I think this reads more clearly.
Aside: If you know your list is concrete and you don't want to generate multiple solutions, you can use memberchk/2 to verify that an element exists instead of member/2; it's cheaper and deterministic.
This works better (you get solutions, anyway) but still you get a lot more solutions than you need:
?- translatable1([(dog,perro)], [(perro,hund)], X).
X = [ (dog, hund)|_G18493925] ;
X = [_G18493924, (dog, hund)|_G18493928] ;
X = [_G18493924, _G18493927, (dog, hund)|_G18493931] a
Something which we know that our code does not know is that the cardinality of the result set should be less than or equal to the lowest cardinality of our inputs; if I have fifteen English-Spanish words and twelve Spanish-German words, I can't have more than twelve words in my English-German result. The reason our code doesn't know that is because it is trying to behave like math: our code is basically saying "for every element of English-Spanish, if there exists a matching element of Spanish-German, that is also an element of English-German." This does not tell us how to construct English-German! It only tells us a fact about English-German that we can verify with English-Spanish and Spanish-German! So it's cool, but it isn't quite enough to compute English-German.
Aside: it's conventional in Prolog to use a-b instead of (a,b); it's too easy to lull yourself into believing that Prolog has tuples when it doesn't and the operator precedence can get confusing.
So, how do we tell Prolog how to compute English-German? There are probably lots of ways but I would prefer to use select/3 because our set cardinality constraints (as well as a general sense that it will converge/halt) will emerge naturally from a computation that "uses up" the input sets as it goes.
translatable2([], _, []).
translatable2(_, [], []).
translatable2([Eng-Span|EngSpanRem], SpanGerm, EngGerm) :-
(select(Span-Germ, SpanGerm, SpanGermRem) ->
translatable2(EngSpanRem, SpanGermRem, EngGermRem),
EngGerm = [Eng-Germ|EngGermRem]
;
translatable2(EngSpanRem, SpanGerm, EngGerm)
).
The base cases should be obvious; if we are out of English-Spanish or Spanish-German, there's nothing left to compute. Then the inductive case peels the first item off the English-Spanish list and searches for a Spanish-German translation that matches. If it finds one, it uses it to build the result; otherwise, it just recurs on the remaining English-Spanish list. This way, on each iteration we at least discard an English-Spanish translation from that list, and we discard Spanish-German translations as they are used. So it seems intuitively likely that this will work and terminate without producing a bunch of extra choice points.
It seems to do the trick:
?- translatable2([dog-perro], [perro-hund], X).
X = [dog-hund] ;
X = [dog-hund].
The extra result there is because we hit both terminal cases because both lists became []; this isn't attractive but it isn't anything to worry about really either.
Now one thing that sucks about this solution is that it treats the first two parameters as in-parameters and the last one as an out-parameter and there isn't really anything you can do about this. I don't know if this is an issue for you; translatable/1 should not have this limitation, but because member((Spanish,German), SpanishGerman) happens before member((English,German), EnglishGerman) it winds up generating an infinitely large list, searching in effect for the missing Spanish-German translation.
Still, it feels like it should be possible to come up with a general purpose predicate that works as long as you supply any two of these inputs. I can do that if I know that all three lists are complete and in the same order:
translatable3([], [], []).
translatable3([X-Y|XYs], [Y-Z|YZs], [X-Z|XZs]) :-
translatable3(XYs, YZs, XZs).
And you can see it work like so:
?- translatable3([dog-perro], [perro-hund], X).
X = [dog-hund].
?- translatable3([dog-perro], X, [dog-hund]).
X = [perro-hund].
?- translatable3(X, [perro-hund], [dog-hund]).
X = [dog-perro].
But I don't know enough about your constraints to know if that could be a legitimate answer. My suspicion is no, because languages don't work that way, but who knows?
Anyway, that's three different approaches; I hope one of them is helpful to you!
I'm trying to write a predicate to remove the head from every list in list of lists and add the tails to a new list. The resulting list should be returned as the second parameter.
Here's the attempt:
construct_new(S,New) :-
New = [],
new_situation(S,New).
new_situation([],_).
new_situation([H|T], New) :-
chop(H, H1),
new_situation(T, [H1|New]).
chop([_|T], T).
You would call it like this:
construct_new([[x,x],[b,c],[d,e,f]],S).
This, however, only produces output true..
Step-by-step execution
Your query is construct_new(Input,Output), for some instanciated Input list.
The first statement in construct_new/2 unifies Output (a.k.a. New) with the empty list. Where is the returned list supposed to be available for the caller? Both arguments are now unified.
You call new_situation(Input,[])
You match the second clause new_situation([H|T],[]), which performs its task recursively (step 4, ...), until ...
You reach new_situation([],_), which successfully discards the intermediate list you built.
Solutions
Write a simple recursive predicate:
new_situation([],[]).
new_situation([[_|L]|T],[L|R]) :-
new_situation(T,R).
Use maplist:
construct_new(S,R) :-
maplist(chop,S,R).
Remark
As pointed out by other answers and comments, your predicates are badly named. construct_new is not a relation, but an action, and could be used to represent almost anything. I tend to like chop because it clearly conveys the act of beheading, but this is not an appropriate name for a relation. repeat's list_head_tail(L,H,T) is declarative and associates variables to their roles. When using maplist, the other predicate (new_situation) doesn't even need to exist...
...even though guillotine/3 is tempting.
This could be done with a DCG:
owth(Lists, Tails) :-
phrase(tails(Tails), Lists).
tails([]) --> [].
tails([T|Tails]) --> [[_|T]], tails(Tails).
Yielding these queries:
| ?- owth([[x,x],[b,c],[d,e,f]], T).
T = [[x],[c],[e,f]] ? ;
no
| ?- owth(L, [[x],[c],[e,f]]).
L = [[_,x],[_,c],[_,e,f]]
yes
(owth = Off with their heads! or, if used the other direction, On with their heads!)
If you also want to capture the heads, you can enhance it as follows:
owth(Lists, Heads, Tails) :-
phrase(tails(Heads, Tails), Lists).
tails([], []) --> [].
tails([H|Hs], [T|Tails]) --> [[H|T]], tails(Hs, Tails).
We use meta-predicate maplist/[3-4] with one of these following auxiliary predicates:
list_tail([_|Xs],Xs).
list_head_tail([X|Xs],X,Xs).
Let's run some queries!
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],Heads,Tails).
Heads = [x,b,d],
Tails = [[x],[c],[e,f]].
If you are only interested in the tails, use maplist/4 together with list_head_tail/3 ...
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],_,Tails).
Tails = [[x],[c],[e,f]].
... or, even simpler, maplist/3 in tandem with list_tail/2:
?- maplist(list_tail,[[x,x],[b,c],[d,e,f]],Tails).
Tails = [[x],[c],[e,f]].
You can also use the somewhat ugly one-liner with findall/3:
?- L = [[x,x],[b,c],[d,e,f]],
findall(T, ( member(M, L), append([_], T, M) ), R).
R = [[x], [c], [e, f]].
(OK, technically a two-liner. Either way, you don't even need to define a helper predicate.)
But definitely prefer the maplist solution that uses chop as shown above.
If you do the maplist expansion by hand, and name your chop/2 a bit better, you would get:
lists_tails([], []).
lists_tails([X|Xs], [T|Ts]) :-
list_tail(X, T),
lists_tails(Xs, Ts).
And since you can do unification in the head of the predicate, you can transform this to:
lists_tails([], []).
lists_tails([[_|T]|Xs], [T|Ts]) :-
lists_tails(Xs, Ts).
But this is identical to what you have in the other answer.
Exercise: why can't we say:
?- maplist(append([_]), R, [[x,x],[b,c],[d,e,f]]).
I'm traying to learn the basics of logic programming.
I solved some exercises, and now I'm having trouble on creating a function that take two arguments, a list of non empty lists whose elements concatenated together form the second argument.
By the time I created a function that concat the elements of a list of lists:
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!.
Now, what I need to know is how to take the return value of that function and compare it with a list (the second argument of the function).
This is one approach that will allow down to single elements in a sublist, but not an empty sublist:
concat([[L]], [L]).
concat([[H],L|T], [H|R]) :- concat([L|T], R).
concat([[H1,H2|T]|LT], [H1|RT]) :- concat([[H2|T]|LT], RT).
The method here to avoid an empty list is to call out two head elements in the recursive clause, and a solitary element list in the base case. This prevents empty sublists from succeeding, as requested in the comments of the original post.
If you have a variable, Y that is already instantiated, and you want to know if it is the result of concatenating the list of lists, LL, you simply query:
concat(LL, Y).
This will be true if Y is the concatenation of list LL and false if it is not. You don't have to "return and compare" (as, for example, in C, you might say, concat(LL) == Y, or concat(LL, X); if (X == Y)...). This is because concat is a relation defined between the two arguments and it determine if the query can be made true by following the stated rules (clauses of the predicate).
If you already obtained a result and want to determine if it's unifiable to another variable, Z, then you can say:
concat(X, Y), Y = Z.
Note that, in Prolog, concat(X, Y) == Z is not correct to determine if the result of the predicate is equal to Z because it is not a function that returns a value.
Prolog doesn't have functions or return values in the sense of a procedural programming language. It has predicates, which assert a relationship. It has terms, which include variables which comes with some strictures:
All variables are local, and
A variable, once assigned a value, ceases to be variable. That's why it's called unification.
So....
If you want a predicate that will take two lists and produce their concatenation, you'll need to pass it a 3rd variable. You might invoke it like this:
concat([a,b],[c,d],X).
which asserts that X is the concatenation of [a,b] and [c,d]. Prolog's inference engine will then evaluate the truth or falseness of the assertion.
Most recursive problems has a few special cases and a more general case. The implementation of such a concat/3 predicate might look something like this (annotated to explain what it's doing).
First, we have one special (and terminating) case: If the left-hand list is empty, the concatenation is simply the right-hand list.
concat( [] , Bs , Bs ).
Next, we have the one general case: if the left-hand list is non-empty, we need to prepend it to the concatentation that we're building (and then recurse down.)
concat( [A|As] , Bs , [A|Cs] ) :-
concat(As,Bs,Cs).
That's all there is two it. You'll also notice that it's bi-directional: it's perfectly happy to split lists apart as well. Invoking it like this:
concat( Prefix , Suffix, [a,b,c,d] ).
will, on backtracking, produce all the possible ways that [a,b,c,d] could be split into a prefix and suffix:
Prefix Suffix
--------- ---------
[] [a,b,c,d]
[a] [b,c,d]
[a,b] [c,d]
[a,b,c] [d]
[a,b,c,d] []
You just need the base case
concat([],[]).
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3).
It also works for empty (sub)lists.
I've removed the useless cut.