From: Gavin Kistner Date: 2011-08-13T04:28:53+09:00 Subject: Re: noob question - pattern matching --Boundary_(ID_3xH6w/y3P6qTQg5nlpI7ZQ) Content-type: text/plain; charset=ISO-8859-1; format=flowed Content-transfer-encoding: quoted-printable On Aug 12, 2011, at 01:19 PM, Gavin Kistner wrote:=0A=0AOn= 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 "be= st" from a defined set of patterns.=0A=0Aa pattern could be "abababab" giv= ng a score of 10, and another would be=0A"abab" giving a score of 5. Patte= rns could also be specific digits, so=0Aanother pattern defining "a0b0" - = giving 7 points would mean that it=0Awould only match if there is zeroes i= n 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 t= he number=0A52526262 would give the score of 10.=0A=A0=0ACode 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 i= t gets 10 from abababab and 25 from five matches of "abab" - three occurre= nces of 5252 and two occurrences of 2525. If this is not correct, then you= 'll have to explain what the matching rules are more exactly.=0A=0A...howe= ver, the code I posted gave an incorrect score for 52526262, since my rege= xps were not anchored. Here's an updated version of the code with a debug = mode that fixes the problem and shows you when the matches are found. (Act= ual code is preceded by the output.)=0A=0A#=3D> Scoring "52525252"=0A#=3D>= ..."52525252" scored 10 using abababab=0A#=3D> ..."52525252" scored 5 usi= ng abab=0A#=3D> ..."2525252" scored 5 using abab=0A#=3D> ..."525252" score= d 5 using abab=0A#=3D> ..."25252" scored 5 using abab=0A#=3D> ..."5252" sc= ored 5 using abab=0A#=3D> ...final score: 35=0A#=3D> Scoring "52526262"=0A= #=3D> ..."52526262" scored 5 using abab=0A#=3D> ..."26262" scored 5 using = abab=0A#=3D> ..."6262" scored 5 using abab=0A#=3D> ...final score: 15=0A#=3D= > Scoring "10203040"=0A#=3D> ..."10203040" scored 7 using a0b0=0A#=3D> ...= "203040" scored 7 using a0b0=0A#=3D> ..."3040" scored 7 using a0b0=0A#=3D>= ...final score: 21=0A#=3D> "52525252"=0A=0Adef run=0A=A0 $DEBUG =3D true=0A= =A0 numbers =3D DATA.readlines.map(&:chomp)=0A=A0 p numbers.max_by{ |s| Sc= orer.score(s) }=0A=A0 #=3D> "52525252"=0Aend=0A=0Amodule Scorer=0A=A0 @sco= rers =3D {}=0A=A0 def self.add(name,&block)=0A=A0 =A0 @scorers[name] =3D b= lock=0A=A0 end=0A=A0 def self.score(str)=0A=A0 =A0 puts "Scoring #{str.ins= pect}" if $DEBUG=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 d= o |name,block|=0A=A0 =A0 =A0 =A0 score =3D block[s].to_i=0A=A0 =A0 =A0 =A0= if $DEBUG && score!=3D0=0A=A0 =A0 =A0 =A0 =A0 puts "...#{s.inspect} score= d #{score} using #{name}"=A0=0A=A0 =A0 =A0 =A0 end=0A=A0 =A0 =A0 =A0 total= +=3D score=0A=A0 =A0 =A0 end=0A=A0 =A0 end=0A=A0 =A0 puts "...final score= : #{total}"=0A=A0 =A0 total=0A=A0 end=0Aend=0AScorer.add('abababab'){ |s| = 10 if s =3D~ /^(.)(.)\1\2\1\2\1\2/ && s[0]!=3Ds[1] }=0AScorer.add('abab' =A0= =A0){ |s| 5 =A0if s =3D~ /^(.)(.)\1\2/ =A0 =A0 =A0 =A0 && s[0]!=3Ds[1] }=0A= Scorer.add('a0b0' =A0 =A0){ |s| 7 =A0if s =3D~ /^(.)0(.)0/ =A0 =A0 =A0 =A0= =A0 && s[0]!=3Ds[2] }=0A=0Arun if __FILE__=3D=3D$0=0A=0A__END__=0A5252525= 2=0A52526262=0A10203040= --Boundary_(ID_3xH6w/y3P6qTQg5nlpI7ZQ) Content-type: multipart/related; boundary="Boundary_(ID_I8Rqdd5qdBBMw93LUDmIVQ)"; type="text/html" --Boundary_(ID_I8Rqdd5qdBBMw93LUDmIVQ) Content-type: text/html; CHARSET=US-ASCII Content-transfer-encoding: quoted-printable
On Aug 12, 2011, at 01:19 PM, Gavin Kistner <phrogz@me.com> wro= te:

