Prolog recursion not working as intended - list

I have to write a function that filters out palindromes from a given list (palindrome are words which are the same in reverse like abba)
palindroom([], []).
palindroom([X|Xs], Y):-
( atom_chars(X, Z),
reverse(Z, K),
atom_chars(D,K),
atom_chars(P,Z),
D==P,
palindroom(Xs,[P|Y])
;
palindroom(Xs,Y)
).
I make the list elem into char array then reverse it and make it back into a string then compare the two, if it is I add it Y.
Here is my stacktrace where everything is going correctly until:
[trace] 44 ?- palindroom(["abba"], X).
Call: (7) palindroom(["abba"], _G5269) ? creep
Call: (8) atom_chars("abba", _G5351) ? creep
Exit: (8) atom_chars("abba", [a, b, b, a]) ? creep
Call: (8) lists:reverse([a, b, b, a], _G5363) ? creep
Exit: (8) lists:reverse([a, b, b, a], [a, b, b, a]) ? creep
Call: (8) atom_chars(_G5386, [a, b, b, a]) ? creep
Exit: (8) atom_chars(abba, [a, b, b, a]) ? creep
Call: (8) atom_chars(_G5386, [a, b, b, a]) ? creep
Exit: (8) atom_chars(abba, [a, b, b, a]) ? creep
Call: (8) abba==abba ? creep
Exit: (8) abba==abba ? creep
Call: (8) palindroom([], [abba|_G5269]) ? creep
Fail: (8) palindroom([], [abba|_G5269]) ? creep
Redo: (7) palindroom(["abba"], _G5269) ? creep what is happening here? and why?
Call: (8) palindroom([], _G5269) ? creep
Exit: (8) palindroom([], []) ? creep
Exit: (7) palindroom(["abba"], []) ? creep
X = [].
I have another program with the same problem, could anyone help me? is the base of the recursion wrong or smt?
EDIT!!
got it working with
palindrome(Xs) :-
reverse(Xs, Xs).
cycle([],[]).
cycle([X|Xs], Y):-
atom_chars(X,Z),
palindrome(Z),
Y = [X|K],
cycle(Xs,K);
cycle(Xs,Y).
I misunderstood recursion in Prolog afterall. thanks #repeat and #lurker

How about defining palindrome/1 like this, using the widely available list predicate reverse/2?
palindrome(Xs) :-
reverse(Xs, Xs).
Sample queries:
:- palindrome([a,b,b,a]).
true.
:- palindrome([a,b,X,Y]).
X = b, Y = a.
Last, let's not forget about the most general query!
?- palindrome(Xs).
Xs = []
; Xs = [_A]
; Xs = [_A,_A]
; Xs = [_A,_B,_A]
; Xs = [_A,_B,_B,_A]
; Xs = [_A,_B,_C,_B,_A]
...

Related

Prolog - Split a list in two halves, reversing the first half

