0

I've just started learning Prolog. I am practicing from a fruit sample. but I could not create a structure that allows users to select by number. The examples I look at on the internet are not effective on the fruit sample.

when I run the following code on SWISH-Prolog, I have to write the values ​​in the list one by one. how can I select "1,2,3,4" instead of red, orange, yellow, green, purple, peach?

error code block:

menuask(Attr, Val, List) :- 
    write('What is the value for '), write(Attr), write('? '), nl,
    write (1. red), nl,
    write (2. orange), nl,
    read(Ans),
    check_val(Ans, Attr, Val, List),
    asserta(known(yes, Attr, Ans)),
    Ans == Val.

in the "menuask" gives an error. I tried it.

Prolog All Codes:

:- dynamic(known/3).
:- discontiguous menuask/3.
:- discontiguous ask/2.
% 
% % Data: fruit(X) :- attributes(Y)
fruit(banana) :- colour(yellow), shape(crescent).
fruit(apple) :- (colour(green); colour(red)), shape(sphere), stem(yes).
fruit(lemon) :- colour(yellow), (shape(sphere);shape('tapered sphere')), acidic(yes).
fruit(lime) :- colour(green), shape(sphere), acidic(yes).
fruit(pear) :- colour(green), shape('tapered sphere').
fruit(plum) :- colour(purple), shape(sphere), stone(yes).
fruit(grape) :- (colour(purple);colour(green)), shape(sphere).
fruit(orange) :- colour(orange), shape(sphere).
fruit(satsuma) :- colour(orange), shape('flat sphere').
fruit(peach) :- colour(peach).
fruit(rhubarb) :- (colour(red); colour(green)), shape(stick).
fruit(cherry) :- colour(red), shape(sphere), stem(yes), stone(yes).

% Expert recogniser
% Asks
colour(X) :- menuask(colour, X, [red, orange, yellow, green, purple, peach]).
shape(X) :- menuask(shape, X, [sphere, crescent, 'tapered sphere', 'flat sphere', stick]).
acidic(X) :- ask(acidic, X).
stem(X) :- ask(stem, X).
stone(X) :- ask(stone, X).

% Remember what I've been told is correct
ask(Attr, Val) :- known(yes, Attr, Val), !.
menuask(Attr, Val, _) :- known(yes, Attr, Val), !.
% % Remember what I've been told is wrong
ask(Attr, Val) :- known(_, Attr, Val), !, fail.
menuask(Attr, Val, _) :- known(_, Attr, Val), !, fail.
% Remember when I've been told an attribute has a different value
ask(Attr, Val) :- known(yes, Attr, V), V \== Val, !, fail.
menuask(Attr, Val, _) :- known(yes, Attr, V), V \== Val, !, fail.
% % I don't know this, better ask!
ask(Attr, Val) :- write(Attr:Val), write('? '), read(Ans), asserta(known(Ans, Attr, Val)), Ans == yes.
menuask(Attr, Val, List) :- 
    write('What is the value for '), write(Attr), write('? '), nl,
    write(List), nl,
    read(Ans),
    check_val(Ans, Attr, Val, List),
    asserta(known(yes, Attr, Ans)),
    Ans == Val.

check_val(Ans, _, _, List) :- member(Ans, List), !.
check_val(Ans, Attr, Val, List) :- 
    write(Ans), write(' is not a known answer, please try again.'), nl,
    menuask(Attr, Val, List).

go :- fruit(Fruit), write('The fruit is '), write(Fruit), nl.
dan1st
  • 12,568
  • 8
  • 34
  • 67
Murat Kılınç
  • 175
  • 3
  • 16
  • *in the "menuask" gives an error*. What is the error and what line of your code does the message point out? – lurker Dec 21 '19 at 13:10
  • gives 2 errors including "**Syntax error: Operator expected**" and, "**Syntax error: Illegal start of term**". I mentioned above the part that gives error – Murat Kılınç Dec 21 '19 at 13:18
  • 1
    Sorry I don't see it in your post anywhere. What was your query and, if it got that far, what did you try to input? – lurker Dec 21 '19 at 14:04
  • I'm not sure where exactly you're stuck regarding modifying the program to accept numbers. When the user types in a number, it will need to end in a period to terminate the Prolog term. You'll then have a variable instantiated with a number. You'll need a list or simple set of facts to correspond the number to a name. – lurker Dec 21 '19 at 14:19

1 Answers1

3

I'm not totally clear on the focus of the question, but perhaps this will help. Here's a brief example of how to get a name corresponding to a number input:

fruit(1, apple).
fruit(2, pear).
fruit(3, orange).

read_fruit(FruitName) :-
    repeat,
    write('Please select a fruit:'), nl,
    write_fruit_list,
    read(FruitNumber),
    (   fruit(FruitNumber, FruitName)
    ->  write('You selected: '), write(FruitName), nl, !
    ;   write('Not a valid choice, try again...'), nl, fail
    ).

write_fruit_list :-
    fruit(N, Name),
    write(N), write('. '), write(Name), nl,
    fail.
write_fruit_list.

Here's what it looks like when you use it:

2 ?- read_fruit(F).
Please select a fruit:
1. apple
2. pear
3. orange
|: 4.
Not a valid choice, try again...
Please select a fruit:
1. apple
2. pear
3. orange
|: 3.
You selected: orange
F = orange.

3 ?-

You can remove the cut if you want it to continuously ask for fruit inputs.

lurker
  • 56,987
  • 9
  • 69
  • 103