Anda di halaman 1dari 12

Artificial Intelligence

Mini Project.

Lady Limunga Jemea

Subject description

The subject aims to write a program to play with


numbers.
Consider L a list of numbers and S a number. The goal is
to obtain S by applying the four basic arithmetic
operations (addition, subtraction, multiplication and
division) on the elements of the list L, if possible. Note
that each number in L can be used only once, but the use
of all of them is not compulsory.
Let F an arithmetical expression whose value is S. The list
of numbers in F is a permutation of a sublist of L. Then,
the principle of the program you are going to write is to
find the permutations of all possible sublists of L and
combine the numbers in each of them with the four basic
arithmetic operations.
1. Write a predicate is_sublist(L1, L) which succeeds if L1
is a sublist of L.
?- is_sublist([3,4],[2,3,5,4]).
true
?- is_sublist(L1,[3,4]).
L1 = [] ;
L1 = [4] ;
L1 = [3] ;
L1 = [3, 4] ;
false
?- is_sublist([3,4],[2,3,5]).
false

2. Write a predicate permutation(L1,L) which succeeds if


L1 is a permutation of L.
?- permutation([3,4,2,5],[2,3,5,4]).
true
?- permutation([4,5],[3,5,4]).
false
3. Write a predicate concatenation(L1,L2,L) which
succeeds if L is the concatenation of lists L1 and L2, and
if neither L1 nor L2 is empty.
Hint: You can use the built-in predicate append. (Look at
SWI-Prolog help if needed)
?- concatenation([3,4],[2,3], L).
L = [3,4,2,3]
?- concatenation([],[3,5,4],[3,5,4]).
false
4. Write a predicate chain(L1,L2,Op,L) which succeeds if L
is the list obtained from the concatenation of L1, L2 and
Op.
?- chain(1,2,[+],L).
L = [1, +, 2]
?- chain([3,+, 4],[5,-,6],[*],L).
L = [[3, +, 4], *, [5, -, 6]]
5. Write a predicate associate([A,LA],[B,LB],[C,LC]),
where A, B and C are numbers ; LA, LB and LC are

arithmetic expressions used to obtain these numbers, in


the form of lists. Four cases will be considered:
If C=A+B, then LC = [LA, +, LB]
If C=A-B, then LC = [LA, -, LB]
If C=A*B, then LC = [LA, *, LB]
If C=A/B, then LC = [LA, /, LB]
Hint: the operator mod can be used.
6. Write a predicate compute(L,D) where L is a list of
integers, and D is a list of 2 elements : an integer and the
arithmetic expression (in the form of a list) used to obtain
the integer. The predicate compute(L,D) should build all
the values of D that can be obtained from L.
Hint: This predicate could divide the list L into two
sublists on which it recursively calls itself.
7. Write the predicate numbers(L,S,D) where L is a list of
integers, S the number to obtain, and that build if
possible, the list D with two elements, containing an
integer and the arithmetic expression (in the form of a
list) to obtain it from L.
?- numbers([2,3,25,7,1,3], 347, D).
D = [347, [[25, *, [7, *, [3, -, 1]]], -, 3]].
8. Provide an adequate GUI to run your program (your
predicates) in a convenient way. You should use XPCE
Prolog for the GUI.

SOLUTION
Please load the file ui.pl in order to test the program.
Explanations for each predicate can be found in the
commented source code below.

1. Mini.pl
/* making the numbers function global such that it can be
accessed from within another prolog file*/
:- module(kb,[numbers/3]).
/*sublist predicate checks if a list is a sublist of another*/
is_sublist([], _).
is_sublist([H|R], [H|T]) :is_sublist(R, T).
is_sublist([H|R], [_|T]) :is_sublist([H|R], T).
/*checks if a list is a permutation of another*/
is_permutation(L1,L2):permutation(L1,L2).

/* a helper predicate to make sure a list is not the empty


list*/
notempty(L):L \= [].
/*makes sure a two list are not empty then appends them
together*/
concatenation(L1,L2,L):notempty(L1),
notempty(L2),
append(L1,L2,L).
/*creates a list out of two lists and and operator. the
operator itself is placed in a list.*/
chain(L1,L2,Op,L):concatenation([L1],Op,L3),
concatenation(L3,[L2],L).
/*performs all possible arithmetic operations on a list
created with chain above*/
associate([A,LA],[B,LB],[C,LC]):C is A+B,
chain(LA, LB, [+], LC).
associate([A,LA],[B,LB],[C,LC]):C is A-B,
chain(LA, LB, [-], LC);
C is B-A,

