I am implementing a words/2 predicate in which a list of characters can be rendered to a list of the character as a word inside a list. I use the mathematical symbol <=> to denote that they're working in any mode. Please advise if there's a better expression.
The example:
?- words([p,r,o,l,o,g,' ',i,s,' ',g,o,o,d],Y).
Y = [[p,r,o,l,o,g],[i,s],[g,o,o,d]]
?- words(X,[[p,r,o,l,o,g],[i,s],[g,o,o,d]]).
X = [p,r,o,l,o,g,' ',i,s,' ',g,o,o,d]
What I've done is trying to use append/3 as below, trying to put the empty string in between, and concatenate them together. And recurse the List with NewCharList, but failed with "out of local stack".
% base case, empty list
words([],[]).
% X is a list of characters
% Y is a list with characters list as a word
words(CharList,[WordList|List]):-
append(WordList,[' '],NewWord),
append(NewWord,CharList,NewCharList),
words(NewCharList,List).
How could I improve the code? Thanks.
Edit1
Million thanks from #rajashekar. Now I understand the code
% base case
split(_, [], [[]]).
% when the the element list of Ys is empty
% add a C to the Xs, in this case, C is a empty string ' '
split(C, [C|Xs], [[]|Ys]) :-
split(C, Xs, Ys).
% put the X character from [X|Y] list to Xs
% and goes on next word list
split(C, [X|Xs], [[X|Y]|Ys]) :-
split(C, Xs, [Y|Ys]).
but in my SWI-prolog, it seems weird that:
?-split(' ', X, [[p,r,o,l,o,g],[i,s],[g,o,o,d]]).
X = [p, r, o, l, o, g, ' ', i, s|...]
Here is the trace record:
[trace] ?- split(X, [[p,r,o,l,o,g],[i,s],[g,o,o,d]]).
Call: (10) split(_5702, [[p, r, o, l, o, g], [i, s], [g, o, o, d]]) ? creep
Call: (11) split(_6210, [[r, o, l, o, g], [i, s], [g, o, o, d]]) ? creep
Call: (12) split(_6266, [[o, l, o, g], [i, s], [g, o, o, d]]) ? creep
Call: (13) split(_6322, [[l, o, g], [i, s], [g, o, o, d]]) ? creep
Call: (14) split(_6378, [[o, g], [i, s], [g, o, o, d]]) ? creep
Call: (15) split(_6434, [[g], [i, s], [g, o, o, d]]) ? creep
Call: (16) split(_6490, [[], [i, s], [g, o, o, d]]) ? creep
Call: (17) split(_6546, [[i, s], [g, o, o, d]]) ? creep
Call: (18) split(_6596, [[s], [g, o, o, d]]) ? creep
Call: (19) split(_6652, [[], [g, o, o, d]]) ? creep
Call: (20) split(_6708, [[g, o, o, d]]) ? creep
Call: (21) split(_6758, [[o, o, d]]) ? creep
Call: (22) split(_6814, [[o, d]]) ? creep
Call: (23) split(_6870, [[d]]) ? creep
Call: (24) split(_6926, [[]]) ? creep
Exit: (24) split([], [[]]) ? creep
Exit: (23) split([d], [[d]]) ? creep
Exit: (22) split([o, d], [[o, d]]) ? creep
Exit: (21) split([o, o, d], [[o, o, d]]) ? creep
Exit: (20) split([g, o, o, d], [[g, o, o, d]]) ? creep
Exit: (19) split([' ', g, o, o, d], [[], [g, o, o, d]]) ? creep
Exit: (18) split([s, ' ', g, o, o, d], [[s], [g, o, o, d]]) ? creep
Exit: (17) split([i, s, ' ', g, o, o, d], [[i, s], [g, o, o, d]]) ? creep
Exit: (16) split([' ', i, s, ' ', g, o, o, d], [[], [i, s], [g, o, o, d]]) ? creep
Exit: (15) split([g, ' ', i, s, ' ', g, o, o|...], [[g], [i, s], [g, o, o, d]]) ? creep
Exit: (14) split([o, g, ' ', i, s, ' ', g, o|...], [[o, g], [i, s], [g, o, o, d]]) ? creep
Exit: (13) split([l, o, g, ' ', i, s, ' ', g|...], [[l, o, g], [i, s], [g, o, o, d]]) ? creep
Exit: (12) split([o, l, o, g, ' ', i, s, ' '|...], [[o, l, o, g], [i, s], [g, o, o, d]]) ? creep
Exit: (11) split([r, o, l, o, g, ' ', i, s|...], [[r, o, l, o, g], [i, s], [g, o, o, d]]) ? creep
Exit: (10) split([p, r, o, l, o, g, ' ', i|...], [[p, r, o, l, o, g], [i, s], [g, o, o, d]]) ? creep
X = [p, r, o, l, o, g, ' ', i, s|...] .
EDIT2
I found out that using ! (cut) could cut down the backtracking.
% base case
split(_, [], [[]]).
% when the the element list of Ys is empty
% add a C to the Xs, in this case, C is a empty string ' '
split(C, [C|Xs], [[]|Ys]) :-
split(C, Xs, Ys),!.
% put the X character from [X|Y] list to Xs
% and goes on next word list
split(C, [X|Xs], [[X|Y]|Ys]) :-
split(C, Xs, [Y|Ys]),!.
The code does exactly what you want.
Here:
?-split(' ', X, [[p,r,o,l,o,g],[i,s],[g,o,o,d]]).
X = [p, r, o, l, o, g, ' ', i, s|...]
X is exactly the expected output.
If you want to see all of X, do:
?-split(' ', X, [[p,r,o,l,o,g],[i,s],[g,o,o,d]]), write_canonical(X).
[p,r,o,l,o,g,' ',i,s,' ',g,o,o,d]
X = [p, r, o, l, o, g, ' ', i, s|...]
Long lists are shortened on the output in SWI prolog.
split(_, [], [[]]).
split(C, [C|Xs], [[]|Ys]) :-
split(C, Xs, Ys).
split(C, [X|Xs], [[X|Y]|Ys]) :-
split(C, Xs, [Y|Ys]).
| ?- split(' ', [p,r,o,l,o,g,' ',i,s,' ',g,o,o,d], X).
X = [[p,r,o,l,o,g],[i,s],[g,o,o,d]] ?
yes
| ?- split(' ', X, [[p,r,o,l,o,g],[i,s],[g,o,o,d]]).
X = [p,r,o,l,o,g,' ',i,s,' ',g,o,o,d] ?
yes
you can use mode declaration to say the predicate works in both modes. e.g., you could have said the words/2 predicate needs to work in both words(+Chars, -Words) and words(-Chars, +Words) modes(or in words(+, -) and words(-, +) modes). See for mode details. These are mostly used for documentation purposes in prolog (check out mercury where they really work).
Using Definite Clause Grammers DCGs will make problems like this a whole lot easier.
Try using trace when you feel a run away recursion. You can spot the problem most of the time if you use it.
Related
I am programming in Dart and I need a multi-dimensional array to be filled with some data. But when I tried to run it, data at previous indexes were overwritten.
Here is my code:
List<List<String>> list = List.filled(4, List.filled(4, ""));
String toFill = "abcdefghijklmnop";
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
list[i][j] = toFill[i * 4 + j];
}
}
print(list);
I expected output of print() function to be
[[a, b, c, d], [e, f, g, h], [i, j, k, l], [m, n, o, p]]
but when I run it, it printed
[[m, n, o, p], [m, n, o, p], [m, n, o, p], [m, n, o, p]]
I don't know, why the last part is duplicating over to previous values.
I'd be glad for any help.
Thanks
I was able to solve this use List.generate which makes a new list from an iterable.
List<List<String>> list = List.generate(4, (int index) => List.generate(4, (int index) => ""));
Which gives me
> [[a, b, c, d], [e, f, g, h], [i, j, k, l], [m, n, o, p]]
This seems a little verbose, so there may be a shortcut to do the same thing.
Edit: Since you don't care about the index variable, you can shorten it somewhat but ignoring it:
List<List<String>> list = List.generate(4, (_) => List.generate(4, (_) => ""));
You could also combine the creating and filling the list:
import 'dart:math';
void main() {
String toFill = "abcdefghijklmnopqrstuvwxyz";
List<List<String>> list = List.generate(
(toFill.length/4).ceil(),
(i) => toFill.substring(i*4, min(toFill.length, (i+1)*4)).split(''),
);
print(list);
}
[[a, b, c, d], [e, f, g, h], [i, j, k, l], [m, n, o, p], [q, r, s, t], [u, v, w, x], [y, z]]
Which, if your string is always 16 characters long, can be simplified to:
void main() {
String toFill = "abcdefghijklmnop";
List<List<String>> list = List.generate(
4,
(i) => toFill.substring(i*4, (i+1)*4).split(''),
);
print(list);
}
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!
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.
I have a problem in Prolog.
Consider a list where each element is referring to a position/location in the same list.
I want to write a program which returns true if I start with the same location that I end in. For example:
If I give it find-s([3,2,0,1],0)
It starts with 0 index which contains 3
then goes to the 3 index which contains 1
then the 1 index to find 2
finally to index 2 which contains 0 !
so it returns true in this case
I tried this but it didn't work
position([Head1| Tail1], Var1) :-
( Head1 == Var1,
Tail1 == Var1 ->
true
).
this should work
find_s(L, S) :- nth0(S, L, I), find_s(L, I, S).
find_s(_, S, S).
find_s(L, I, S) :- nth0(I, L, J), find_s(L, J, S).
but I think it could easily loop. So, instead of nth0/3, let's use nth0/4, after this consideration:
?- nth0(2,[a,b,c,d],X,Y).
X = c,
Y = [a, b, d].
?- nth0(2,L,$X,$Y).
L = [a, b, c, d].
for sake of readability, let's introduce a replace_nth0/4
replace_nth0(P, L, E, LrepE) :-
nth0(P, L, E, L_Without_E),
nth0(P, LrepE, -1, L_Without_E).
and then
find_s(L, S) :- nth0(S, L, I), find_s(L, I, S).
find_s(_, S, S).
find_s(L, I, S) :- I >= 0, replace_nth0(I, L, J, L_rep), find_s(L_rep, J, S).
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]
...