Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Pattern problem: How to count from a long list of numbers

  • To: mathgroup at smc.vnet.net
  • Subject: [mg87476] Re: [mg87427] Re: [mg87393] Pattern problem: How to count from a long list of numbers
  • From: DrMajorBob <drmajorbob at att.net>
  • Date: Fri, 11 Apr 2008 01:46:09 -0400 (EDT)
  • References: <200804090956.FAA25006@smc.vnet.net> <2514503.1207820602171.JavaMail.root@m08>
  • Reply-to: drmajorbob at longhorns.com

For those of you, like me, who need a little help understanding Carl's  
always brilliant code, here's a cheat-sheet of sorts.

First, the original:

pairCount[data_, p1_, p2_] :=
  Total@BitAnd[
    Clip[Clip[Most@data, {p1, p1}, {p1 - 2, p1 - 2}], {p1 - 1,
      p1 - 1}, {0, 1}],
    Clip[Clip[Rest@data, {p2, p2}, {p2 - 2, p2 - 2}], {p2 - 1,
      p2 - 1}, {0, 1}]]

Next, a parsing of that. straddle[data,p] changes everything that's NOT p  
to p-2, binaryMark changes that to 0s and 1s, and pairCount2 uses Total 
and BitAnd to compare binaryMark for Most@data to binaryMark for Rest@data.

straddle[data_, p_] := Clip[data, {p, p}, {p - 2, p - 2}]
binaryMark2[data_, p_] :=
  Clip[straddle[data, p], {p - 1, p - 1}, {0, 1}]
pairCount2[data_, p1_, p2_] :=
  Total@BitAnd[binaryMark2[Most@data, p1], binaryMark2[Rest@data, p2]]

That's exactly the same as Carl's solution, except for the  
compartmentalization of code.

Third, here's my initial solution to the same problem, with a simpler  
binaryMark:

binaryMark3[data_, p_] := 1 - Unitize@Sign[data - p]
pairCount3[data_, p1_, p2_] :=
  Total@BitAnd[binaryMark3[Most@data, p1], binaryMark3[Rest@data, p2]]

A one-liner version of that:

pairCount4[data_, p1_, p2_] :=
  Total@BitAnd[1 - Unitize@Sign[Most@data - p1],
    1 - Unitize@Sign[Rest@data - p2]]

And a faster one-liner:

pairCount5[data_, p1_, p2_] :=
  Length@data - 1 -
   Total@BitOr[Unitize@Sign[Most@data - p1],
     Unitize@Sign[Rest@data - p2]]

Finally, some timings:

sample[n_] := RandomInteger[{1, 5}, n]
times[n_, p1_, p2_] :=
  With[{data = sample@n}, {Timing@pairCount[data, p1, p2],
    Timing@pairCount2[data, p1, p2], Timing@pairCount3[data, p1, p2],
    Timing@pairCount4[data, p1, p2], Timing@pairCount5[data, p1, p2]}]

times[10^7, 2, 3]

{{0.680051, 399704}, {0.683036, 399704}, {1.2015, 399704}, {1.19743,
   399704}, {0.684635, 399704}}

times[10^7, 2, 1]

{{0.652513, 398875}, {0.65154, 398875}, {1.19801, 398875}, {1.20221,
   398875}, {0.687839, 398875}}

My final version is almost as fast as Carl's original, and for me, that's  
a VERY good day.

Bobby

On Thu, 10 Apr 2008 01:13:42 -0500, Carl Woll <carlw at wolfram.com> wrote:

> Nasser Abbasi wrote:
>
>> Hello;
>>
>> I think using Pattern is my weakest point in Mathematica.
>>
>> I have this list, say this: (it is all a list of integers, no real  
>> numbers).
>>
>> x = {1, 3, 3, 3, 2, 3, 3, 1, 3, 3}
>>
>> And I want to count how many say a 3 followed immediately by 3. So in 
>> the
>> above list, there will be 4 such occurrences. And if I want to count how
>> many 1 followed by a 3, there will be 2 such cases, etc...
>>
>> I tried Count[] but I do not know how to set the pattern for "3  
>> followed by
>> a comma followed by 3" or just "3 followed immediately by 3".
>>
>> I tried few things, such as the following
>>
>> In[68]:= Count[x, {3, 3}_]
>> Out[68]= 0
>>
>> Also tried Cases, but again, I am not to good with Patterns, so not  
>> sure how
>> to set this up at this moment.
>>
>> Any ideas will be appreciated.
>>
>> Nasser
>> I really need to sit down and study Patterns in Mathematica really well  
>> one
>> day :)
>>
>>
>>
> If you have long lists and would like this to be very quick, I would do
> this by basically finding out the locations of the first and second
> elements, and seeing where the two line up. Here is a function that will
> do this:
>
> pairCount[data_, p1_, p2_] :=  Total @ BitAnd[
>     Clip[Clip[Most[data], {p1, p1}, {p1 - 2, p1 - 2}], {p1 - 1, p1 - 1},
> {0, 1}],
>     Clip[Clip[Rest[data], {p2, p2}, {p2 - 2, p2 - 2}], {p2 - 1, p2 - 1},
> {0, 1}]
> ]
>
> A couple examples:
>
> In[146]:= pairCount[{1, 3, 3, 3, 2, 3, 3, 1, 3, 3}, 3, 3]
>
> Out[146]= 4
>
> In[147]:= pairCount[{1, 3, 3, 3, 2, 3, 3, 1, 3, 3}, 1, 3]
>
> Out[147]= 2
>
> Carl Woll
> Wolfram Research
>
>



-- =

DrMajorBob at longhorns.com


  • Prev by Date: Re: Dynamic
  • Next by Date: Re: Product
  • Previous by thread: Re: Pattern problem: How to count from a long list of numbers
  • Next by thread: Re: Pattern problem: How to count from a long list of numbers all occurrences of 2 numbers next to each others?