chain(LB, LA, [-], LC).


associate([A,LA],[B,LB],[C,LC]):C is A*B,
chain(LA, LB, [*], LC).
associate([A,LA],[B,LB],[C,LC]):0 \== B,
C is A/B,
chain(LA, LB, [/], LC);
0 \== A,
C is B/A,
chain(LB, LA, [/], LC).
/*evaluate is a helper predicate to faciltate the
functioning of the compute predicate. it also serves as a
base case for compute*/
/*it uses the associate predicate to do this*/
evaluate([X], [X, X]).
evaluate([H|T], A) :evaluate(T, S),
associate([H, H], S, A).
/*compute finds out all operations that can be applied on
each list item , given an operator*/
compute(L,D):is_sublist(S,L),

evaluate(S,D).
/*numbers recieves a list and an element and a variable
returns all possible arithemetic opertations to obtain the
element */
numbers(L,S,[S|D]):compute(L,[S|D]).

2.

Ui.pl

/*the ui imports the knowledge base mini.pl and the


pce library*/
:- use_module(mini).
:- use_module(library(pce)).
:-

/*Create a window titled Number Game*/


new(Window, frame('Number Game')),
/*create an dialog (group of items) called input
dialog and adds it to the window*/
send(Window, append(new(Input_Dialog,
dialog))),
/* create a text area and place it below the
dialog created above*/
send(new(Expressions_Browser, browser),
below(Input_Dialog)),
/*create a dialog (group of items) and place it
under the text area*/
send(new(Action_Dialog, dialog),
below(Expressions_Browser)),
/*creates a text box and label for user to input a
list of numbers*/
new(List_of_Numbers,
text_item(list_of_numbers)),
/*specify that the data returned from text box
above should be string*/
send(List_of_Numbers, type(string)),
/*creates a text box and label for user to input
the expected result of the computation on the list
items*/

new(Expected_Result,
text_item(expected_result)),
/*specify that the data returned from text box
above should be int*/
send(Expected_Result, type(int)),
/*add the two text boxes, to the first dialog
created above and place a label beneath them*/
send_list(Input_Dialog, append,
[List_of_Numbers,
Expected_Result,
label(list_of_expressions, "Arithmetic
Expressions:", bold)
]),
/*add three command buttons to the second
dialog box*/
/*one to close the window*/
/*one to delete all entries*/
/*one to perform the game logic and determine
all possible arithmetic expresions using predicates in
the loaded knowledge base*/
send_list(Action_Dialog, append,
[
button(quit, and(
message(Window, destroy))),
button(new_game, and(
message(List_of_Numbers, clear),
message(Expected_Result, clear),
message(Expressions_Browser, clear))),
button(generate, message(
@prolog, process_input,
List_of_Numbers?selection,
Expected_Result?selection,
Expressions_Browser))

]),
send(Window, open).
/*this predicate is called whenever the user
clicks on the generate button.*/
/*its converts the string entered into a list and
passes it to the numbers predicate along with the
expected result*/
/*the numbers predicate then returns all possible
arithmetic expressions with the help of find all */
/* and the results are formated to look
mathematical*/
process_input(List_of_Numbers, Expected_Result,
Expression_Browser) :get(List_of_Numbers, split, ,, Initial_Chain),
new(Final_Chain, chain()),
send(Initial_Chain, for_all, message(
Final_Chain,
append,
?(number(0), convert, @arg1)?value)),
chain_list(Final_Chain, List),
findall(Expression_as_String,
(mini:numbers(List, Expected_Result,
[Expected_Result|Expression]),
swritef(Expression_as_String, '%w',
[Expression])),
List_of_Expressions),
chain_list(Chain_of_Expressions,
List_of_Expressions),
send(Chain_of_Expressions,
for_all,
message(@arg1, delete, 0, 1)),
send(Chain_of_Expressions,
for_all,
message(@arg1, delete, @arg1?size-1, 1)),

send(Chain_of_Expressions,
for_all,
message(@arg1, translate, ',', '\s')),
send(Chain_of_Expressions,
for_all,
message(@arg1, translate, '[', '(')),
send(Chain_of_Expressions,
for_all,
message(@arg1, translate, ']', ')')),
send(Expression_Browser, members,
Chain_of_Expressions).
/*thats it*/

Anda mungkin juga menyukai