CS 152 - Lecture 19

Cover page image

Cay S. Horstmann

Lists in Prolog

The Append Predicate

Numbers in Prolog

Note that factorial(N - 1, F1) would not work. (See the lab).

Use is to Evaluate Arithmetic

Generate and Test

Fun and Games

A Simple Game

Lab

???

Step 1: Arithmetic

  1. Consider this definition of a power of two predicate. pow2(N,M) means that M = 2N. (Remember, we need a predicate, not a function, at the top level in Prolog.)
    pow2(0, 1).
    pow2(N, F) :- N > 0, pow2(N-1, F1), F is 2 * F1.

    Try it out. What is the result of pow2(3,X)?

  2. Use the text-based tracer to trace to the step
    3-1-1-1 > 0

    Does it succeed? Does it fail? If so, why? What happens next?

  3. When you are done tracing, issue the query
    3-1-1-1 > 0.

    at the Prolog interpreter. What result do you get?

  4. Fix pow2 by forcing evaluation of the arithmetic. What is your code for pow2 now? Confirm that pow2(3, X) works.
  5. Try pow2(X,8). What happens?
  6. That's disappointing, but if you think about it, there is no way Prolog could have figured out the answer. Except...
  7. ...by trying all the possible answers. What is the result of evaluating numlist(1, 8 L)?
  8. Now try
    solvepow2(N,M) :- numlist(1, M, L), member(N, L), pow2(N, M).

    Try out solvepow2(X,8). Explain why it works.

Step 2: The Game of Nim

  1. In the game of Nim, two players alternately remove marbles from a pile of marbles. In each turn, a player must remove at least one marble, and at most half the marbles. The player who is left with one marble loses. We will represent the game state by a list of o functors, such as [o,o,o,o,o]. Your task is to write a predicate move(From, To) that checks whether one can legally move from game state From to game state To. For example,
    move([o,o,o,o,o],Y).
    Y = [o,o,o] ;
    Y = [o,o,o,o] ;
    fail

    Hint: It is very easy to check whether To is at least one less than F:

    append(To, [o|_], From)

    It is also easy to check that To is at least half as long as From. Append it to itself and check that you can append more to get From.

    What is your move predicate?

  2. A position is a winning position if the player can force a win, no matter what the opponent does.
    win(X) :- move(X,Y), not(win(Y)).

    For example,

    win([o,o,o,o,o]).
    true ;
    fail.

    Try out marble lists of length 1 to 10. Which ones are winning positions?