I am asked to take a list of letters into two lists that are either equal in size (even sized original list I guess) or one is larger than the other by one element (odd sized list), and reverse the first one while I'm at it.
Query and output example:
?- dividelist2([a,b,c,d,e,f], L1,L2).
L1 = [c,b,a]
L2 = [d,e,f]
?- dividelist2([a,b,c,d,e], L1,L2).
L1 = [c,b,a]
L2 = [d,e]
% OR
L1 = [b,a]
L2 = [c,d,e]
I've reached this solution, but I have a feeling something is wrong with it. Please let me know if I'm missing something... How do I get the last output? (two options for output, I mean)
dividelist2(L, X, B) :-
( append(A, B, L),
length(A, O),
length(B, N),
( (O-1) =:= N
; (O+1) =:= N
; O =:= N
),
!
), reverse(A, X).
reverse(List, Rev) :-
reverse(List, Rev, []).
reverse([], L, L).
reverse([H|T], L, SoFar) :-
reverse(T, L, [H|SoFar]).
Thanks in advance!
You're on the right track:
splitflip(In, Out1, Out2) :-
length(In, L), % length of the list
FL is L//2, % integer division, so half the length, Out1 will be 1 shorter than Out2 if L is odd
( \+ (FL*2 =:= L), % is odd
FLP is FL + 1 % odd case, choicepoint left
; FLP = FL % odd and even case, no choicepoint left
), % the one place we need a choicepoint for the odd length case of an odd input, note order prunes choicepoint for even case
length(FirstHalf, FLP), % generate an list of vars to the right length
append(FirstHalf, Out2, In), % unify with the first half and generate second half of correct length
reverse(FirstHalf, Out1). % do the reverse
Just need to reorder things a bit and use integer division.
Thanks #WillNess, I have a full solution here using the tortoise/hare trick. The idea behind that trick is that you are traversing the list simultaneously, with the tortoise going element by element and the hare going by two elements at a time. When the hare list is empty, you know you're at the middle of the list. This inlines a common accumulator pattern for reversing a list in one pass, which is how we produce the first half of the result. The second half of the result is just the remainder of the list--which is to say, the tortoise list.
divide(List, Left, Right) :-
reverse(List, List, [], Left, Right).
% reverse(Tortoise, Hare, ReverseAccumulator, RevFirstHalf, SecondHalf)
reverse(Right, [], Left, Left, Right).
reverse([X|Xs], [_,_|Rem], Acc, Left, Right) :-
reverse(Xs, Rem, [X|Acc], Left, Right).
As you can see, the hare is just here to be traversed two-at-a-time until it becomes empty, which triggers our base case. This works fine for even-length lists.
For odd-length lists we must handle them by noticing that the hare is a single-item list. Then we need to produce two more solutions, so we have two clauses for the single-item list case: one that places the next tortoise item into the first half list, one that places it into the second half:
reverse([X|Xs], [_], Acc, Left, Right) :-
reverse([X|Xs], [], Acc, Left, Right).
reverse([X|Xs], [_], Acc, Left, Right) :-
reverse(Xs, [], [X|Acc], Left, Right).
This produces the results you want. It's a little hard to understand what is going on at first, but it is more efficient than the accepted answer, probably because it doesn't allocate as much. For comparison, I ran both on a list of 5 million entries; this version ran somewhat faster:
?- length(L, 5000000), time(splitflip(L, Left, Right)).
% 5,000,014 inferences, 0.806 CPU in 0.806 seconds (100% CPU, 6200835 Lips)
L = [_58, _64, _70, _76, _82, _88, _94, _100, _106|...],
Left = [_15000052, _15000046, _15000040, _15000034, _15000028, _15000022, _15000016, _15000010, _15000004|...],
Right = [_15000058, _15000064, _15000070, _15000076, _15000082, _15000088, _15000094, _15000100, _15000106|...].
?- length(L, 5000000), time(divide(L, Left, Right)).
% 2,500,001 inferences, 0.567 CPU in 0.568 seconds (100% CPU, 4405613 Lips)
L = [_850, _856, _862, _868, _874, _880, _886, _892, _898|...],
Left = [_15000844, _15000838, _15000832, _15000826, _15000820, _15000814, _15000808, _15000802, _15000796|...],
Right = [_15000850, _15000856, _15000862, _15000868, _15000874, _15000880, _15000886, _15000892, _15000898|...] .
Edit: Original answer follows.
This is only a partial solution. I'm missing something obvious about how to convert this to the full solution, and I don't have a lot of time at the moment to finish it, but I thought it might be useful to share anyway. And probably another prolog answerer will see immediately where the problem is.
My plan here is basically to be reversing the list and tracking the index I'm at from the start on the way into the recursive call, and be tracking the index I'm at from the end on the way out of the recursive call. With that in-hand, if the indexes match, we take the reversed prefix and the suffix and that is the result. We can define "match" as the indexes are within 1 of each other, with a separate predicate.
reverse(_, [], 0, Z, Z).
reverse(I, [X|Xs], J1, Z, Acc) :-
succ(I, I1),
reverse(I1, Xs, J, Z, [X|Acc]),
succ(J, J1).
The combination of pieces that I think we need are visible in this code when viewed in the trace. output:
[trace] ?- reverse(0, [a,b,c,d], _, R, []).
Call: (8) reverse(0, [a, b, c, d], _694, _696, []) ? creep
Call: (9) succ(0, _964) ? creep
Exit: (9) succ(0, 1) ? creep
Call: (9) reverse(1, [b, c, d], _972, _696, [a]) ? creep
Call: (10) succ(1, _970) ? creep
Exit: (10) succ(1, 2) ? creep
Call: (10) reverse(2, [c, d], _978, _696, [b, a]) ? creep
Call: (11) succ(2, _976) ? creep
Exit: (11) succ(2, 3) ? creep
Call: (11) reverse(3, [d], _984, _696, [c, b, a]) ? creep
Call: (12) succ(3, _982) ? creep
Exit: (12) succ(3, 4) ? creep
Call: (12) reverse(4, [], _990, _696, [d, c, b, a]) ? creep
Exit: (12) reverse(4, [], 0, [d, c, b, a], [d, c, b, a]) ? creep
Call: (12) succ(0, _988) ? creep
Exit: (12) succ(0, 1) ? creep
Exit: (11) reverse(3, [d], 1, [d, c, b, a], [c, b, a]) ? creep
Call: (11) succ(1, _988) ? creep
Exit: (11) succ(1, 2) ? creep
Exit: (10) reverse(2, [c, d], 2, [d, c, b, a], [b, a]) ? creep
Call: (10) succ(2, _988) ? creep
Exit: (10) succ(2, 3) ? creep
Exit: (9) reverse(1, [b, c, d], 3, [d, c, b, a], [a]) ? creep
Call: (9) succ(3, _694) ? creep
Exit: (9) succ(3, 4) ? creep
Exit: (8) reverse(0, [a, b, c, d], 4, [d, c, b, a], []) ? creep
R = [d, c, b, a] .
Note particularly this line:
Exit: (10) reverse(2, [c, d], 2, [d, c, b, a], [b, a]) ? creep
As you can see, at this moment we have I = J = 2, and we have a list [b,a] and a list [c,d]. This gives me hope that this is close, but for whatever reason I'm not seeing the bridge to the complete solution. Maybe you will!

