Reputation: 3
I'm trying to build a simple algorithm to detect if a word in an array matches a given string (in this case, g) uniquely--as in, only 1 appearance of the characters in g, AND an unlimited amount of appearances of the vowels--aeiouy.
g = "bs"
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss']
for y in arr
return y if y.include? { |z| /[aeiouy]/ =~ z } and y.include? { |z|/[ #{g} ]/ =~ z }
end
Expected output:
base
bees
# all others either have more than 1 b or s, or contain other consonants.
Getting this error:
include?': wrong number of arguments (0 for 1) (ArgumentError)
I think there could be better ways of doing this, using .find or .any? perhaps?
Upvotes: 0
Views: 148
Reputation: 8487
Based on the sample in the question, I presume two cases:
g = "bs"
should remain same in the target.g = "bs"
will also match a the strings "sb", "sabe", "sob", "boose" etc.For case 1:
You can first remove all vowels from target words in the arr
array. Then match it with the pattern in g
, and select only those words which match.
g = "bs"
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss']
arr.map{ |x| [x, x.gsub(/[aeiou]/,'')] }.select{ |x| x[1] == g }.map{|x| x[0]}
# ["base", "bees"]
For case2, simply sort the source string characters and target string characters before a match:
g = "bs"
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss']
v1 = arr.map{ |x| [x, x.gsub(/[aeiou]/,'')] }.select{ |x| x[1] == g }.map{|x| x[0]}
p v1
# ["base", "bees"]
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss', "sb", "sabe", "sob", "boose"]
v2 = arr.map{ |x| [x, x.gsub(/[aeiou]/,'')] }.select{ |x| x[1].split("").sort == g.split("").sort }.map{|x| x[0]}
p v2
# ["base", "bees", "sb", "sabe", "sob", "boose"]
Depending on the amount of data in arr
you can keep the intermediate values pre-processed for faster results.
Upvotes: 0
Reputation: 168239
If the order of the characters should be taken into account:
g = "bs"
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss']
arr.select{|w| w.tr("aeiouy", "") == g}
If the order of the characters should not be taken into account:
g = "bs"
g = g.each_char.sort
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss']
arr.select{|w| w.tr("aeiouy", "").each_char.sort == g}
Upvotes: 1
Reputation: 9782
This is what you want:
2.0.0p247 :122 > ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss'].select do |x|
x.match /^(?>b)[^bs]*(?>s)[^bs]*\b/
end
=> ["base", "bees"]
Matching unlimited amount of vowels aeiouy
['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss'].select do |x|
x.match /^(?>b)[aeiouy]*(?>s)[aeiouy]*\b/
end
=> ["base", "bees"]
Upvotes: 0
Reputation: 2582
Use Array#grep
method (core lib) and String#count
(codelib)
We look for words contained both characters (b and s) only once.
g = ["b", "s"]
arr = ['base', 'vase', 'race', 'bees', 'bass', 'sabb', 'babss']
arr.grep(/[aeiouy]/).select { |w| g.all? { |s| w.count(s) == 1 } }
Upvotes: 2