CS 313 - Homework 9 - Prolog

Due: Wednesday 4/29 in class

This assignment consists of several programming problems in Prolog. The assignment has two parts; the first part you have to solve individually, but on the second part you can work in groups of two if you want. Hand in a printout of your code (for the second part, one per group). As always, include sample output! On the first page of your printout, write your name, the names of the students with whom you collaborated, and how much time it took you.

Prolog on the lab machines

A Prolog interpreter called SWI-Prolog is installed in the lab. To run it, simply type "pl":
abe:~/cs313/prolog% pl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.6.64)
Copyright (c) 1990-2008 University of Amsterdam.
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?-
At the prompt you can enter Prolog queries, terminated by a period:
?- X is 2+3.
X = 5.

?-
You can load a file "myprog.pl" with the command "consult(myprog)." or the shorthand "[myprog].":
?- [pete1].
% pete1 compiled 0.00 sec, 3,104 bytes
true.

?-
To exit, type control-D.

Part 1 - to be done individually

  1. Sethi, page 470, problem 11.3 a, b, c, d.
    Sample output:
    1. ?- permutation([a, b, c], [b, a, c]).
      true .
      
      ?- permutation([1, 2, 2], [2, 1, 1]).
      false.
      
      ?- permutation([1, 2, 2], [2, 2, 1]).
      true .
      
    2. ?- evenLength([1,2,3]).
      false.
      
      ?- evenLength([1,2,3,4]).
      true.
      
      ?- evenLength([1,2,3,4,5]).
      false.
      
    3. For the purpose of this problem, let "merging" mean interleaving the elements of the two lists while keeping them in order.
      ?- mergeLists([a,b],[c,d,e],[a,c,d,e,b]).
      true .
      
      ?- mergeLists([a,b],[1,2,3],[1,a,2,b,3]).
      true .
      
      ?- mergeLists([a,b],[1,2],[1,2,a,b]).
      true .
      
      ?- mergeLists([a,b],[1,2],[1,2,b,a]).
      false.
      
      ?- mergeLists([1,2], [3], X).
      X = [1, 2, 3] ;
      X = [1, 3, 2] ;
      X = [3, 1, 2] ;
      false.
      
    4. ?- palindrome([1,2,3]).
      false.
      
      ?- palindrome([1,2,3,2,1]).
      true.
      
      ?- palindrome([1,2|T]).
      T = [1] ;
      T = [2, 1] ;
      T = [_G318, 2, 1] .
      
  2. Sethi, page 471, problem 11.4 a. Sample output:
        ?- removeDup([1,2,2,3,3,3,4,5,5], X).
        X = [1, 2, 3, 4, 5] .
    
        ?- removeDup([2,2,1,1,2,2,a,a,1,1,1], X).
        X = [2, 1, 2, a, 1] .
    
  3. Sethi, page 471, problem 11.6 a, b. (Factorial, recursive and tail-recursive.) Sample output:

        ?- factorial(7, X).
        X = 5040 .
    
        ?- factorial2(10, X).
        X = 3628800 .
    
  4. How much time did it take you to complete part 1?