Prolog list and recursion in finding a graph path [duplicate]

Many predicates define some kind of an acyclic path built from edges defined via a binary relation, quite similarly to defining transitive closure. A generic definition is thus called for.
Note that the notions defined in graph theory do not readily match what is commonly expected. Most notably, we are not interested in the edges' names.
Worse, also graph theory has changed a bit, introducing the notion of walk, noting
Traditionally, a path referred to what is now usually known as an open walk. Nowadays, when stated without any qualification, a path is usually understood to be simple, meaning that no vertices (and thus no edges) are repeated. (The term chain has also been used to refer to a walk in which all vertices and edges are distinct.)
So my question is: How to name and define this functionality?
What I have done so far is to define:
path(Rel_2, Path, X0,X)
The first argument has to be the continuation of the relation which is an incomplete goal that lacks two further arguments. Then comes either the Path or the pair of vertices.
Example usage
n(a, b).
n(b, c).
n(b, a).
?- path(n,Xs, a,X).
Xs = [a], X = a
; Xs = [a, b], X = b
; Xs = [a, b, c], X = c
; false.
Implementation
:- meta_predicate(path(2,?,?,?)).
:- meta_predicate(path(2,?,?,?,+)).
path(R_2, [X0|Ys], X0,X) :-
path(R_2, Ys, X0,X, [X0]).
path(_R_2, [], X,X, _).
path(R_2, [X1|Ys], X0,X, Xs) :-
call(R_2, X0,X1),
non_member(X1, Xs),
path(R_2, Ys, X1,X, [X1|Xs]).
non_member(_E, []).
non_member(E, [X|Xs]) :-
dif(E,X),
non_member(E, Xs).
How about defining path/4 like this?
path(R_2, Xs, A,Z) :- % A path `Xs` from `A` to `Z` is ...
walk(R_2, Xs, A,Z), % ... a walk `Xs` from `A` to `Z` ...
all_dif(Xs). % ... with no duplicates in `Xs`.
To aid universal termination, we swap the two goals in above conjunction ...
path(R_2, Xs, A,Z) :-
all_dif(Xs), % enforce disequality ASAP
walk(R_2, Xs, A,Z).
... and use the following lazy implementation of all_dif/1:
all_dif(Xs) :- % enforce pairwise term inequality
freeze(Xs, all_dif_aux(Xs,[])). % (may be delayed)
all_dif_aux([], _).
all_dif_aux([E|Es], Vs) :-
maplist(dif(E), Vs), % is never delayed
freeze(Es, all_dif_aux(Es,[E|Vs])). % (may be delayed)
walk/4 is defined like path/4 and path/5 given by the OP:
:- meta_predicate walk(2, ?, ?, ?).
walk(R_2, [X0|Xs], X0,X) :-
walk_from_to_step(Xs, X0,X, R_2).
:- meta_predicate walk_from_to_step(?, ?, ?, 2).
walk_from_to_step([], X,X, _).
walk_from_to_step([X1|Xs], X0,X, R_2) :-
call(R_2, X0,X1),
walk_from_to_step(Xs, X1,X, R_2).
IMO above path/4 is simpler and more approachable, particularly for novices. Would you concur?
I want to focus on naming the predicate.
Unlike maplist/2,
the argument order isn't of primary importance here.
The predicate name should make the meaning of the respective arguments clear.
So far, I like path_from_to_edges best, but it has its pros and cons, too.
path_from_to_edges(Path,From,To,Edges_2) :-
path(Edges_2,Path,From,To).
Let's pick it apart:
pro: path is a noun, it cannot be mis-read a verb. To me, a list of vertices is implied.
pro: from stands for a vertex, and so does to.
con: edges is somewhat vague, but using lambdas here is the most versatile choice.
con: According to Wikipedia, a path is a trail in which all vertices (except possibly the first and last) are distinct. So that would need to be clarified in the description.
Using lambdas for a lists of neighbor vertices Ess:
?- Ess = [a-[b],b-[c,a]],
From = a,
path_from_to_edges(Path,From,To,\X^Y^(member(X-X_neibs,Ess),member(Y,X_neibs))).
Ess = [a-[b],b-[c,a]], From = a, To = a, Path = [a]
; Ess = [a-[b],b-[c,a]], From = a, To = b, Path = [a,b]
; Ess = [a-[b],b-[c,a]], From = a, To = c, Path = [a,b,c]
; false.
Edit 2015-06-02
Another shot at better naming! This leans more on the side of maplist/2...
graph_path_from_to(P_2,Path,From,To) :-
path(P_2,Path,From,To).
Here, graph, of course, is a noun, not a verb.
Regarding the meaning of "path": paths definitely should allow From=To and not exclude that by default (with pairwise term inequalities). It is easy to exclude this with an additional dif(From,To) goal, but not the other way round.
I do not see the reason to define in path/4 the arguments "start node" and "end node". It seems that a simple path/2 with the rule and the list of nodes must be enough.
If the user wants a list starting with some node (by example, 'a'), he can query the statement as: path( some_rule, ['a'|Q] ).
A user could, by example, request for path that have length 10 in the way: length(P,10), path( some_rule, P).
* Addendum 1 *
Some utility goals can be easily added, but they are not the main subject. Example, path/3 with start node is:
path( some_rule, [start|Q], start ) :-
path ( some_rule, [start|Q ] ).
* Addendum 2 *
Addition of last node as argument could give the false idea that this argument drives the algorithm, but it doesn't. Assume by example:
n(a, b).
n(a, c).
n(a, d).
and trace algorithm execution for the query:
[trace] ?- path( n, P, X, d ).
Call: (6) path(n, _G1025, _G1026, d) ? creep
Call: (7) path(n, _G1107, _G1026, d, [_G1026]) ? creep
Exit: (7) path(n, [], d, d, [d]) ? creep
Exit: (6) path(n, [d], d, d) ? creep
P = [d],
X = d ;
Redo: (7) path(n, _G1107, _G1026, d, [_G1026]) ? creep
Call: (8) n(_G1026, _G1112) ? creep
Exit: (8) n(a, b) ? creep
Call: (8) non_member(b, [a]) ? creep
Call: (9) dif:dif(b, a) ? creep
Exit: (9) dif:dif(b, a) ? creep
Call: (9) non_member(b, []) ? creep
Exit: (9) non_member(b, []) ? creep
Exit: (8) non_member(b, [a]) ? creep
Call: (8) path(n, _G1113, b, d, [b, a]) ? creep
Call: (9) n(b, _G1118) ? creep
Fail: (9) n(b, _G1118) ? creep
Fail: (8) path(n, _G1113, b, d, [b, a]) ? creep
Redo: (9) non_member(b, []) ? creep
Fail: (9) non_member(b, []) ? creep
Fail: (8) non_member(b, [a]) ? creep
Redo: (8) n(_G1026, _G1112) ? creep
Exit: (8) n(a, c) ? creep
Call: (8) non_member(c, [a]) ? creep
Call: (9) dif:dif(c, a) ? creep
Exit: (9) dif:dif(c, a) ? creep
Call: (9) non_member(c, []) ? creep
Exit: (9) non_member(c, []) ? creep
Exit: (8) non_member(c, [a]) ? creep
Call: (8) path(n, _G1113, c, d, [c, a]) ? creep
Call: (9) n(c, _G1118) ? creep
Fail: (9) n(c, _G1118) ? creep
Fail: (8) path(n, _G1113, c, d, [c, a]) ? creep
Redo: (9) non_member(c, []) ? creep
Fail: (9) non_member(c, []) ? creep
Fail: (8) non_member(c, [a]) ? creep
Redo: (8) n(_G1026, _G1112) ? creep
Exit: (8) n(a, d) ? creep
Call: (8) non_member(d, [a]) ? creep
Call: (9) dif:dif(d, a) ? creep
Exit: (9) dif:dif(d, a) ? creep
Call: (9) non_member(d, []) ? creep
Exit: (9) non_member(d, []) ? creep
Exit: (8) non_member(d, [a]) ? creep
Call: (8) path(n, _G1113, d, d, [d, a]) ? creep
Exit: (8) path(n, [], d, d, [d, a]) ? creep
Exit: (7) path(n, [d], a, d, [a]) ? creep
Exit: (6) path(n, [a, d], a, d) ? creep
P = [a, d],
X = a .
as you can see, in this case algorithm fails to brute force.
For this reason, if algorithm is not improved, I suggest do not add "end node" as "path" argument.

