pater said:
I think the only way to solve this problem is to go through the first list element by element and remove each element from the second list. If at one point, you can't find a matching element in B, the test fails, if A gets empty before this happens, the subset condition is met. The task will be simpler if you can assume both lists are sorted (but I doubt you can...).
BTW: Why do you check for the size of the lists? Is it part of the exercise that B always has one element more than A?
That would do it and yes the lists will not be sorted as they arrive, but a sorting tast could be implemented if necessary and since it's only a test condition the sorting would not make any permanenet changes to the lists, although i guess it may slow it down a very tiny fraction. The reason i check for the size of the list is for another condition (not necessary to solve this task, yet it's a necessary condition in the overall program so i thought mentioning it may make things clearer).
Thanks for your thoughts it all helps.
Here's the code so far, it's almost there apart from the problem of unsorted lists, if it weren't for that i think the following code would be ok. (Note 'move' is the real name of the predicate 'test_subset' was the name used before and element_count is not a good name but will do for now).
move(A, B) :-
subset(A, B),
length(A, C),
length(B, D),
successor(C, D),
element_count(A, B).
element_count(A, B) :-
subtract(B, A, Result),
length(Result, L),
L is 1.
% subtract(+Set, +Delete, -Result)
% Delete all elements of set `Delete' from `Set' and unify the
% resulting set with `Result'.
Some other variations with unsorted problems (for a general picture) are:
alt_element_count(A, B) :-
member(X, A),
member(X, B),
delete(A, X, Y),
delete(B, X, Z),
length(Y, Ly),
length(Z, Lz),
Ly is 0,
Lz is 1.
% delete(+List1, ?Elem, ?List2)
% Delete all members of List1 that simultaneously unify with Elem and
% unify the result with List2.
....or this:
alt2_element_count([], B) :-
length(B, L),
L is 1.
alt2_element_count(A, B) :-
member(X, A),
remove(B, X, ResultB),
remove(A, X, ResultA),
alt2_element_count(ResultA, ResultB).
% remove(X,L,R) :<=> by removing one occurrence of X
% from L one obtains R
The last two versions don't work as they are (something wrong in my logic), the first version 'subtract' seems more promising, it uses sets and seems much more elegant (apart from unordered/unsorted lists problem), if i could sort that problem out it would be nice; then again perhaps the last two will end up convincing me they are more on track?
Here's the output of first version which tests the difference between sets:
?- element_count([119, 101, 101], [119, 101, 101, 108]).
Yes
?- element_count([119, 101, 108], [119, 101, 101, 108]).
No.........order matters
Any more help appreciated.
Thanks