We'll say that a lowercase 'g' in a string is "happy" if there is another 'g' immediately to its left or right. Return true if all the g's in the given string are happy.
gHappy("xxggxx") → true gHappy("xxgxx") → false gHappy("xxggyygxx") → false
I have written two functions to solve this problem, but I have some concerns:
- Of the one with Regex, I don't like all the special cases.
- Of the one with iteration, I don't like the weird helper method.
Both pass a fair number of tests and work correctly. Which one is better?
regex_geppy.rb
def geppy(string)
return true if ! string.include?('g')
return false if [0, 1].include?(string.length)
return false if string.length == 2 && string != 'gg'
return (not string.match("[^g]g[^g]"))
end
array_geppy.rb
def non_wrap_get(array, index)
index < 0 ? nil : array[index]
end
def geppy(string)
string
.chars
.each_with_index
.all? { |curr, i|
curr == 'g' ?
non_wrap_get(string, i - 1) == 'g' || non_wrap_get(string, i + 1) == 'g'
: true
}
end
geppy_tests
geppy("xxggxx") #=> true
geppy("xxgxx") #=> false
geppy("xxggyygxx") #=> false
geppy("g") #=> false
geppy("ag") #=> false
geppy("gg") #=> true
geppy("") #=> true
geppy("ab") #=> true
geppy("aaaa") #=> true
geppy('g'*1000) #=> true
2 Answers 2
@200_success already showed a compact solution using regular expressions. As for the "array-solution", I think you missed the abstraction Enumerable#chunk:
def g_happy(s)
s.chars.chunk { |c| c }.all? { |c, cs| c == "g" ? cs.size > 1 : true }
end
Or .all? { |c, cs| cs != ["g"] }
, whatever feels more declarative to you.
-
\$\begingroup\$ Error:
undefined method "itself" for string
which version are you using? \$\endgroup\$Caridorc– Caridorc2015年07月11日 09:07:34 +00:00Commented Jul 11, 2015 at 9:07 -
1\$\begingroup\$ >= 2.2.0. Changed to a more portable block. \$\endgroup\$tokland– tokland2015年07月11日 11:37:39 +00:00Commented Jul 11, 2015 at 11:37
Regular expressions are the right tool to use for this kind of test. However, if you are going to use a regular expression to find lonely g
characters, then you should use negative lookbehind and lookahead assertions instead of the negated character class [^g]
.
def geppy(str)
!/(?<!g)g(?!g)/.match(str)
end
Explore related questions
See similar questions with these tags.