Prolog: lists consisting of one element

I believe that the problem I have is very silly, but couldn't find an answer searching online. I want a function to always return a list of elements, even in the case the list consists of just one element. I don't know if it is always like that in prolog (i.e. that one element lists are transformed in a simple constant) but here I go into detail.
First off, I have a set of predicates (like composeBase(<,<,[<]).) based on which the function I was talking about, compose/3, makes its computations:
compose(X, Y, Z):-
compositionBase(X,Y,Z).
So, for instance, compose/3 does this:
compose(<, <, L).
L = (<) .
compose(<, =, L).
L = (<) .
compose(=, =, L).
L = (=) .
So, why in the first example does it not return [<] if the predicate says composeBase(<,<,[<]).? Is there a way to make it return the list [<] instead?
If there is not or my question doesn't make any sense, here is where the problem comes with not being able to do so (if there is, don't even bother to go on reading of course! :) Unless you feel like giving me suggestions for my naive code, which I would very much appreciate as a newbie).
I have to write a function composeList/3 which, given two lists of elements, should compute a list containing all the possible compositions of the elements in the two set.
Therefore, for example, composeList/3 should do this:
composeList([<], [<, =], L).
L = [<, =] .
composeList([<,=], [<, =], L).
L = [<, =] .
And here's the code:
composeList(_,[],[]).
composeList([],_,[]).
composeList([X| Xs], [Y| Ys], L):-
compose(X,Y,L1),
composeList(Xs, [Y| Ys], L2),
composeList([X| Xs], Ys, L3),
union(L1, L2, L4),
union(L3,L4,L).
So, as confirmed by doing trace., I believe the problem occurs when compose/3 returns a simple constant and not a list. For instance, in the example above it returns false . because, since L1 is set <, the first union fails. How can I fix this in a casual way?
By the way, here is what trace. does:
[trace] 123 ?- compositionListe([<],[<,=],L).
Call: (7) compositionListe([<], [<, =], _G8032) ? creep
Call: (8) compose(<, <, _G8122) ? creep
Call: (9) compositionBase(<, <, _G8122) ? creep
Exit: (9) compositionBase(<, <, [<]) ? creep
Exit: (8) compose(<, <, [<]) ? creep
Call: (8) compositionListe([], [<, =], _G8128) ? creep
Exit: (8) compositionListe([], [<, =], []) ? creep
Call: (8) compositionListe([<], [=], _G8131) ? creep
Call: (9) compose(<, =, _G8131) ? creep
Exit: (9) compose(<, =, <) ? creep
Call: (9) compositionListe([], [=], _G8134) ? creep
Exit: (9) compositionListe([], [=], []) ? creep
Call: (9) compositionListe([<], [], _G8137) ? creep
Exit: (9) compositionListe([<], [], []) ? creep
Call: (9) lists:union(<, [], _G8137) ? creep
Fail: (9) lists:union(<, [], _G8137) ? creep
Thank you very much in advance!

