Logic Programming and Artificial Intelligence Prolog Lab Problem Sheet 2 1. Define a predicate listless/3 which has as its first argument a number and as its second argument and third argument a list of numbers. The predicate only succeeds when the third argument is the same as the second argument, but with all numbers greater than the first argument removed. For example: ?- listless(3, [1,2,3,4,5,6], X). X = [1, 2, 3] 2. Add the following facts to a file or download the file lord.pl from the LPA web page: character(frodo, hobbit). character(bilbo, hobbit). character(gandalf, wizard). character(saruman, wizard). character(aragorn, man). character(faramir, man). character(boromir, man). character(legolas, elf). character(gimli, dwarf). a) Write a predicate nonchar/2 which succeeds only when its _rst argument is a list and its second argument is the same list but with all the non-character names removed. You will need to use negation to solve this problem. For example: ?- nonchar([faramir, gandalf, gimli], X). X = [faramir, gandalf, gimli] ?- nonchar([faramir, ed, gandalf, gimli, eds_one_mate, eds_other_mate], X). X = [faramir, gandalf, gimli] b) Define a predicate is char list/1 whose single argument is a list and the predicate is true only when all elements of the list are characters. Use a failure-driven loop to write this predicate. You'll probably need the definition of a list membership predicate, such as memb/2 from the lecture slides. You can also, if you like, take advantage of SWI-Prolog's automatic loading of libraries and use the built-in member/2 predicate. When you load your program which uses the built-in member/2 predicate, SWI-Prolog will automatically load the list library to provide the predicate. memb(X, [X|_]). memb(X, [_|Xs]) :memb(X, Xs). Examples of using char_list/1: ?- is_char_list([gandalf, bilbo]). Yes ?- is_char_list([ed, and, his, cleaning, robot]). No 3. Some more list exercises: a) Define a predicate add(Item, List, Newlist), where Newlist consists of List with Item at the front. b) Define a predicate del(Item, List, Newlist), where Newlist consists of List with an occurrence of Item removed from it. c) Define a predicate insert(Item, List, Newlist), where Newlist consists of List with Item added into it somewhere (not necessarily at the front). Your definition should be given in terms of del alone by exploiting del's limited polymodality. 4. For this question, you need to implement a simple sorting predicate in Prolog. The sorting algorithm is bubblesort, which basically consists in examining the first two elements of the list, reordering them if necessary, sorting the remainder of the list and then seeing if the start of the ordered part is greater or less than the greater of the first two considered. Hints: In the simplest implementation of bubblesort, there should be 5 clauses in total, a base case and four recursive clauses, depending on the results of the two comparisons in the question. Implement a predicate bsort/2 which is true if its two arguments are both lists and the second list is an ordered version of the first list. 5. In this question, you will write a more elegant version of bsort/2 than the one in question 4, call it bubblesort/2. First, define a predicate swap/2 that is true when the first two unsorted elements of its first argument are sorted in the second argument. For example: ?- swap([4,3,2,1], X). X = [3, 4, 2, 1] ; X = [4, 2, 3, 1] ; X = [4, 3, 1, 2] ; No Now, define a predicate bubblesort/2 which exploits the polymodality of swap/2 to do the same as bsort/2 from question 4. Note that it is likely your program will be able to compute more than one solution to the problem each time you press the semicolon. These new solutions may not be sorted lists. This is fine (it's a feature, not a bug!). 6. Even more exercises on lists: a) Define a predicate last/2 which is true if its second argument is the last element of its first argument, the first argument being a list. b) Define a predicate which checks for consecutive elements: next_to(X, Y, L) succeeds if elements X and Y are consecutive elements of list L The answer has some of the flavor of last. c) Define predicates evenlength(L) and oddlength(L) using mutual recursion, where evenlength(L) succeeds if L has an even number of elements in it and oddlength(L) succeeds if L has an odd number of elements in it. Note, you do not necessarily need arithmetic expressions to do this if you utilize the mutual recursion between an odd-length list and an even-length list! 7. Consider the digits: 1234567890. First remove one digit, then swap two adjacent digits and then insert some number of plus signs between the digits. There is a way to do this so that the answer to the resulting arithmetic expression is 2004! But how? Write a Prolog program to do it! Hints: You should define the digits as a list in your code, i.e. put the fact: digits([1,2,3,4,5,6,7,8,9,0]) in your program. You'll have to represent the addition operator by a constant such as plus. Don't use + as it may confuse Prolog. Also, if the solution (a list containing numbers and one or more plus signs inserted) gets too long, Prolog may shorten it using the ... notation. To see the full solution, add a write/1 clause in your program that outputs the solution once one has been found. You may need to use the number/1 predicate. This predicate is true if its single argument is a number. Using number/1 you can differentiate between numbers and the plus operator. Then, the problem is simplified to: • Define a predicate that removes an element of a list. • Define a predicate that swaps adjacent elements of a list. • Define a predicate that, for each successive pair of numbers in a list, can either add a plus constant between them or leave that pair unchanged. • Define a predicate which returns the numeric value of a list that contains numbers and occurrences of plus, as if it was a numerical expression There is only one answer to this puzzle!