Solution
%% If the input list is empty, the output list has %% to be empty as well. replace_a_b_c([],[]). %% If the input list is not empty, there are four cases. %% First case: the first element is an a. The first element %% of the output list has to be a b. OutTail should be what %% you get what properly replacing all a's, b's, and c's in InTail. replace_a_b_c([a|InTail],[b|OutTail]) :- replace_a_b_c(InTail,OutTail). %% Second case: the first element is a b. replace_a_b_c([b|InTail],[c|OutTail]) :- replace_a_b_c(InTail,OutTail). %% Third case: the first element is a c. replace_a_b_c([c|InTail],[a|OutTail]) :- replace_a_b_c(InTail,OutTail). %% Fourth case: the first element is something else. replace_a_b_c([X|InTail],[X|OutTail]) :- replace_a_b_c(InTail,OutTail).Download the knowledge base here.
This predicate takes a list and replaces all a's by b's, all b's by c's, and all c's by a's. However, if you force Prolog to backtrack (using the semicolon), it will give you other solutions as well. Try it out. Do you see why this is the case and how it can be fixed?
The problem is due to the definition of the last rule. It does
not explicitly specify that it should only be applied to lists
where the first element is neither an a, nor a b,
nor a c. So, when Prolog is asked to look for alternative
solutions, it actually applies this clause to lists which do
have an a, or a b, or a c as first
element. So, we have to tell Prolog that it shouldn't be doing
that. Here is the improved version of the fourth
clause. Remember that \=
means does not
match.
%% Fourth case: the first element is something else. replace_a_b_c([X|InTail],[X|OutTail]) :- X \= a, X \= b, X \= c, replace_a_b_c(InTail,OutTail).Download the improved knowledge base here.