1

I recently started learning Prolog and got stuck on this question...

How do I change this rule below to give me the value of "A*1 + A*2 + A*3 + ... + A*N"?

sum(1,A,1).
sum(N,A,Res) :-
  N > 1, 
  Nminus1 is N-1,
  sum(Nminus1,A,Res2),
  Res is Res2 + N*A.

The result always appears to be off by one, as shown in the following query:

?- sum(4,2,Res).
Res = 19 ;                 % NO! expected: `Res = 20`
false.

I can't figure it out. Thank You in advance!

repeat
  • 18,496
  • 4
  • 54
  • 166
Prolog
  • 21
  • 3
  • at first glance, should work as is... – CapelliC Dec 27 '14 at 15:23
  • This would only give me the value without the integer "a". How do I change it so that the "a" is also included. – Prolog Dec 27 '14 at 15:29
  • 2
    This isn't as hard as you may think. You'll obviously need to introduce `A` as an argument. The easiest answer is that your result is just `A * sum(n)` where `sum(n)` is your current result. You can use your current `sum` as an auxiliary predicate for that: `suma(N, A, Res) :- sum(N, Res1), Res is A * Res.` You could also just add up multiples of `A` as you did for multiples of `1`: `Res is Res2 + A*N`. But that's more multiplying. There are other similar approaches. – lurker Dec 27 '14 at 15:37
  • @lurker How would I write that down? I am really struggling with prolog at the moment. Sorry – Prolog Dec 27 '14 at 16:46
  • @lurker gave you perfect advice. – false Dec 27 '14 at 17:18
  • @false I understand what lurker is saying but I don't know how to write it down. I keep getting errors like "No permission to modify static procedure `(=)/2'" if I declare A = 'a'. I don't think this the right way to do it but I cant figure out how to. – Prolog Dec 27 '14 at 17:56
  • @Prolog, did you write the code that you are showing in the problem statement, or did you get it from somewhere else? Why not edit the problem and add the code that you've attempted so folks here can help? It sounds to me like you might need to read some Prolog books or tutorials, since you refer to `A = 'a'` as some kind of "declaration", but that's not how Prolog works basically at all. Although, you should be able to *unify* the variable `A` with the atom `a` (or `'a'`, same thing). However, I assume you need to assign a number to `A` to do a computation. – lurker Dec 27 '14 at 21:11
  • 1
    What I described in my other comment is almost everything you need to do. I only left a little bit for you to figure out. What needs to be done isn't deep into what makes Prolog unique. You'd need to create a `sum(N, A, Res)` predicate (to include the `A`) then query it such as, `sum(15, 3, Res)` which will compute `3*1 + 3*2 + ... + 3*15`. – lurker Dec 27 '14 at 21:13
  • @lurker HONESTLY thanks a lot for your help. I looked up some tutorials and got the code (above) but still cant figure out why my answer is always -1. – Prolog Dec 28 '14 at 01:05
  • What you posted is nearly correct. The only issue is the base case, `sum(1, A, 1)`. It says that the sum of one `A` term is `1`, which is not true. What should the sum of one `A` term be? :) By the way, I never got a `-1` answer with your code. You'll need to show an example of that if it's still a problem. – lurker Dec 28 '14 at 01:17
  • @lurker sum of A is 2, finally got the right answers :D, but why is it 2? – Prolog Dec 28 '14 at 01:28
  • The sum of a single `A` term should be `A` (whatever `A` is). For example, `sum(1, 3, R).` should result in `R = 3`, right? – lurker Dec 28 '14 at 01:32
  • @lurker Yes, true indeed I just got it now. Thank You very much for your help. – Prolog Dec 28 '14 at 01:35

1 Answers1

2

Use !

:- use_module(library(clpfd)).

Based on equidistant_stride/2, length/2, and the clpfd library predicate sum/3, we write:

n_a_sum(N,A,Sum) :-
   length(Zs,N),
   Zs = [A|_],
   equidistant_stride(Zs,A),
   sum(Zs,#=,Sum).

Here's the sample query given by the OP:

?- n_a_sum(4,2,Sum).
Sum = 20.              % expected result
Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166