Prolog list permutation

I have the following code that generates all possible permutations of a list, but I can't figure it out why it is working.
remove(X,[X|T],T).
remove(X,[F|T],[F|T1]) :- remove(X,T,T1).
perm([X|Y],Z) :- perm(Y,W), remove(X,Z,W).
perm([],[]).
Could someone give me some explanation or send me to a reference, please?
I'm just picking up Prolog, so I don't know the correct terms, but I think the logic goes as following:
The rules for remove(X,L,T) is straightforward, it defines T as a list with X removed from L. For example, given T=[1], which L satisfies X=2? the answer is [1,2] or [2,1].
For perm, let's take the example of perm([1,2,3], P).
According to the definition, P is a permutation of [1,2,3] if W is a permuation of [2,3], where W is P with 1 removed.
Assuming we somehow know W is [2,3] or [3,2] through the magic of backtracking, then P must be [1,2,3],[2,1,3],[2,3,1],...
How did we find out permutation of [2,3] is [2,3] or [3,2]? It happens when W2 is a permutation of [3], where W2 is P2 with 2 removed.
Assuming we somehow know W2 is [3], then P2 must be [2,3] or [3,2].
How did we find out permutation of [3] is [3]? It happens when W3 is a permutation of [], where W3 is P3 with 3 removed. Since W3 must be [] due to the base case, then P3 must be [3].
Just learned about the trace mode, it provides a step-by-step explanation:
?- trace.
true.
[trace] 2 ?- perm([1,2],X).
Call: (7) perm([1, 2], _G22903) ? creep
Call: (8) perm([2], _G22988) ? creep
Call: (9) perm([], _G22988) ? creep
Exit: (9) perm([], []) ? creep
Call: (9) remove(2, _G22988, []) ? creep
Exit: (9) remove(2, [2], []) ? creep
Exit: (8) perm([2], [2]) ? creep
Call: (8) remove(1, _G22903, [2]) ? creep
Exit: (8) remove(1, [1, 2], [2]) ? creep
Exit: (7) perm([1, 2], [1, 2]) ? creep
X = [1, 2] ;
Redo: (8) remove(1, _G22903, [2]) ? creep
Call: (9) remove(1, _G22984, []) ? creep
Exit: (9) remove(1, [1], []) ? creep
Exit: (8) remove(1, [2, 1], [2]) ? creep
Exit: (7) perm([1, 2], [2, 1]) ? creep
X = [2, 1] ;
Redo: (9) remove(1, _G22984, []) ? creep
Fail: (9) remove(1, _G22984, []) ? creep
Fail: (8) remove(1, _G22903, [2]) ? creep
Redo: (9) remove(2, _G22988, []) ? creep
Fail: (9) remove(2, _G22988, []) ? creep
Fail: (8) perm([2], _G22988) ? creep
Fail: (7) perm([1, 2], _G22903) ? creep
false.

