3

So I'm trying to create a method that determines the number of Ns in a list. I've been experimenting for an hour or so now and can't seem to get something solid. As of now, what I have returns 0. I think it might have something to do with my basecase, but I can't seem to figure it out. Logical programming such as prolog is a new horizon for me so any help would be great.

% base case returns 0 occurrences for empty list
numN(_,[],0).
numN(N,[Y | T], A) :- N == Y, numN(N,T,A2), A is A2+1.
numN(N, [Y | T], A) :- Y \= N, numN(N,T,A).



?- numN(X, [a,X,l,g,X], N).
N = 3.

when it should be 2. When I change the basecase to -1, then it returns the correct value.

false
  • 10,264
  • 13
  • 101
  • 209
Jake Senior
  • 223
  • 4
  • 11
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/77340/discussion-on-question-by-jake-senior-find-the-number-of-ns-in-a-list). – Taryn May 08 '15 at 17:46
  • In your last clause you want `\==` not `\=`. – migfilg May 08 '15 at 17:46
  • 1
    Why isn't there a pure, correct solution? – false May 08 '15 at 18:06
  • @false: **repeat** and I where discussing that. In my opinion a more sophisticate answer is not adequate for a beginner as it may confuse him. – migfilg May 08 '15 at 18:10
  • @migfilg: Then, the very question is not right for beginners. – false May 08 '15 at 18:12
  • @migfilg: Certainly I do not agree that it is too hard for beginners. – false May 08 '15 at 19:05

2 Answers2

1

Here is one solution using accumulator:

%returns number of elements E in list L
numN(E,L,N) :- numN2(E,L,0,N).

numN2(E,[],Ak,Ak).
numN2(E,[E|Xs],Ak,N) :- !, Ak1 is Ak+1, numN2(E,Xs,Ak1,N).
numN2(E,[X|Xs],Ak,N) :- numN2(E,Xs,Ak,N).

Edited solution, thanks @migfilg :)

robmnr
  • 41
  • 4
  • 1
    It is bad practice to use a cut in a top-level predicate to avoid wrong solutions of an ancillary predicate: you should correct `numN2/3` and get rid of the cut in `numN/3`. – migfilg May 08 '15 at 17:44
  • Thank you @migfilg, updated solution. – robmnr May 08 '15 at 17:49
  • 1
    Just a small detail: as the cut is wanted because of the unification in the clause head, the cut should appear after the `:-` to make that clear. – migfilg May 08 '15 at 18:05
0

Your last two clauses use N as a free variable, so the 2nd clause always succeeds because N unifies with any term at the list head, and the solution of your program as it stands now will be the length of the list irrespective of its contents. In the last clause you probably have typo as @repeat commented above: is it numX/2 you want to call?

What you need is to have a new argument in your predicate representing the term that you need to count.

migfilg
  • 542
  • 2
  • 9
  • just edited my code doing what you're saying. But for some reason it gives me 1 extra count. Could you please point me in the right direction to what might be doing it. – Jake Senior May 08 '15 at 17:30