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 g
s 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 g
s).
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