Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to detect sequences of x times same object in an Array in Smalltalk?

What's the idiomatic way to detect sequences of x times the same object (or an object with a specific matching parameter) in an OrderedCollection or Array?

E.g. does the Array contain 10 times the number 5 in a row?

like image 318
MartinW Avatar asked Dec 25 '22 00:12

MartinW


1 Answers

I like Uko's answer and would like to provide a different solution which addresses the "matching parameter" part of your question. In SequenceableCollectiondefine:

contains: m consecutiveElementsSatisfying: block
    | n i |
    self isEmpty ifTrue: [^m = 0].
    n := self size - m + 1.
    i := 1.
    [i <= n] whileTrue: [| j |
        (block value: (self at: i)) ifTrue: [
            j := 2.
            [j <= m and: [block value: (self at: i + j - 1)]]
                whileTrue: [j := j + 1].
            j > m ifTrue: [^true]].
        i := i + 1].
    ^false

Now, for example the two following expressions would evaluate to true

#(2 1 1 1 2) contains: 3 consecutiveElementsSatisfying: [:e | e = 1]
#(2 1 0 1 2) contains: 3 consecutiveElementsSatisfying: [:e | e squared = e]

Note: If you want the startingAt: n version of this method just initialize i := n instead of i := 1 just before the main loop.

EDIT:

And, of course, we can complete the protocol with the following method in SequenceableCollection:

contains: m consecutiveTimes: anObject
    ^self contains: m consecutiveElementsSatisfying: [:e | e = anObject]

And the example:

#(2 1 1 1 2) contains: 3 consecutiveTimes: 1
like image 198
Leandro Caniglia Avatar answered Dec 28 '22 10:12

Leandro Caniglia