Reputation: 21
This function should take in two strings "daBcD" and "ABC". It is trying to create the string "b" from the letters in "a". You can only delete or capitalize letters, you cant change them. b will always contain all uppercase letters.
def abbreviation(a, b)
aArray = a.split('')
idx = 0
aArray.each do |char|
#print "char: #{char}\n"
#print "Before loops: #{aArray}\n"
if char.casecmp(b[idx]) == 0
char.upcase!
idx += 1
#print "char: #{char}\nArry: #{aArray}\n"
#print "idx: #{idx}\n siz: #{b.size}\n"
if idx == b.size
aArray.reject! {|i| i == 'delete'}
aArray.slice!(b.size)
break
end
else
aArray[aArray.index(char)] = 'delete'
#print "deleted, now is: #{aArray}\n"
end
end
res = aArray.join('')
if res == b
return 'YES'
else
return 'NO'
end
end
This works for a couple test cases, but fails most of them. Can someone describe a better approach?
Upvotes: 1
Views: 75
Reputation: 198314
The absolutely easiest way is via regular expression:
def abbreviation(a, b)
re = Regexp.new(b.each_char.map(&Regexp.method(:quote)).join('.*'), Regexp::IGNORECASE)
!!re.match(a)
end
abbreviation("daBcD", "ABC")
# => true
abbreviation("daCbD", "ABC")
# => false
For the input ABC
, we'll construct a regular expression /A.*B.*C/i
, then test the other string against it. The .*
construct will account for "deletion"; the IGNORECASE
option for "capitalisation".
EDIT: If the problem is further constrained that only lowercase letters can be deleted, as suggested by the comments,
def abbreviation(a, b)
# (b is uppercase only)
re_pat = b.each_char.map { |c| "[#{c}#{c.downcase}]"}.join('[[:lower:]]*')
re = Regexp.new(re_pat)
!!re.match(a)
end
p abbreviation("daBcD", "ABC") # => true
p abbreviation("daBdcD", "ABC") # => true
p abbreviation("daBDcD", "ABC") # => false
Upvotes: 0
Reputation: 110665
I have assumed the problem is to determine whether the characters in b
appear in a
(case indifferent), in the same order as in b
, but not necessarily contiguous in a
(see the second example below). If they do I return an array of the indices at which they appear in a
. If there is no match, nil
is returned.
def doit(a, b)
m = a.match(Regexp.new(b.each_char.map { |c| "(#{c})" }.join('.*'),
Regexp::IGNORECASE))
return nil if m.nil?
(1..b.size).map { |i| m.begin(i) }
end
doit "daBcD", "ABC"
#=> [1, 2, 3]
doit "daXBDecf", "ABC"
#=> [1, 3, 6]
doit "dacBD", "ABC"
#=> nil
For the first example the regular expression is as follows.
Regexp.new("ABC".each_char.map { |c| "(#{c})" }.join('.*'), Regexp::IGNORECASE)
#=> /(A).*(B).*(C)/i
Upvotes: 1