From: Gavin Kistner Date: 2011-08-13T04:18:25+09:00 Subject: Re: noob question - pattern matching --Boundary_(ID_Hjy/GPwcmrcg73GJcGyHzA) Content-type: text/plain; charset=ISO-8859-1; format=flowed Content-transfer-encoding: quoted-printable On Aug 12, 2011, at 12:31 PM, Jesper Brandt wrote:=0AI have= a list of 22000 8 digit numbers. Im looking for a number which is=0Athe "= best" from a defined set of patterns.=0A=0Aa pattern could be "abababab" g= ivng a score of 10, and another would be=0A"abab" giving a score of 5. Pat= terns could also be specific digits, so=0Aanother pattern defining "a0b0" = - giving 7 points would mean that it=0Awould only match if there is zeroes= in the number such as 10203040 (with=0Aall the above rules it would give = 21 points).=0A=0AThis way the number 52525252 would give a score of 25 and= the number=0A52526262 would give the score of 10.=0A=A0=0ACode follows; i= t lets you perform arbitrary scoring tests, and then sums those up over al= l sub-sections of a string. Note that 52525252 scores 35 (not 25), because= it gets 10 from abababab and 25 from five matches of "abab" - three occur= rences of 5252 and two occurrences of 2525. If this is not correct, then y= ou'll have to explain what the matching rules are more exactly.=0A=0Amodul= e Scorer=0A=A0 @scorers =3D []=0A=A0 def self.add(&block)=0A=A0 =A0 @score= rs << block=0A=A0 end=0A=A0 def self.score(str)=0A=A0 =A0 total =3D 0=0A=A0= =A0 (0...str.length).each do |offset|=0A=A0 =A0 =A0 s =3D str[offset..-1]= =0A=A0 =A0 =A0 @scorers.each do |block|=0A=A0 =A0 =A0 =A0 total +=3D block= [s].to_i=0A=A0 =A0 =A0 end=0A=A0 =A0 end=0A=A0 =A0 total=0A=A0 end=0Aend=0A= =0AScorer.add{ |s| 10 if s =3D~ /(.)(.)\1\2\1\2\1\2/ && s[0]!=3Ds[1] } # a= bababab=0AScorer.add{ |s| 5 =A0if s =3D~ /(.)(.)\1\2/ =A0 =A0 =A0 =A0 && s= [0]!=3Ds[1] } # abab=0AScorer.add{ |s| 7 =A0if s =3D~ /(.)0(.)0/ =A0 =A0 =A0= =A0 =A0 && s[0]!=3Ds[2] } # a0b0=0A=0Anumbers =3D DATA.readlines.map(&:ch= omp)=0Ap numbers.map{ |s| [s,Scorer.score(s)] }=0A#=3D> [["52525252", 35],= ["52526262", 25], ["10203040", 21]]=0A=0Ap numbers.max_by{ |s| Scorer.sco= re(s) }=0A#=3D> "52525252"=0A=0A__END__=0A52525252=0A52526262=0A10203040= --Boundary_(ID_Hjy/GPwcmrcg73GJcGyHzA) Content-type: multipart/related; boundary="Boundary_(ID_BgZ2g6g3fBXBQ2ZkFO4Txw)"; type="text/html" --Boundary_(ID_BgZ2g6g3fBXBQ2ZkFO4Txw) Content-type: text/html; CHARSET=US-ASCII Content-transfer-encoding: quoted-printable
On Aug 12, 2011, at 12:31 PM, Jesper Brandt <jb@jepcom.dk> wrot= e:
I have a list of 22000 8 digit numbers. Im looking for a num= ber which is
=0Athe "best" from a defined set of patterns.
=0A
=0A= a pattern could be "abababab" givng a score of 10, and another would be=0A"abab" giving a score of 5. Patterns could also be specific digits, so=
=0Aanother pattern defining "a0b0" - giving 7 points would mean that i= t
=0Awould only match if there is zeroes in the number such as 10203040= (with
=0Aall the above rules it would give 21 points).
=0A
=0ATh= is way the number 52525252 would give a score of 25 and the number
=0A5= 2526262 would give the score of 10.
 
Code follows; it lets you perform arbitrary scoring = tests, and then sums those up over all sub-sections of a string. Note that= 52525252 scores 35 (not 25), because it gets 10 from abababab and 25 from= five matches of "abab" - three occurrences of 5252 and two occurrences of= 2525. If this is not correct, then you'll have to explain what the matchi= ng rules are more exactly.

module Scorer
  @scorers =3D []
  def sel= f.add(&block)
    @scorers << block
  end
  def self.score(str)
    = total =3D 0
    (0...str.length).each do |offset|
      s =3D str[offset..-1]
    &= nbsp; @scorers.each do |block|
        total= +=3D block[s].to_i
      end
  &n= bsp; end
    total
  end
end<= /div>

Scorer.add{ |s| 10 if s =3D~ /(.)(.)\1\2\1\2\1\2/= && s[0]!=3Ds[1] } # abababab
Scorer.add{ |s| 5  if= s =3D~ /(.)(.)\1\2/         && s[0]!=3Ds[1] }= # abab
Scorer.add{ |s| 7  if s =3D~ /(.)0(.)0/   &nbs= p;       && s[0]!=3Ds[2] } # a0b0

numbers =3D DATA.readlines.map(&:chomp)
p numbers.ma= p{ |s| [s,Scorer.score(s)] }
#=3D> [["52525252", 35], ["52526= 262", 25], ["10203040", 21]]

p numbers.max_by{ |s= | Scorer.score(s) }
#=3D> "52525252"

__END__
52525252
52526262
10203040
= --Boundary_(ID_BgZ2g6g3fBXBQ2ZkFO4Txw)-- --Boundary_(ID_Hjy/GPwcmrcg73GJcGyHzA)--