我正在解决Coderbyte问题,遇到一个名为ABCheck的问题,如果字母“a”和b分开三个位置,它会接受一个字符串并返回true
。我知道有一种更简单的方法可以用正则表达式做到这一点,但我试图以逻辑方式首先进行,以用于学习目的。
这是我的代码:
def ABCheck(str)
str = str.downcase.split('')
str.each_with_index do |char,index|
if char == 'a' && str[index+4] == 'b'
return "true"
elsif
char == 'b' && str[index+4] == 'a'
return "true"
else
return "false"
end
end
end
ABCheck("Laura sobs")
我的代码没有返回正确的答案。即使答案应为false
,它也会返回true
。
答案 0 :(得分:2)
问题是您只检查第一个字符 - 如果第一个字符不是a
或b
符合搜索条件,则会立即返回"false"
。在知道没有匹配的位置之前,您需要在所有中搜索字符串中的可能位置。
(这是在某种集合中搜索匹配时的常见模式;如果您找到它,您可以立即返回,但如果不这样做,则必须继续搜索直到结束。)
另请注意,您返回字符串 "false"
,而不是布尔值false
。
示例解决方案(没有正则表达式):
def axb_match?(str, in_between = 3)
distance = in_between + 1 # chars in between + the 'b'
str, i = str.downcase, -1
while i = str.index('a', i + 1)
return true if (str[i + distance] == 'b') || (i >= distance && str[i - distance] == 'b')
end
false # no match was found (finding would return immediately)
end
axb_match? "Laura sobs" # -> true
当然,使用正则表达式非常简单:
str =~ /(a...b)|(b...a)/i
答案 1 :(得分:2)
由于@Arkku诊断出您的问题,我将把我的评论限制在非正则表达式解决方案的替代方法中。 (在现实生活中,你当然希望使用正则表达式。)
我认为Ruby方式是使用Enumerable#each_cons而不是索引:
def a3b_match?(str)
str.each_char.each_cons(5).any? { |f,*_,l|
(f=='a' && l=='b') || (f=='b' && l=='a') }
end
a3b_match?('xadogbite') #=> true
a3b_match?('xbdogaite') #=> true
a3b_match?('xbdgaite') #=> false
a3b_match?('xadoggybite') #=> false
如果您想要匹配的数量,请将Enumerable#any?更改为Enumerable#count。
以下是步骤:
str = 'xadogbite'
enum0 = str.each_char
#=> #<Enumerator: "xadogbite":each_char>
enum1 = enum0.each_cons(5)
#=> #<Enumerator: #<Enumerator: "xadogbite":each_char>:each_cons(5)>
仔细检查枚举器enum0
和enum1
计算的返回值。您可以将enum1
视为&#34;化合物&#34;枚举器。
通过将该枚举器转换为数组,我们可以看到enum1
any?
将传递到块中的({1}}值:
enum1.to_a
#=> [["x", "a", "d", "o", "g"],
# ["a", "d", "o", "g", "b"],
# ["d", "o", "g", "b", "i"],
# ["o", "g", "b", "i", "t"],
# ["g", "b", "i", "t", "e"]]
让我们模拟将enum1
的第一个值传递到块中并将其分配给块变量 1 :
f,*m,l = enum1.next
f #=> "x"
m #=> ["a", "d", "o"]
l #=> "g"
然后我们执行块计算:
(f=='a' && l=='b') || (f=='b' && l=='a') }
#=> ('x'=='a' && 'g'=='b') || ('x'=='b' && 'g'=='a') }
#=> false || false => false
因此, any?
必须将enum1
的下一个元素传递到块中:
f,*_,l = enum1.next
#=> ["a", "d", "o", "g", "b"]
f #=> "a"
l #=> "b"
(f=='a' && l=='b') || (f=='b' && l=='a') }
#=> ('a'=='a' && 'b'=='b') => true
由于我们在(f=='a' && l=='b')
上匹配,因此Ruby无需评估(f=='b' && l=='a')
或对enum1
的其他元素执行类似的计算,因此她没有&# 39;吨。 any?
会返回true
。
1我使用局部变量m
而不是_
,因为IRB将后者用于自己的目的。从命令行运行时,_
工作正常。