The Hamming distance between two integers is the number of positions at which the corresponding bits are different.
Given two integers x and y, calculate the Hamming distance.
0 ≤ x, y < 231.
1 | Input: x = 1, y = 4 |
Conditional operator (the if-then-else construct in Prolog):
if A then B else C is written as (A -> B ; C)
To Prolog this means:
Try A.
If you can prove it, go on to prove B and ignore C.
If A fails, however, go on to prove C ignoring B.
e.g.
1 | max(X, Y, Z) :- |
Consider the computation of n! (i.e. the factorial of n)
factorial(N, F) :- …
N is the input parameter; and F is the output parameter.
The body of the rule species how the output is related to the input.
For factorial, there are two cases:
N <= 0 and N > 0
1 | factorial(N, F) :- |
Other imperative features:
we can think of prolog rules as imperative programs with backtracking
1 | program :- |
fail: always fails, causes backtracking.
!: the cut operator, prevents other rules from matching.
Integer/Floating Point operators:
- +
- -
- *
- /
Interger operator:
- mod
- // (integer division)
Comparison operators:
- <
- >
- =<
- >=
- Expr1 =:= Expr2 (succeeds if expression Expr1
evaluates to a number equalto Expr2)- Expr1 =\= Expr2 (succeeds if expression Expr1
evaluates to a number non-equalto Expr2)
quicksort:
1 | quicksort([], []). |
We want to define delete/3, to remove a given element from a list (called select/3 in XSB’s basic library)
delete(2, [1, 2, 3], X) should succeed with X = [1, 3]
delete(X, [1, 2, 3], [1, 3]) should succeed with X = 2
delete(2, X, [1, 3]) should succeed with X = [2, 1, 3]; X = [1, 2, 3]; X = [1, 3, 2]; fail
Algorithm:
1 | delete(X, [], _) :- fail. % not needed |
Define permute/2, to find a permutation of a given list.
e.g. permute([1, 2, 3], X) should return X = [1, 2, 3] and upon backtracking, X = [1, 3, 2], X = [2, 1,3], X = [2, 3, 1], X = [3, 1, 2], and X = [3, 2, 1]
The program:
1 | permute([], []). |
Define a predicate, rev/2 that finds the reverse of a given list.
e.g. rev([1, 2, 3], X) should succeed with X = [3, 2, 1]
Hint: what is the relationship between the reverse of [1, 2, 3] and the reverse of [2, 3]?
Answer: append([3, 2], [1], [3, 2, 1])
The program:
1 | rev([], []). |
How long does it take to evaluate rev([1, 2, …, n], X)?
T(n) = T(n - 1) + time to add 1 element to the end of an n - 1 element list
= T(n - 1) + n - 1
= T(n - 2) + n - 2 + n - 1
= …
= O(n^2)
Making rev/2 faster
Keep an accumulator: a stack all elements seen so far.
The program:
1 | rev(L1, L2) :- rev(L1, [], L2). |
Assume you have a binary tree, represented by
node/3 facts: for internal nodes: node(a, b, c) means that a has b and c as children.
leaf/1 facts: for leaves: leaf(a) means that a is a leaf.
Example:
node(5, 3, 6).
node(3, 1, 4).
leaf(1).
leaf(4).
leaf(6).
1 | 5 |
Write a predicate preorder/2 that traverses the tree (starting from a given node) and returns the list of nodes in pre-order.
Algorithm:
1 | preorder(Root, [Root]) :- |
The program takes O(n^2) time to traverse a tree with n nodes.
There are several ways to represent graphs in Prolog:
Represent each edge separately as one clause (fact):
edge(a, b).
edge(b, c).
The whole graph as one data object: as a pair of two sets (nodes and edges): graph([a, b, c, d, f, g], [e(a, b), e(b, c), e(b, f)])
Adjacency-list:
p.105
Task of building a predictive model of language.
A language model is used to predict two types of quantities.
Probability of observing a sequence of words from a language.
e.g., Pr(Colorless green ideas sleep furiously) = ?
Probability of observing a word having observed a sequence.
e.g., Pr(furiously | Colorless green ideas) = ?
Machine translation
Handwriting recognition
Spelling correction
More generally
A language model is something that specifies the following two quantities, for all words in the vocabulary (of a language).
Probability of a sentence or sequence
Pr(w_1, w_2, w_3, …, w_k)
e.g., Pr(I, love, food) =/= Pr(love, I, food)
Probability of the next word in a sequence
Pr(wk | w_1, w_2, …, w_k-1)
functor and ti is an argument.Example: expression trees:
plus(minus (num(3), num(1)), star(num(4), num(2)))
Data structures may have variables. And the same variable may occur multiple times in a data structure.
Prolog uses a special syntax to represent and manipulate lists (syntacic sugar = internally, it uses structures):
[1, 2, 3, 4]: represents a list with 1, 2, 3, and 4, respectively.
This can also be written as [1 | [2, 3, 4]]: a list with 1 as the head (first element) and [2, 3, 4] as its tail (the list of remaining elements).
The empty list is represented by [] or nil.
The symbol “|” (pipe) and is used to separate the beginning elements of a list from its tail.
For example:
[1, 2, 3, 4] = [1 | [2, 3, 4]] = [1| [2 | [3, 4]]] = [1, 2 | [3, 4]] = [1, 2, 3 |[4]] = [1 | [2| [3| [4| []]]]]
Lists are special cases of trees
For instance, the list [1, 2, 3, 4] is represented by the following structure:
1 | . |
1 |
|
Strings: A sequence of characters surrounded by double quotes is equivalent to a list of (numeric) character codes: “abc”, “John Smith”, “to be, or not to be”.
?- X= “abc”.
X = [97, 98, 99]
to find if a given element occurs in a list
concatenate two lists to form the third list
finds the length of a list (first argument).
Given a binary tree
1 | struct TreeLinkNode { |
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
Given the following perfect binary tree,
1 | 1 |
After calling your function, the tree should look like:
1 | 1 -> NULL |