CS 313 - Homework 9 - Prolog

Due: Friday 5/5 at 11:15am

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. Please submit your code for this homework as a single file hw9.pl containing all your code. For part two, if you work on a team, only one person should have the code in their hw9.pl file, the other person should just have a comment indicating the name of the team member submitting the code.

As always, include sample output (as comments in your file). Upload your file via the HW 9 submission page by the beginning of class on Friday.

Prolog on the lab machines

A Prolog interpreter called SWI-Prolog is installed in the lab. To run it, type "swipl", or, better yet, "rlwrap swipl":
abe:~/cs313/prolog% rlwrap swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 7.4.0-rc1)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in 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].
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 b. (Factorial, tail-recursive.) Sample output:

        ?- factorial(10, X).
        X = 3628800 .
    

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 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