Part 2 - can be done in groups of 2

  1. Extend the file bst.pl to handle insertion and deletion in binary search trees.

    1. Insertion:
            insert(N, T, Result)
      
      should insert the number N into tree T and return the result in Result. If N is already contained in T, nothing should happen (i.e., Result = T). Sample output:
        ?- insert(3, nil, Result).
        Result = node(3, nil, nil) .
        
        ?- insert(3, node(2, nil, nil), Result), show(Result).
            3
        2
        
        Result = node(2, nil, node(3, nil, nil)) 
        
        ?- insert(3, node(3, nil, nil), Result).
        Result = node(3, nil, nil) .
        
        ?- mytree1(T), insert(6, T, Result), show(Result).
                9
            8
                7
          	      6
        5
            3
        
        T = node(5, node(3, nil, nil), node(8, node(7, nil, nil), node(9, nil, nil)))
        Result = node(5, node(3, nil, nil), node(8, node(7, node(6, nil, nil), nil), node(9, nil, nil))) .
      
    2. Deletion:
            remove(N, T, Result)
      
      should remove the number N from tree T and return the result in Result. If N is not contained in T, nothing should happen (i.e., Result = T). Recall from class that the algorithm for deletion is as follows (let N be the node to be deleted):
      • if N is a leaf, return nil
      • if N has only one child, return that child
      • if N has two children, replace N's value with the maximum value in the left subtree, and remove that value from the left subtree.
      Sample output:
           ?- remove(3, node(3, nil, nil), Result).
           Result = nil .
           
           ?- remove(3, node(3, node(2, nil, nil), nil), Result).
           Result = node(2, nil, nil) .
           
           ?- remove(2, node(3, node(2, nil, nil), nil), Result).
           Result = node(3, nil, nil) .
           
           ?- remove(1, node(3, node(2, nil, nil), nil), Result).
           Result = node(3, node(2, nil, nil), nil) .
           
           ?- mytree1(T), show(T).                           
      	     9
      	 8
      	     7
           5
      	 3
           
           ?- mytree1(T), remove(5, T, Result), show(Result).
      	     9
      	 8
      	     7
           3
           
           ?- mytree1(T), remove(8, T, Result), show(Result).
      	     9
      	 7
           5
      	 3
           
           ?- T=node(4,node(2,node(1,nil,nil),node(3,nil,nil)),node(5,nil,nil)),show(T).
      	 5
           4
      	     3
      	 2
      	     1
           
           ?- T=node(4,node(2,node(1,nil,nil),node(3,nil,nil)),node(5,nil,nil)),
           |    remove(4, T, Result), show(Result).
      	 5
           3
      	 2
      	     1
           
  2. Extend Pete's puzzle solver (pete1.pl in ~schar/cs313/prolog/) to handle expressions in which the equal sign is not in the middle. E.g.,
          ?- solve(6,2,7,8).
          6=2*7-8
    
          ?- solve(3,6,1,1).
          3=6/ (1+1)
    
          ?- solve(1,2,3,9).
          (1+2)*3=9
    
          ?- solve(5,6,3,7).
          5+6/3=7
    
  3. Extend Pete's puzzle solver again, this time to handle the unary operators "-" and square root ("sqrt") in each subexpression. If your program does not always come up with the simplest expressions first - that's ok.

    Sample output (if yours is slightly different, that's ok too - as long as it finds an answer):

         ?- solve(1,2,3,9).
         1+2=sqrt(3*sqrt(9))
         
         ?- solve(2,4,3,1).
         - (2+ (-4))=sqrt(3+1)
         
         ?- solve(2,4,3,8).
         2+sqrt(4)*3=8
         
         ?- solve(4,2,6,7).
         sqrt(4)/2= - (6+ (-7))
         
         ?- solve(8,6,3,7).
         8+ (-6)=sqrt(-3+7)
    
    Your program should also be able to solve the following puzzles:
         9 4 6 8
         3 7 8 6
         4 4 5 2
         6 4 7 2
    
    
  4. Extra credit (varying amounts, depending on difficulty): Extend Pete's puzzle solver further. Possibilities include: exponentiation, nth root, factorial, and an arbitrary number of unary operators (but trying the fewest number first). (Let's not use "mod" as a valid operation.) Most of these are quite tricky - some (like factorial) require defining new arithmetic functions, others (like exponentiation) require several checks on valid parameters. Ask me for help if you get stuck.

    Which of the following puzzles can your program solve?

         3 5 2 2
         3 5 7 0
         4 6 5 0
         1 7 4 1
         1 7 5 7
         3 5 2 5
         4 7 3 7
         7 4 7 9
         8 6 8 0
         5 8 5 7
    
  5. How much time did it take you to complete part 2?