Home > front end >  Prolog - Check if second list has all even numbers from the first list
Prolog - Check if second list has all even numbers from the first list

Time:03-24

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]). 
  • Related