Noob question - pattern matching

I have a list of 22000 8 digit numbers. Im looking for a number which is
the “best” from a defined set of patterns.

a pattern could be “abababab” givng a score of 10, and another would be
“abab” giving a score of 5. Patterns could also be specific digits, so
another pattern defining “a0b0” - giving 7 points would mean that it
would only match if there is zeroes in the number such as 10203040 (with
all the above rules it would give 21 points).

This way the number 52525252 would give a score of 25 and the number
52526262 would give the score of 10.

do anybody have a good idea on how to make such a scoring in ruby?

I’m sorry - but im a bit of a noob regarding ruby, but thought it would
be a good project to get a better virew on the language:-)
Regards

JB

On Fri, Aug 12, 2011 at 12:31 PM, Jesper B. [email protected] wrote:

52526262 would give the score of 10.

do anybody have a good idea on how to make such a scoring in ruby?

I’m sorry - but im a bit of a noob regarding ruby, but thought it would
be a good project to get a better virew on the language:-)
Regards

JB

#!/usr/bin/env ruby

PATTERNS = {
/(\d)(\d)\1\2\1\2\1\2/ => 10, # abababab (aaaaaaaa too though)
/(\d)(\d)\1\2/ => 5, # abab (aaaa too though)
/\d0\d0/ => 7 # a0b0 (a0a0 too though)
}

NUMBERS = %w{
12345678
00000000
12121212
01020102
23240102
}

def score(number)
PATTERNS.reduce(0) do |score, entry|
entry.first =~ number ? score + entry.last : score
end
end

puts NUMBERS.map { |n| “#{n} => #{score(n)}” }.join(“\n”)


There are several things you didn’t specify fully (such as whether the
shorter 4-digit patterns can match anywhere in a number or whether they
should be anchored to the beginning/end of the number, etc.) but you
could
easily adjust the patterns and/or logic to suit. Additionally, if a
pattern
was too complex to be specified using a regular expression, you could
let
the PATTERNS hash have Regexp or lambda instances and update the
#score
method to detect which each pattern entry is and do the right thing.

On Aug 12, 2011, at 12:31 PM, Jesper B. [email protected] wrote:
I have a list of 22000 8 digit numbers. Im looking for a number which is
the “best” from a defined set of patterns.

a pattern could be “abababab” givng a score of 10, and another would be
“abab” giving a score of 5. Patterns could also be specific digits, so
another pattern defining “a0b0” - giving 7 points would mean that it
would only match if there is zeroes in the number such as 10203040 (with
all the above rules it would give 21 points).

This way the number 52525252 would give a score of 25 and the number
52526262 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 matching rules are
more exactly.

module Scorer
@scorers = []
def self.add(&block)
@scorers << block
end
def self.score(str)
total = 0
(0…str.length).each do |offset|
s = str[offset…-1]
@scorers.each do |block|
total += block[s].to_i
end
end
total
end
end

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

numbers = DATA.readlines.map(&:chomp)
p numbers.map{ |s| [s,Scorer.score(s)] }
#=> [[“52525252”, 35], [“52526262”, 25], [“10203040”, 21]]

p numbers.max_by{ |s| Scorer.score(s) }
#=> “52525252”

END
52525252
52526262
10203040

On Aug 12, 2011, at 01:19 PM, Gavin K. [email protected] wrote:

On Aug 12, 2011, at 12:31 PM, Jesper B. [email protected] wrote:
I have a list of 22000 8 digit numbers. Im looking for a number which is
the “best” from a defined set of patterns.

a pattern could be “abababab” givng a score of 10, and another would be
“abab” giving a score of 5. Patterns could also be specific digits, so
another pattern defining “a0b0” - giving 7 points would mean that it
would only match if there is zeroes in the number such as 10203040 (with
all the above rules it would give 21 points).

This way the number 52525252 would give a score of 25 and the number
52526262 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 matching rules are
more exactly.

…however, the code I posted gave an incorrect score for 52526262,
since my regexps 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. (Actual code is preceded by the output.)

#=> Scoring “52525252”
#=> …“52525252” scored 10 using abababab
#=> …“52525252” scored 5 using abab
#=> …“2525252” scored 5 using abab
#=> …“525252” scored 5 using abab
#=> …“25252” scored 5 using abab
#=> …“5252” scored 5 using abab
#=> …final score: 35
#=> Scoring “52526262”
#=> …“52526262” scored 5 using abab
#=> …“26262” scored 5 using abab
#=> …“6262” scored 5 using abab
#=> …final score: 15
#=> Scoring “10203040”
#=> …“10203040” scored 7 using a0b0
#=> …“203040” scored 7 using a0b0
#=> …“3040” scored 7 using a0b0
#=> …final score: 21
#=> “52525252”

def run
$DEBUG = true
numbers = DATA.readlines.map(&:chomp)
p numbers.max_by{ |s| Scorer.score(s) }
#=> “52525252”
end

module Scorer
@scorers = {}
def self.add(name,&block)
@scorers[name] = block
end
def self.score(str)
puts “Scoring #{str.inspect}” if $DEBUG
total = 0
(0…str.length).each do |offset|
s = str[offset…-1]
@scorers.each do |name,block|
score = block[s].to_i
if $DEBUG && score!=0
puts “…#{s.inspect} scored #{score} using #{name}”
end
total += score
end
end
puts “…final score: #{total}”
total
end
end
Scorer.add(‘abababab’){ |s| 10 if s =~ /^(.)(.)\1\2\1\2\1\2/ &&
s[0]!=s[1] }
Scorer.add(‘abab’ ){ |s| 5 if s =~ /^(.)(.)\1\2/ && s[0]!=s[1] }
Scorer.add(‘a0b0’ ){ |s| 7 if s =~ /^(.)0(.)0/ && s[0]!=s[2] }

run if FILE==$0

END
52525252
52526262
10203040