list


Prolog - Count the Number of Repetitions in a List


I'm writing a program in Prolog that counts the number of uninterrupted occurrences of the first value in a list.
So given, repetitions(A,[a,a,a,a,a,b,c,a]), the program would return A = 5.
This is what my code looks like so far:
repetitions(A,[]).
repetitions(A,[A|T]):- repetitions(A, [_|T]), A is 1+A.
repetitions(A,[_|T]):- repetitions(A,[A|T]).
Here is a relational version:
repetitions(N, [First|Rest]) :-
phrase(repetitions_(First, 1, N), Rest).
repetitions_(_, N, N) --> [].
repetitions_(First, N0, N) --> [First],
{ N1 #= N0 + 1 },
repetitions_(First, N1, N).
repetitions_(First, N, N) --> [Other], { dif(First, Other) }, ... .
... --> [] | [_], ... .
The test case works as required:
?- repetitions(N, [a,a,a,a,a,b,c,a]).
N = 5 ;
false.
And moreover, we can also use this in other directions.
For example, what about a list with 3 element in general:
?- Ls = [A,B,C], repetitions(N, Ls).
Ls = [C, C, C],
A = B, B = C,
N = 3 ;
Ls = [B, B, C],
A = B,
N = 2,
dif(B, C) ;
Ls = [A, B, C],
N = 1,
dif(A, B) ;
false.
And what about all possible answers, fairly enumerated by iterative deepening:
?- length(Ls, _), repetitions(N, Ls).
Ls = [_8248],
N = 1 ;
Ls = [_8248, _8248],
N = 2 ;
Ls = [_8734, _8740],
N = 1,
dif(_8734, _8740) ;
Ls = [_8248, _8248, _8248],
N = 3 ;
Ls = [_8740, _8740, _8752],
N = 2,
dif(_8740, _8752) ;
etc.
It is a major attraction of logic programs that they can often be used in several directions.
See dcg, prolog-dif and clpfd for more information about the mechanisms I used to achieve this generality.
We can also use this to answer the following question
What does a list look like such that there are 3 repetitions of its first element?
Example:
?- repetitions(3, Ls).
Ls = [_2040, _2040, _2040] ;
Ls = [_2514, _2514, _2514, _2532],
dif(_2514, _2532) ;
Ls = [_2526, _2526, _2526, _2544, _2550],
dif(_2526, _2544) ;
Ls = [_2538, _2538, _2538, _2556, _2562, _2568],
dif(_2538, _2556) .
This requires only that a single further constraint be added to the solution above. I leave this as an easy exercise.
Here is a DCG-based solution somewhat a variation to #mat's:
repetitions_II(N, [X|Cs]) :-
phrase( ( reps(X, N), no(X) ), [X|Cs]).
no(X) -->
( [] | [Y], {dif(X,Y)}, ... ).
reps(_X, 0) -->
[].
reps(X, N0) -->
[X],
{ N0 #> 0, N1 #= N0-1 },
reps(X, N1).
Two notable differences:
1mo) There is no use of a difference for maintaining the counter. Thus, constraints on the number can help to improve termination. A perfect clpfd-implementation would (or rather should) implement this with similar efficiency to a difference.
2do) The end no//1 essentially encodes in a pure manner \+[X].
The downside of this solution is that it still produces leftover choicepoints. To get rid of these, some more manual coding is necessary:
:- use_module(library(reif)).
repetitions_III(N, [X|Xs]) :-
reps([X|Xs], X, N).
reps([], _, 0).
reps([X|Xs], C, N0) :-
N0 #>= 0,
if_(X = C, ( N1 #= N0-1, reps(Xs, C, N1) ), N0 = 0 ).
a compact definition, courtesy libraries apply and yall
?- [user].
repetitions(A,[H|T]) :- foldl([E,(C0,H0),(C1,H1)]>>(E==H0 -> succ(C0,C1), H1=H0 ; C0=C1, H1=_), T, (1,H), (A,_)).
|: true.
?- repetitions(A,[a,a,a,a,a,b,c,a]).
A = 5.
Another approach close to what you've done so far, using CLPFD:
:- use_module(library(clpfd)).
repetitions(N,[H|T]):-repetitions(N,[H|T],H).
repetitions(0,[],_).
repetitions(0,[H|_],H1):-dif(H,H1).
repetitions(N,[H|T],H):-repetitions(N1 ,T, H), N #= N1+1.
Examples:
?- repetitions(A,[a,a,a,a,a,b,c,a]).
A = 5 ;
false.
?- repetitions(2,[a,Y]).
Y = a.
?- repetitions(N,[a,a|_]).
N = 2 ;
N = 2 ;
N = 3 ;
N = 3 ;
N = 4 ;
N = 4 ;
N = 5 ;
N = 5 ;
N = 6 ;
N = 6 ....and goes on

Related Links

How to use lists
Filter list of lists in Scheme
Counting names in Coldfusion
How do I get a sequence of cards in haskell [closed]
Longest sequence in prolog
Flattening a list in scheme
Deleting one list from another
Confused about workings of a Haskell list comprehension
How to preserve a list in a loop after calling remove() method
How to iterate a list of Pair with Scala?
Reference Equality Python
writing context free grammar in prolog
rearrange list elements in lisp
Car and Cdr in Scheme
Haskell recursion in lists
list of keyvalue pair into dictionary

Categories

HOME
elasticsearch
apple-push-notifications
enums
tcp
tfs2015
flurry
share
azure-logic-apps
hspi
stack-overflow
cqrs
amazon-elb
sql-injection
texas-instruments
async-await
c#-7.0
hidden
android-permissions
fluent-migrator
pyopencl
pdf.js
mod-wsgi
dragula
fusetools
tortoisehg
acrobat
docx4j
jsonresult
guice
snap-framework
sca
android-canvas
java-stream
grails-2.5
djcelery
strapi
elastica
mars-simulator
llvm-ir
game-center
klee
ipp-protocol
ssi
android-5.0-lollipop
ilrepack
android-mediarecorder
case-when
kendo-editor
polymaps
zend-server
emf-compare
fitbit
email-injection
yargs
cocoa-bindings
haraka
spring-mongo
unsigned
odesk
cryptojs
directx-9
sqlbase
ngcordova
erlog
prism-4
nsmutabledata
inputbox
storing-data
relationships
refit
preorder
oxygene
flipboard
iosched
eager-loading
web-frameworks
oscilloscope
tridion-2011
daap
spark-view-engine
workflow-manager-1.x
border-box
firebird1.5
netstream
servercontrol
cewolf
tablet-pc
jquery-1.4
resharper-5.1
outlook-2007-addin
reliability
principles
self-tracking-entities

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App