Prolog Cookbook
• Classic factorial function,
1
factorial(0, 1).
2
factorial(N, N_Fact) :-
3
N > 0,
4
M is N-1,
5
factorial(M, M_Fact),
6
N_Fact is M_Fact*N.
Copied!
• Fibonacci functions
1
;; Non tail recursive version - is going to stack overflow quickly
2
fib(0, 0).
3
fib(1, 1).
4
fib(N, N_Fib) :-
5
N > 1,
6
M is N-1,
7
T is N-2,
8
fib(M, M_Fib),
9
fib(T, T_Fib),
10
N_Fib is M_Fib + T_Fib.
11
12
;; Tail recursive version
13
fibonacci(N, N_Fib) :- tfib(N, 0, 1, N_Fib).
14
tfib(0, A, _, A).
15
tfib(N, A, B, N_Fib) :-
16
N > 0,
17
Next_N is N-1,
18
Next_A is B,
19
Next_B is A + B,
20
tfib(Next_N, Next_A, Next_B, N_Fib).
Copied!
• Aggregate counting in SWI-Prolog,
1
likes(jimmy, anna).
2
likes(paul, anna).
3
likes(jimmy, paul).
4
5
popular(X) :- aggregate(count, Y^likes(Y,X), N), N > 1.
Copied!
Here, `popular` function checks whether given person is liked by more than one person. In the definition `Y` is existentionally qualified.
• Higher order functions,
1
double(X, Y) :- Y is X + X.
2
pow2(X, Y) :- Y is X * X.
3
4
map([], _, []).
5
map([X|Xs], P, [Y|Ys]) :-
6
call(P, X, Y),
7
map(Xs, P, Ys).
8
9
;; Examples
10
map([1, 2, 3], double, Xs). ;; Xs = [1, 4, 6]
11
map([1, -2, 3], pow2, Xs). ;; Xs = [1, 4, 9]
Copied!
• 1
current_predicate(map/3). ;; checks whether map which takes 3 parameters exists
Copied!
• Define contains based on append function,
1
append([], Ys, Ys).
2
append([X|Xs], Ys, [X|Zs]) :- append(Xs, Ys, Zs).
3
4
prefix(P, L) :- append(P, _, L).
5
suffix(S, L) :- append(_, S, L).
6
7
contains(SubL, L) :- suffix(S, L), prefix(SubL, S), !.
Copied!
• Palindrome check in Prolog is quite nice,
1
palindrome(Xs) :- reverse(Xs, Xs).
Copied!
In a restricted set, we can even use this declarative definition to generate palindromes, as in the following example!
1
member(X, [1, 2, 3]),
2
member(Y, [10, 11, 12]),
3
member(Z, [1, 2]),
4
palindrome([X, Y, Z]).
Copied!
• Fizz buzz in Prolog,
```prolog print_fizz_buzz(N) :- ( 0 is mod(N, 15) -> write("fizzbuzz"),nl ; 0 is mod(N, 3) -> write("fizz"), nl ; 0 is mod(N, 5) -> write("buzz"), nl ; write(N), nl ).
fizz_buzz(N) :- aux_fizz_buzz(0, N). aux_fizz_buzz(M, N) :- M < N, print_fizz_buzz(M), M1 is (M + 1), aux_fizz_buzz(M1, N). aux_fizz_buzz(M, N) :- M >= N, !, nl.
1
- `current_op` can be used to find out precedence and type of an operator.
2
Example, to find out these information about `mod`,
3
4
```prolog
5
current_op(Precedence, Type, mod).
Copied!
In true Prolog fashion, one can find out all the operators which are curently definied using something like follows,
1
current_op(Precedence, Type, Op).
Copied!
which will list all the opeartors with their respective precedence and type.
• Permutations,
1
take([H|T], H, T).
2
take([H|T], R, [H|S]) :- take(T, R, S).
3
4
perm([], []).
5
perm(List, [H|T]) :- take(List, H, R), perm(R, T).
Copied!