I am trying to write a rule in Prolog that will first check if all the elements in the second list are contained in the first and if all the elements in the second list are even.
So, for example the following queries:
evenSubList([5, 6, 7, 8], [6, 8]). -> True
evenSubList([5, 6, 7, 8], [6, 7, 8]). -> no
evenSubList([5, 6, 7, 8], X). -> X = [6, 8]
evenSubList([6, 7, 8], [6, 8]). -> True
evenSubList([6, 8], [6, 8]). -> True
When I query my current code, it only works if both lists have even numbers only. The first list is not allowed to have any odd numbers. I've also tried to use the built-in sublist rule with no luck. I know problem is in my second definition where the head in both lists are different, but I'm not sure what I'm doing wrong.
evenSubList([X | _], [X]) :- % base case gets hit if second list only has one element
mod(X, 2) =:= 0.
evenSubList([X | Y], [Z | T]) :- % If first element of both lists are different
evenSubList(Y, [Z]),
evenSubList(Y, T).
evenSubList([X | Y], [X | Z]) :- % If both heads are the same
mod(X, 2) =:= 0,
evenSubList(Y, Z).
CodePudding user response:
You have the right idea, it's just that your case where the heads aren't the same, you are trying to do two things at a time and tripping over yourself because eventually, you will have a null list and that will return false. There is a much simpler solution.
You start off with the tail, Y
, then you traverse compare it to the head Z
, but if it gets to the case where both heads are the same, you'll have a null call and that will cause the output to be no
.
With your second recursive call, evenSubList(Y, T)
, again, if T
is shorter than Y
, you'll have an issue with a null list.
You want to do something like this where first list gets smaller and your second list stays the same size and have each of the elements from the first list get compared to the second list as a whole which does not change until or unless other case is met where you'll know it's safe to take the tail of the second list.
evenSubList([X], [X]) :-
mod(X, 2) =:= 0.
evenSubList([X | Y], [X | Z]) :-
mod(X, 2) =:= 0,
filterevens(Y, Z).
evenSubList([X | Y], [Z | T]) :-
evenSubList(Y, [Z | T]).