# Lab 11: Logic Programming II

Learning objectives:

• Gain experience writing Prolog predicates

This labs aims to further prepare you for homework 3, which covers logic programming in Prolog.

```\$ wget https://eecs390.github.io/lab/lab11/starter-files.tar.gz
\$ tar xzf starter-files.tar.gz
```
1. Sieve of Eratosthenes. The sieve of Eratosthenes is a method for computing prime numbers. Given a set that initially contains all the natural numbers starting from 2, the algorithm is as follows:

1. Let k be the smallest number still in the set. It must be the case that k is prime, so add k to the result.
2. Eliminate all multiples of k from the set.
3. If any numbers remain in the set, go to step 1.

For this problem, write your code in sieve.pl.

1. Write a Prolog predicate filter_not_multiple that relates a number and a list of numbers to another list with multiples of the number filtered out:

```?- filter_not_multiple(2, [2, 3, 4, 5, 6, 7, 8], Filtered), !.
Filtered = [3, 5, 7].
```
2. Write a Prolog predicate sieve that relates a list of numbers to another list resulting from the application of the Sieve of Eratosthenes:

```?- sieve([2, 3, 4, 5, 6, 7, 8, 9, 10, 11], Sieved), !.
Sieved = [2, 3, 5, 7, 11].
```

Your solution should use filter_not_multiple. Assume that the input numbers are sorted in increasing order.

3. Write a Prolog predicate primes that relates an upper bound to the set of primes up to that upper bound:

```?- primes(20, Primes), !.
Primes = [2, 3, 5, 7, 11, 13, 17, 19].
```

Use the built-in numlist predicate to generate a sorted list of numbers.

2. List manipulation. Complete the following Prolog list problems. You may use the built-in arithmetic and list operations. You may not use any built-in predicates. You may write helper predicates.

1. Write a Prolog predicate any_contains that relates a list of lists and an item, and is true if and only if at least one of the inner lists contains the item. Examples:

```?- any_contains([[1], [2, 3], [4]], a), !.
false.
?- any_contains([[1], [2, 3], [4]], 3), !.
true.
```

2. Write a Prolog predicate unzip that succeeds if its first argument is the "zip" of the second and third arguments, meaning that it interleaves the items from the second and third arguments. The second argument is required to be exactly the same length as, or one item larger than, the third argument. For example:

```?- unzip([a, b, c, d, e, f], Evens, Odds), !.
Evens = [a, c, e],
Odds = [b, d, f].
?- unzip([a, b, c, d, e], Evens, Odds), !.
Evens = [a, c, e],
Odds = [b, d].
```

```?- filter_nonempty([[1], [], [2, 3, 4], [], [a, b]], X), !.