Home > Net >  How to check if all lowercase 'g' in a string has another 'g' adjacent to it?
How to check if all lowercase 'g' in a string has another 'g' adjacent to it?

Time:04-28

I need to write a program that returns True/False based on the following conditions:

  • A lowercase 'g' in a string is "happy" if there is another 'g' adjacent to it, such as "gg". Then, return True if all the g's in the given string are happy.
  • Else, return False

The desired output is:

string: xggt
output: True

string: abgsx
output: False

string: xxggygxx
output: False

I am a little lost with this question and am scratching my head at trying to solve it. Would anyone be able to assist me and explain how the desired result is achieved?

My current code is :

s=input("Enter string: ")

happy = true
sad = false
while s <='g':
    print ("Happy?",sad)
elif s <='gg':
    print("Happy?", happy)

CodePudding user response:

Using re library is very helpful when looking for patterns in strings. So in that case you would want to search for one of the following patters:

  • "g"
  • "...Xg"
  • "gX..."
  • "...XgX..."

where X is anything except 'g'. so with re library it would be:

import re
s=input("Enter string: ")
res = bool(re.search(r"(^g$|[^g]g$|^g[^g]|[^g]g[^g])", s))
print("Happy?", res)

CodePudding user response:

The classic way of doing this would be with a regex, but I'll show how to do it with itertools.groupby:

>>> from itertools import groupby
>>> def is_happy(s):
...     """Returns whether all 'g's are next to at least one other 'g'."""
...     return all(sum(1 for _ in x) > 1 for g, x in groupby(s, "g".__eq__) if g)
...
>>> is_happy("xggt")
True
>>> is_happy("abgsx")
False
>>> is_happy("xxggygxx")
False

Let's break down the individual pieces:

for g, x in groupby(s, "g".__eq__)

groupby turns an iterable (in this case s) into "groups" based on a grouping function.

g in this iteration is the result of "g".__eq__, i.e. whether the group is of gs or not. x is the actual group (i.e. a substring of s).

if g

The if g on the end means we'll skip any g, x pair where g is false (i.e. any group that's not just gs).

sum(1 for _ in x) > 1

This tells us whether the group has more than one element. If x were a string we could just use its len, but it's a _grouper which is a one-use iterable that doesn't implement __len__, so instead we use sum to iterate over it and count 1 for each character.

all(...)

tells us whether all of the elements in the iteration are true -- are all the g groups longer than 1 element?

CodePudding user response:

Using regular expressions can be a little hard to read and understand, but is more efficient. This is an implementation that searches for instances of the letter g and then looks for a preceding or following g. If not found, then return unhappy result:

s = input("Enter string: ")
happy = True
for ctr, letter in enumerate(s):
    if letter == "g":
        if ctr > 0 and s[ctr - 1] == "g":
            pass
        elif ctr < (len(s) - 1) and s[ctr   1] == "g":
            pass
        else:
            # unhappy
            happy = False
            break
print(s, happy)

CodePudding user response:

Here's a way of doing it by checking the index before and after every "g" in a word.

my_inputs = ["xggt", "abgsx", "xxggygxx"]

for _input in my_inputs:
    state = False
    for i, char in enumerate(_input):
        if char == "g":
            if i > 0 and _input[i-1] == "g" or i < len(_input)-1 and _input[i 1] == "g":
                state = True
            else:
                state = False
    print(f"string: {_input}\noutput: {state}\n")

output:

string: xggt
output: True

string: abgsx
output: False

string: xxggygxx
output: False
  • Related