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
- References:
- Pattern problem: How to count from a long list of numbers all occurrences of 2 numbers next to each others?
- From: "Nasser Abbasi" <nma@12000.org>
- Pattern problem: How to count from a long list of numbers all occurrences of 2 numbers next to each others?