take(HasX,X,NoX)
removes exactly one element X
from the list HasX
with the result list being NoX
.
take(HasX,X,NoX)
removes exactly one element X
from the list HasX
with the result list being NoX
.
take([H|T],H,T).
take([H|T],R,[H|S]) :- take(T,R,S).
Read the second clause as, "Given a list [H|T]
you can take R
from the list and leave [H|S]
if you can take R
from T
and leave S
".
?- take([1,2,3],1, Y).
?- take([2,3],1,X).
?- take([1,2,3],X,Y).
We can now build permutation using take.
perm([],[]).
perm(L,[H|T]) :- take(L,H,R), perm(R,T).
?- perm([1,2,3],X).
Implement a predicate checkFlag(L)
to see whether the list L
contains the colours in the right order.
checkRed([red|T]) :- checkRed(T).
checkRed([white|T]) :- checkWhite(T).
checkWhite([white|T]) :- checkWhite(T).
checkWhite([blue|T]) :- checkBlue(T).
checkBlue([blue|T]) :- checkBlue(T).
checkBlue([]).
checkFlag(L) :- checkRed(L).
?- checkFlag([red,white,blue,blue]).
?- checkFlag([white,red,blue,blue]).
checkRed([red|T]) :- checkRed(T).
checkRed([white|T]) :- checkWhite(T).
checkWhite([white|T]) :- checkWhite(T).
checkWhite([blue|T]) :- checkBlue(T).
checkBlue([blue|T]) :- checkBlue(T).
checkBlue([]).
checkFlag(L) :- checkRed(L).
Which one of the following queries is true?
?- checkFlag([white,blue]).
?- checkFlag([blue]).
?- checkFlag([]).
Which one of the following queries is true?
?- checkFlag([white,blue]).
true?- checkFlag([blue]).
false?- checkFlag([]).
falseHow can we prevent the first predicate from holding?
Introduce a new state chkRed2
in the transition system.
chkRed([red|T]) :- chkRed2(T).
chkRed2([red|T]) :- chkRed2(T).
chkRed2([white|T]) :- chkWhite(T).
chkWhite([white|T]) :- chkWhite(T).
chkWhite([blue|T]) :- chkBlue(T).
chkBlue([blue|T]) :- chkBlue(T).
chkBlue([]).
chkFlag(L) :- chkRed(L).
?- chkFlag([white,blue]).
Using the predicate mkFlag(L,F)
which makes the flag F
from the list of colours in L
.
mkFlag(L,F) :- perm(L,F), chkFlag(F).
?- mkFlag([white,red,blue,blue,blue],F) {1}.
In the above, perm
is the generate and chkFlag
is the test.
We can generalise our solution to the Dutch national flag problem to sorting.
Let us define a predicate sorted(L)
which holds if L
is sorted.
sorted([]).
sorted([H]).
sorted([A,B|T]) :- A =< B, sorted([B|T]).
?- sorted([1,2,3,4]).
?- sorted([1,3,2,4]).
Now sorting can be defined using the predicate permsort(L,SL)
, where SL
is the sorted version of L
.
permsort(L,SL) :- perm(L,SL), sorted(SL).
?- permsort([1,3,5,2,4,6], SL).
partition(L,X,LES,GS)
that given a list L
and an element X
partitions the list into two. LES
which contains elements from L
less than or equal to X
and GS
which contains elements from L
greater than X
.Let's first define a partition predicate partition(Xs,X,Ls,Rs)
that partitions elements in Xs
into Ls
and Rs
where $\forall E \in Ls. E =< X$ and $\forall E \in Rs. E > X$.
partition([],Y,[],[]).
partition([X|Xs],Y,[X|Ls],Rs) :- X =< Y, partition(Xs,Y,Ls,Rs).
partition([X|Xs],Y,Ls,[X|Rs]) :- X > Y, partition(Xs,Y,Ls,Rs).
?- partition([6,5,3,2,1,0],4,X,Y).
Quicksort works by partitioning the list into two, sorting each one, and appending to get the resultant sorted list.
quicksort([H|T],SL) :-
partition(T,H,Ls,Rs), quicksort(Ls,SLs), quicksort(Rs,SRs), append(SLs,[H|SRs],SL).
quicksort([],[]).
?- quicksort([6,5,4,3,2,1,0],SL).
Find the assignment of N-queens on a NxN chessboard such that none of the queens threaten each other.
[1,2,3,...,N]
.[1,6,8,3,7,4,2,5]
says that the first queen is on (1,1), second on (2,6), thrid on (3,8), forth on (4,3), fifith on (5,7), ...[1,2,3,...,N]
. Represent the positions of the queens as a permutation of [1,2,3,...,N]
.
[1,6,8,3,7,4,2,5]
says that the first queen is on (1,1), second on (2,6), thrid on (3,8), forth on (4,3), fifith on (5,7), ...[1,2,3,...,N]
. Importantly, two queens cannot be on the same row or column.
checkBoard([H|T]) :- L is H-1, R is H+1, checkRow(T,L,R), checkBoard(T).
checkRow([H|T],L,R) :- H =\= L, H =\= R, LN is L-1, RN is R+1, checkRow(T,LN,RN).
checkBoard([]).
checkRow([],_,_).
Example:
?- checkBoard([1,6,8,3,7,4,2,5]).
queens(B) :- perm([ 1, 2, 3, 4, 5, 6, 7, 8 ], B), checkBoard(B).
?- queens(B) {1}.
There are 92 solutions to 8-Queens problem. We can find them all.
?- queens(B) {92}.