function that returns `True` if a string contains exactly two instance of a substring and `False` if it doesn't - python-3.x

I'm trying to write a function that returns True if a string contains exactly two instance of a substring and False if it doesn't.
I'm getting an error:
return' outside function
I feel I'm very close but just can't quite get it, I'd appreciate being pointed in the right direction.
Should recursion be used?
s = ("xeroxes")
exes = str(x)
count = 0
def has_two_X(s):
count = s.count(exes)
for exes in s:
count = +1
if count ==2:
return True
else:
return False
if __name__ == "__main__":
print("string has :",count.s(exes))

If the code must return True if there is two or more instances of substring, you can create a dictionary and return True if value is there in dictionary or not.
mydict = {}
for letter in s:
if letter in mydict:
return True
else:
mydict[letter] = 0
return False #Since there is no substring (two substring can be formed only if it has two same letters in the string)
To find exactly if it has two substring, I would recommend the same approach where you can maintain the dictionary and the count of substring present. Add all the substring/count to the dictionary, this would take O(n^2) to generate all substrings and approx- O(n^2) hashmap memory.
After constructing hashmap, you can iterate over the hashmap to return True if it has exactly two occurences of substring.

Related

Function returns inside loops?

How do return statements of a function work inside for loops? See my code below for what got me thinking about this.
It is like a game of scrabble. You get given n letters (we'll call it a hand), and the aim is to make a word out of your hand. The hand is in the form of a dictionary, like so:
yellow = {'y':1, 'e':1, 'l':2, 'o':1, 'w':1}
I have written a function called get_frequency_dict to transform a string in to this form.
I want to write a function which tells me if the word given is valid or not. I have a list of acceptable words in the variable word_list
Call the function: is_valid_word(word, hand, word_list) which takes in three inputs.
word: string
hand: dictionary (string: int)
word_list: list of lowercase strings
So, I wanted to write this function to return True if the word is valid and False if the word is invalid:
def is_valid_word(word, hand, word_list):
word_dict = get_frequency_dict(word.lower())
if word.lower() in word_list:
for char in word_dict:
if (char in hand) and (hand[char] >= word_dict[char]):
return True
else:
return False
else:
return False
This function seems to work fine with various different inputs, but I'm not quite sure I understand the logic behind the function return in the for loop?
As we loop through the keys in the dictionary (letters), we will get a True or False depending on whether or not the condition is satisfied. So, how does the function know what to return? What if one char returns False and then the next char returns True? Does it instantly return False as soon as it sees one False in the for loop?
The code below makes more sense to me:
total_false = 0
for char in word_dict:
if (char in hand) and (hand[char] >= word_dict[char]):
pass
else:
total_false += 1
if word.lower() not in word_list:
return False
elif total_false > 0:
return False
else:
return True
Does the first segment of code do this "counting" behind the scenes? As in, as soon as we see a False, it returns False?
Simply iterate over the list and if you find an error, stop:
def is_valid_word(word, hand, word_list):
word_dict = get_frequency_dict(word.lower())
if word.lower() in word_list:
for char in word_dict:
if (char in hand) and (hand[char] >= word_dict[char]):
continue
else:
return False #This will stop the function and return false
else:
return False #This will do the same
#At the end, this means that all of the criteria are met, so we return True
return True
As we see, the moment a character doesn't fit the criteria, the function stops and returns false. If it passes all the criteria, it returns true.

Finding a substring in a jumbled string

I am writing a script - includes(word1, word2) - that takes two strings as arguments, and finds if word1 is included in word2. Word2 is a letter jumble. It should return Boolean. Also repetition of letters are allowed, I am only checking if the letters are included in the both words in the same order.
>>>includes('queen', 'qwertyuytresdftyuiokn')
True
'queen', 'QwertyUytrEsdftyuiokN'
I tried turning each word into lists so that it is easier to work with each element. My code is this:
def includes(w1, w2):
w1 = list(w1)
w2 = list(w2)
result = False
for i in w1:
if i in w2:
result = True
else:
result = False
return result
But the problem is that I need to also check if the letters of word1 comes in the same order in word2, and my code doesn't controls that. I couldn't find a way to implement that with list. Just like I couldn't do this much with strings, so I think I need to use another data structure like dictionary but I don't know much about them.
I hope I understood what is your goal.
Python is not my thing, but I think I made it pythonic:
def is_subsequence(pattern, items_to_use):
items_to_use = (x for x in items_to_use)
return all(any(x == y for y in items_to_use) for x, _ in itertools.groupby(pattern))
https://ideone.com/Saz984
Explanation:
itertools.groupby transfers pattern in such way that constitutive duplicates are discarded
all items form form grouped pattern must fulfill conditions
any uses generator items_to_use as long as it doesn't matches current item. Note that items_to_use mus be defined outside of final expression so progress on it is kept every time next item from pattern is verified.
If you are not just checking substrings:
def include(a, b):
a = "".join(set(a)) # removes duplicates
if len(a) == 1:
if a in b:
return True
else:
return False
else:
try:
pos = b.index(a[0])
return include(a[1:], b[pos:])
except:
return False
print(include('queen', 'qwertyuytresdftyuiokn'))
#True

Python: Check if tuple contain only integers with while

I have a task to define a function contains_only_integers which takes a tuple as the argument and returns True is every element of the tuple is an integer, and false otherwise. I'm a bit stuck on why I get false every time.
I would use a for-loop, but the task asks specifically for a while loop.
def contains_only_integers(tup):
while isinstance(tup, int)==True:
return True
else:
return False
What am I missing?
Mthrsj covered your problem and how to fix it but an alternative, perhaps more pythonic, way of doing this would be to use the builtin all function.
def contains_only_integers(tup):
return all(isinstance(v, int) for v in tup)
When you do while isintance(tup,int), the function evaluates the tuple, not each element. To achieve what you want, you need to iterate over the tuple. An example below:
def contains_only_integers(tup):
for item in tup:
if not isinstance(item, int):
return False
return True
If the code find any item in the tuple that is not an integer instance it will return False. Otherwise, it will return True.
EDIT
As you said you need to use a while loop, there it is:
def contains_only_integers(tup):
i = 0
while i < len(tup):
if not isinstance(tup[i], int):
return False
i+=1
return True

How to slice a list of strings till index of matched string depending on if-else condition

I have a list of strings =
['after','second','shot','take','note','of','the','temp']
I want to strip all strings after the appearance of 'note'.
It should return
['after','second','shot','take']
There are also lists which does not have the flag word 'note'.
So in case of a list of strings =
['after','second','shot','take','of','the','temp']
it should return the list as it is.
How to do that in a fast way? I have to repeat the same thing with many lists with unequal length.
tokens = [tokens[:tokens.index(v)] if v == 'note' else v for v in tokens]
There is no need of an iteration when you can slice list:
strings[:strings.index('note')+1]
where s is your input list of strings. The end slice is exclusive, hence a +1 makes sure 'note' is part.
In case of missing data ('note'):
try:
final_lst = strings[:strings.index('note')+1]
except ValueError:
final_lst = strings
if you want to make sure the flagged word is present:
if 'note' in lst:
lst = lst[:lst.index('note')+1]
Pretty much the same as #Austin's answer above.

recursion not stopping with 'if'

I am trying to write a code which prints True if given string has at max 2 consecutive c, and at max 1 b. I am using recursion to reduce the string and check that at max 'c' is present in the same index twice.But my recursion is not stopping till it empties the whole list. Can you please suggest what's wrong with my code. Thanks!
def stringcond(N,count=0,k=0):
N=list(N)
if(N.count('b')>1):
return False
if len(N)<2:
return True
else:
for i,j in enumerate(N):
if(j=='c'):
del N[i]
count+=1
if(k==i and count>2):
return False
stringcond(N,count=count,k=i)
return True
You have several mistakes. First, why are you splitting the characters into a list? There is a perfectly good count method for strings.
Your recursion fails because you ignore the return value. You would want something like
if not stringcond(N,count=count,k=i):
return False
# I make no claim that this logic is correct.
In any case, there is no need to recur. Use count to check the quantity of "b" and many-'c' substrings:
def stringcond(s, c_max=0):
return s.count('b') <= 1 and \
s.count("c" * (c_max+1)) == 0
You have to use the result of the stringcond call. Now your function will only return whatever was determined on the top level call.

Resources