1

I'm new to Prolog and I have a problem that queries for calculator([three,times,two],Total). and yield the answer Total=6.

Following up on my previous question: I am using a predicate translate to have Prolog understand that [1,2,3,4,etc.] is [one,two,three,four,etc.].

translate([],[]).    
translate([H|T],[H2|T2]):-means(H,H2),translate(T,T2).
means(0,zero).
means(1,one).
means(2,two).
means(3,three).
means(4,four).
means(5,five).
means(6,six).
means(9,nine).
means(10,ten).

I entered the query

?-translate([1,2,3,4],X).

X=[one,two,three,four].

Prolog translated the English numerical values to numbers. I just need help incorporating this translation to my arithmetic code.

calc([N1,times,N2],Total):-Total is N1*N2.

Any kind of advice would be appreciated. Thank You.

David Yoon
  • 25
  • 5

2 Answers2

2

I'm not sure if I can help without just giving the answer, but my first stab at it would be to use DCGs. They're a very convenient way to parse anything, lists of atoms included. For instance:

word_number(1) --> [one].
word_number(2) --> [two].

You can use this with phrase/2:

?- phrase(word_number(N), [one]).
N = 1 ;

What's going on here is Prolog is looking for DCG rules or lists that match in the input sequence. These DCG expressions are just syntactic sugar on top of difference lists, but they enable a very declarative grammatical reading. To expand on that:

expression(Value) --> 
  word_number(Left), 
  [times], 
  word_number(Right),
  { Value is Left * Right }.

The other part of the syntactic sugar besides the --> notation itself is that you can embed arbitrary Prolog in braces. We're using other DCG predicates essentially as other tokens in the input, so word_number(Left) is going to bind Left to the integer value of the word, and then Value is just the product of the left word number and the right.

?- phrase(expression(Value), [two,times,two]).
Value = 4.

Hopefully this will be enough to get you started.

Edit

It turns out you don't need to incorporate translate/2 into your calc/2 predicate, means/2 will do the job just fine:

calc([W1, times, W2], Total) :- 
  means(W1, N1), means(W2, N2),
  Total is N1*N2.
Community
  • 1
  • 1
Daniel Lyons
  • 22,421
  • 2
  • 50
  • 77
  • Hello, this did send me on the right direction, but since I am a bad programmer I am still struggling to get my code to work. I have tried your example on Prolog and got it to work however I am trying to use the predicate translate but I cannot seem to define it to make Prolog understand [1,2,3,4] = [one,two,three,four]. Here is my code would you be kind enough to help me figure out my problem? Thank you. – David Yoon Feb 08 '13 at 02:00
  • translate([],[]). translate(...,...):-means(...),translate(...) – David Yoon Feb 08 '13 at 02:00
  • means(zero,0). means(one,1). means(two,2). means(three,3). means(four,4). means(five,5). means(six,6). means(nine,9). means(ten,10). – David Yoon Feb 08 '13 at 02:01
  • calc([N1,times,N2],Total):-Total is N1*N2. – David Yoon Feb 08 '13 at 02:02
  • It would be better in these circumstances to edit your question with your new code and then comment, because the comment restrictions are pretty onerous. I'll take a look later tonight but I'm going to need the body of translate as well, so it would be very helpful if you'd edit the question. – Daniel Lyons Feb 08 '13 at 02:06
  • OK I will give the body of translate and post it as a new question. Thank you so much for your help I really appreciate it. – David Yoon Feb 08 '13 at 02:09
  • I've edited the answer, please take a look and let me know if it answers your question. – Daniel Lyons Feb 08 '13 at 03:19
  • Yes it did! Thank you so much!!! I didn't realize how simple that was and that I ended up writing a code I didn't need. I really appreciate your help! I hope I can become as good a programmer as you someday haha. – David Yoon Feb 08 '13 at 04:15
  • Drop me a line, my email's in my profile. I'd like to know more about why you're studying Prolog, and maybe I can give you more open-ended help. – Daniel Lyons Feb 08 '13 at 04:30
  • Hey, I checked your profile and website but I couldn't find your email. Could you leave me it here? – David Yoon Feb 10 '13 at 03:51
  • Sure, fusion at storytotell dot org. – Daniel Lyons Feb 10 '13 at 05:17
1

a compact way to assign a number to a symbol could be nth0/3, and combining it with the 'if' (see (->)/2) the accepted input can span symbols and numbers.

valof(V, U) :-
 nth0(U, [zero, one, two], V) -> true ; U = V.

with that, a simple way to apply to a list could be

calc([A, Op, B|Cs], R) :-
    valof(A, Va),
    valof(B, Vb),
    arith(Va, Op, Vb, T),
    calc([T|Cs], R).

edit I forgot the recursion' base:

calc([A], R) :-
    valof(A, R).

arith(A, plus, B, R) :- R is A+B.
arith(A, mult, B, R) :- R is A*B.

note that we pop three elements and replace with the evaluated value (hence valof must accept numbers).

I introduced on purpose plus, an operator with different precedence than mult. You should see that the above solution is not correct, because it doesn't handle such important property of arithmetical expressions syntax. See if you can correct it, merging this answer with what Daniel provided (+1), and this other answer I gave on a similar problem.

Community
  • 1
  • 1
CapelliC
  • 59,646
  • 5
  • 47
  • 90