5
\$\begingroup\$

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
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jul 10, 2015 at 22:12
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

@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.

answered Jul 11, 2015 at 8:47
\$\endgroup\$
2
  • \$\begingroup\$ Error: undefined method "itself" for string which version are you using? \$\endgroup\$ Commented Jul 11, 2015 at 9:07
  • 1
    \$\begingroup\$ >= 2.2.0. Changed to a more portable block. \$\endgroup\$ Commented Jul 11, 2015 at 11:37
2
\$\begingroup\$

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
answered Jul 10, 2015 at 23:13
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.