My Prolog "translator" script returns an empty list

I am trying to write a simple translator, where you enter a list of numerical numbers and it returns their string values like so :
translate([1,2,3], X).
X=[one, two, three].
The code I have written works...except it returns an empty list. Here is my code and the trace:
means(1, one).
means(2, two).
means(3, three).
means(4, four).
means(5, five).
means(6, six).
means(7, seven).
means(8, eight).
means(9, nine).
means(10, ten).
translate([], X).
translate([H|T], []):-
means(H, X),
translate(T, X).
translate([H|T], X):-
means(H, Y),
translate(T, [X|Y]).
[trace] 1 ?- translate([1,2,3], X).
Call: (6) translate([1, 2, 3], _G2219) ? creep
Call: (7) means(1, _G2301) ? creep
Exit: (7) means(1, one) ? creep
Call: (7) translate([2, 3], one) ? creep
Call: (8) means(2, _G2301) ? creep
Exit: (8) means(2, two) ? creep
Call: (8) translate([3], [one|two]) ? creep
Call: (9) means(3, _G2304) ? creep
Exit: (9) means(3, three) ? creep
Call: (9) translate([], [[one|two]|three]) ? creep
Exit: (9) translate([], [[one|two]|three]) ? creep
Exit: (8) translate([3], [one|two]) ? creep
Exit: (7) translate([2, 3], one) ? creep
Exit: (6) translate([1, 2, 3], []) ? creep
X = [] .
My other question is: why is my list concatenating as [[one|two]|three]? instead of [one, two, three]?
Thanks,
You get empty list because of translate([H|T], []) clause.
The whole program (except means facts) can be just this simple:
translate([], []).
translate([NumH | NumT], [WordH | WordT]) :-
means(NumH, WordH),
translate(NumT, WordT).
Doing it manually Sergey's way is good practice, but you can simplify even further with maplist/3:
translate(Numbers, Words) :- maplist(means, Numbers, Words).