On Aug 12, 2011, at 12:31 PM, Jesper Brandt <jb@jepcom.dk>= ; wrote:
I 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" givng a score of 10, and another woul= d be
=0A"abab" giving a score of 5. Patterns could also be specific dig= its, so
=0Aanother pattern defining "a0b0" - giving 7 points would mean= that it
=0Awould only match if there is zeroes in the number such as 1= 0203040 (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<= br>=0A52526262 would give the score of 10.
&= nbsp;
Code follows; it lets you perform arbitrary s= coring tests, and then sums those up over all sub-sections of a string. No= te 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 occurre= nces of 2525. If this is not correct, then you'll have to explain what the= matching rules are more exactly.

...however, the code I posted gave an incorrect s= core for 52526262, since my regexps were not anchored. Here's an updated v= ersion of the code with a debug mode that fixes the problem and shows you = when the matches are found. (Actual code is preceded by the output.)

#=3D> Scoring "52525= 252"
#=3D> ..."52525252" scored 10 using abababab
#= =3D> ..."52525252" scored 5 using abab
#=3D> ..."2525252" = scored 5 using abab
#=3D> ..."525252" scored 5 using abab
#=3D> ..."25252" scored 5 using abab
#=3D> ..."5252= " scored 5 using abab
#=3D> ...final score: 35
#=3D= > Scoring "52526262"
#=3D> ..."52526262" scored 5 using ab= ab
#=3D> ..."26262" scored 5 using abab
#=3D> ..= "6262" scored 5 using abab
#=3D> ...final score: 15
#=3D> Scoring "10203040"
#=3D> ..."10203040" scored 7 us= ing a0b0
#=3D> ..."203040" scored 7 using a0b0
#=3D= > ..."3040" scored 7 using a0b0
#=3D> ...final score: 21
#=3D> "52525252"

def run
  $DEBUG =3D true
  numbers =3D D= ATA.readlines.map(&:chomp)
  p numbers.max_by{ |s| Scor= er.score(s) }
  #=3D> "52525252"
end

module Scorer
  @scorers =3D {}
&= nbsp; def self.add(name,&block)
    @scorers[name]= =3D block
  end
  def self.score(str)
=
    puts "Scoring #{str.inspect}" if $DEBUG
 = ;   total =3D 0
    (0...str.length).each do |off= set|
      s =3D str[offset..-1]
 =     @scorers.each do |name,block|
     = ;   score =3D block[s].to_i
        if = $DEBUG && score!=3D0
          = puts "...#{s.inspect} scored #{score} using #{name}" 
 = ;       end
        total +=3D= score
      end
    end
    puts "...final score: #{total}"
   = ; total
  end
end
Scorer.add('abababab'= ){ |s| 10 if s =3D~ /^(.)(.)\1\2\1\2\1\2/ && s[0]!=3Ds[1] }
<= div>Scorer.add('abab'    ){ |s| 5  if s =3D~ /^(.)(.)\1\2/ =         && s[0]!=3Ds[1] }
Scorer.add= ('a0b0'    ){ |s| 7  if s =3D~ /^(.)0(.)0/     &n= bsp;     && s[0]!=3Ds[2] }

run = if __FILE__=3D=3D$0

__END__
52525252
52526262
10203040
= --Boundary_(ID_I8Rqdd5qdBBMw93LUDmIVQ)-- --Boundary_(ID_3xH6w/y3P6qTQg5nlpI7ZQ)--