0
votes

I just start learning Prolog and find it's hard to handle list related problem. If I have a list. Inside this list, I have three inner lists.

[[a,b,c], [d,e,f],[h,g]]

I need to write a predicate called "move(L, X, From, To, R)" where X is the character I want to move (this character has to be the last element in the inner list), From is the index of list I want to move from, To is the index of list I want to move to. e.g.

move([[a,b,c], [d,e,f],[h,g]], f, 2, 3, R).

returns

R = [[a,b,c], [d,e],[h,g,f]]

One more example:

move([[a,b,c], [d,e,f],[h,g]], f, 2, 1, R).

returns

R = [[a,b,c,f], [d,e],[h,g]]

I wrote a helper predicates to determine if a character is the last element in the list:

last([A], C):- A == C.
last([_|T], C):- last_one(T, C).

I spent a few hours thinking about it, but no working solutions. Any help please?

1
And the predicate should fail if the given element does not exist in the list with the given index, or if no list exists of either one of the indices? Or if the indices are the same? This is not a very well-defined predicate and is very non-Prolog-ish (imperative in nature), but you'll need an auxiliary predicate to add a counter, or use nth1/3. - lurker
A == C should be A = C. But even better, last([A], C) :- A = C. would be best replaced by last([A], A).. - lurker
Your predicate would look at the current count. If that current count matches the "from" index, then the element would be removed from the current sublist. Otherwise, the current sublist is unified with the one in the result list. If the current count matches the "to" index, the element is included in the result sublist. You should be able to come up with something based upon that. You also have to decide: where in the result sublist does the element go, or does it matter? - lurker
Thanks @lurker , I can changed predicate to "move([[a,b,c], [d,e,f],[h,g]], f, 2, 3)", it will print out the result. - Davidw
No that's not a good way to do it. You want to keep the result argument. - lurker

1 Answers

0
votes

I think you must prove the following: move(L, X, From, To, R) is the predicate you want run, so the #1 argument is a list of list (in the sample: L = [[a,b,c], [d,e,f],[h,g]] ); the #3 and #4 arguments are members of L, so you can use the predicate nth1(N, L, E), where N is the order of the element, L is the list and E the Element; each element is another list, and now you must delete the X from the list From and add it to the list To. For it, first you can use the predicate 'select/3'; for the second, you can use 'append/3'.

I tried the folowwing rules, but it give me a different order of the main list:

move(L, X, F, T, R) :- nth1(F, L, Lf), nth1(T, L, Lt), select(X, Lf, Rf), append(Lt, [X], Rt), select(Lf, L, Ra), select(Lt, Ra, Rb), append(Rb, [Rf], Rc), append(Rc, [Rt], R).

with this code, you obtain the following:

move([[a,b,c], [d,e,f],[h,g]], f, 2, 3, R).

R = [[a,b,c], [d,e],[h,g,f]]

but:

move([[a,b,c], [d,e,f],[h,g]], f, 2, 1, R).

R = [[h,g], [d,e], [a,b,c,f]]