1

I am trying to find the number of occurrences of X in the List L For eg :-

occurrences(a, [b, a, b, c, a, d, a], N ).
N =3

My code not working .Here is my code.

occ(K,L,N) :-  N1=0,  occ1(K,L,N1,N).

occ1(K,[],N1,N) :- N=N1.
occ1(K,L,N1,N) :-
   L=[X|L1], 
   ( K=X -> N1 is N1+1, occ1(K,L1,N1,N) ; occ1(K,L1,N1,N) ).

Can anybody tell me what's wrong in the code.

false
  • 10,264
  • 13
  • 101
  • 209
Squirtle
  • 151
  • 1
  • 3
  • 11

2 Answers2

2

While the answer given by @Kay is spot-on as far as fixing the bug is concerned, it completely circumvents a much bigger issue: The code of occ1/4 is logically impure.

This may not appear very important to you right now, but using impure code has several negative consequences:

  1. Impure code cannot be read declaratively, only procedurally.
  2. Debugging impure code is often tedious and pain-staking.
  3. Impure predicates are less "relational" than their pure counterparts.
  4. Logical impurity hampers code re-use.
  5. Because it is non-monotone, impure code is prone to lead to logically unsound answers, particularly when working with non-ground terms.

To show that these problems persisted in your code after having been "fixed" as suggested @Kay, let us consider the "corrected" code and some queries. First, here's the corrected code:

occ(K,L,N) :-  N1=0,  occ1(K,L,N1,N).

occ1(_,[],N1,N) :- N=N1.
occ1(K,L,N1,N) :-
   L=[X|L1], 
   ( K=X -> N2 is N1+1, occ1(K,L1,N2,N) ; occ1(K,L1,N1,N) ).

Here's the query you gave in your question:

?- occ(a,[b,a,b,c,a,d,a],N).
N = 3 ;
false.

Okay! What if we write the query differently?

?- A=a,B=b,C=c,D=d, occ(a,[B,A,B,C,A,D,A],N).
A = a, B = b, C = c, D = d, N = 3 ;
false.

Okay! What if we reorder goals? Logical conjunction should be commutative...

?- occ(a,[B,A,B,C,A,D,A],N), A=a,B=b,C=c,D=d.
false.

Fail! It seemed that occ1/4 is fine, but now we get an answer that is logically unsound.

This can be avoided by using logically pure code: Look at the pure and monotone code I gave in my answer to the related question "Prolog - count repititions in list (sic)".

Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166
1

The problem is

N1 is N1+1

Variables cannot be "overwritten" in Prolog. You need to just a new variable, e.g.

N2 is N1+1, occ1(K,L1,N2,N)

To your question "Can we replace a particular list element. If yes, what is the syntax?":

You can only build a new list:

replace(_, _, [], []).
replace(Old, New, [H0|T0], [H1|T1]) :-
    (H0 = Old -> H1 = New; H1 = H0),
    replace(Old, New, T0, T1).
Kijewski
  • 25,517
  • 12
  • 101
  • 143