passing parameters into a linear search function on python - python

I have this linear search where there is a list of words and a single word. the search checks whether the word is in the list or not. I keep on trying to pass my parameters to test the function but when i run the program nothing comes up. it would be great if you could look at this code and tell me where im going wrong.
def isin(alist, word):
found = False
length = len(alist)
pos = 0
while found == False and pos < length:
if alist[pos] == word:
found == True
else:
pos = pos + 1
return found
words = ["child","adult","cat","dog","whale"]
if isin(words, "dog"):
print("yes")
else:
print("no")

You are doing a lot extra works. Do it like this:
def isin(alist, word):
if word in alist:
return True
else:
return False
words = ["child","adult","cat","dog","whale"]
if isin(words, "dog"):
print("yes")
else:
print("no")

You have a problem with line found == True. It should be found = True.
def isin(alist, word):
found = False
length = len(alist)
pos = 0
while found == False and pos < length:
if alist[pos] == word:
found = True
else:
pos = pos + 1
return found
You could simplify the method to do the same task in one line as:
def isin(alist, word):
return True if word in alist else False

Related

Balanced expression with replacement

Given a string that contains only the following => ‘{‘, ‘}’, ‘(‘, ‘)’, ‘[’, ‘]’. At some places there is ‘X’ in place of any bracket. Determine whether by replacing all ‘X’s with appropriate bracket, is it possible to make a valid bracket sequence.
Examples:
Input : S = "{(X[X])}"
Output : Balanced
Input : S = "[{X}(X)]"
Output : Not balanced
I tried to work it out like this, and it works for examples above. But it doesn't work for all examples eg. (it should be balanced but it says it's not)
Input: S = "([X}])"
Output: Not balanced
I tried to work it out but i can't find a solution. Please help.
class Stack:
def __init__(self):
self.data = []
def insert(self, x):
self.data.append(x)
def empty(self):
return len(self.data) == 0
def remove(self):
if self.empty():
raise ValueError('Stack is empty.')
self.data.pop()
def top_element(self):
if self.empty():
raise ValueError('Stack is empty.')
return self.data[-1]
def is_matching(a, b):
if a == "(" and b == ")":
return True
elif a == "[" and b == "]":
return True
elif a == "{" and b == "}":
return True
elif a == "X":
return True
return False
def is_balanced(expression,elements=Stack(),ind=0):
if ind == len(expression):
return elements.empty()
pre_brackets = "([{"
post_brackets = ")]}"
char = expression[ind]
if char in pre_brackets:
elements.insert(char)
return is_balanced(expression,elements,ind+1)
elif char in post_brackets:
if elements.empty() :
return False
if not is_matching(elements.top_element(), char):
return False
elements.remove()
return is_balanced(expression,elements,ind+1)
elif char == "X":
temp = Stack()
temp.insert(char)
result = (is_balanced(expression,temp,ind+1))
if result:
return True
if elements.empty():
return False
elements.remove()
return is_balanced(expression,elements,ind+1)
expression = "([X}])"
if expression == "":
print("No brackets in expression!")
elif len(expression) % 2 != 0:
print("Not balanced")
elif is_balanced(expression):
print("Balanced")
else:
print("Not Balanced")
You can do it by recursively testing all possible replacements for an X:
def can_be_balanced(expr):
pairs = "{}[]()"
opening_brackets = pairs[::2]
closing_brackets = pairs[1::2]
closer = {o:c for o, c in zip(opening_brackets, closing_brackets)}
opener = {c:o for o, c in zip(opening_brackets, closing_brackets)}
stack = []
for item in expr:
if item in opening_brackets:
# we append opening brackets to the stack
stack.append(item)
elif item in closing_brackets:
if not stack or stack[-1] != opener[item]:
# the closing bracket doesn't match the top of the stack
return False
else:
# if it does, we remove the matching opening bracket
stack.pop()
elif item == 'X':
# X could be any of the opening brackets,
possible = list(opening_brackets)
if stack and stack[-1] in opening_brackets:
# or the closing bracket matching the top of the stack
possible.append(closer[stack[-1]])
for pos in possible:
# we replace this X, the first one remaining in expr
test_expr = expr.replace('X', pos, 1)
if can_be_balanced(test_expr):
# This is just in order to print the working solution we just found,
# you may remove these two lines
if not 'X' in test_expr:
print(test_expr)
return True
# None of the replacements for X gave a balanced expression
return False
else:
raise ValueError(f'Invalid item {item} in {expr}')
# The expression is balanced if and only if the stack ends up empty
return not stack
Testing on your sample data:
tests = [("[{X}(X)]", False),
("{(X[X])}", True),
("([X}])", True),
]
for test in tests:
print(test[0], ': should be', test[1])
print(can_be_balanced(test[0]))
print('-'*20)
correctly outputs (with the balanced expression in case it can be done):
[{X}(X)] : should be False
False
--------------------
{(X[X])} : should be True
{([[]])}
True
--------------------
([X}]) : should be True
([{}])
True
--------------------
Note that a major problem in your code is that you only test the end of the expression, starting at the position of the X. Beware also of the mutable default argument elements=Stack() that would leave you with the remnants of the previous call to the function instead of a fresh, empty Stack object.

I am trying to reduce my code to make it simpler by removing the indexes

This is my recursive function named find(text,substring) that will return the substring if the substring is inside the text or return an empty string if substring is not inside the text. Another function named is_string_there(text, string) to test the find function. The function will return True if the string is inside the text or False if the string is not inside the text.
Am I able to cancel out text index and substring index to remove the two (0,0) at the print coding area to reduce my code to make it simpler and easier to understand so i can teach my students
def find(text, substring, text_index, substring_index):
if text_index == len(text) and substring_index != len(substring):
return False
if substring_index == len(substring):
return True
if text[text_index] == substring[substring_index]:
return find(text, substring, text_index+1, substring_index+1)
return False
def oo(text, substring, text_index, substring_index):
if text_index == len(text):
return False
if text[text_index] == substring[substring_index]:
if find(text, substring, text_index, substring_index):
return True
else:
return oo(text, substring, text_index+1, substring_index)
return oo(text , substring, text_index+1, substring_index)
print(oo("I love pie", "pie",0,0))
print(oo("I love pie1", "pie1",0,0))
Well if you want to remove the indexes permanently from the print commands, you could just use a class. This way you can even create other functions to take user input etc and take advantage of class variables for readability. Not sure if if cases should in form if-elif-else though:
class test():
def __init__(self):
self.reset()
self.run()
def reset(self):
self.substring_index = 0 #instead of putting in function they are now class variables
self.text_index = 0
def run(self):#more stuff can be done here
print(self.oo("I love pie","pie"))
self.reset() #reset the class variables for each step
print(self.oo("I love pie1","pie1"))
def find(self,text, substring): #pretty much the same code just using class variables and class methods
if self.text_index == len(text) and self.substring_index != len(substring):
return False
elif self.substring_index == len(substring):
return True
elif text[self.text_index] == substring[self.substring_index]:
self.text_index +=1
self.substring_index +=1
return self.find(text, substring)
else:
return False
def oo(self,text, substring):
if self.text_index == len(text):
return False
elif text[self.text_index] == substring[self.substring_index]:
if self.find(text, substring):
return True
else:
self.text_index +=1
return oo(text, substring)
else:
self.text_index +=1
return self.oo(text , substring)
if __name__=='__main__':
test()
Although just for reference, a super simple way for the problem is actually:
def oo(text,substring):
if substring in text:
return True
else:
return False
AS mentioned in comments:
def oo(text,substring):
if text.find(substring) == 0:
return True
else:
return False
Returns 0 if exists in text, -1 if not.
Interesting expansion possible when considering uppercase or lowercase diffrences. 'A' != 'a'
In your code, you use oo() to check if a character matches, and then calls find() to check if the rest of the characters match. Instead of checking character-by-character, you could use the idea of checking string equality. In your oo() function, you can check if the substring is equal to a splice of the original text. This will reduce your code but will make your find() function obsolete, while still serving as a simple demonstration of recursion.
def oo(text, substring, index):
if index == len(text):
return False
start = index
end = start + len(substring)
if text[start:end] == substring:
return True
else:
return oo(text, substring, index+1)
print(oo("I love pie", "pie",0))
print(oo("I love pie1", "pie1",0))
print(oo("I love pie", "pie1",0))
print(oo("I love pie1", "pie",0))
print(oo("pie", "pie",0))
print(oo("pi", "pie1",0))
print(oo("pie1", "pie",1))
Output:
True
True
False
True
True
False
False

Check the lexicographic order of two strings in python

I am trying to implement a function in python that given two strings it checks if the first string is smaller than the second string in the lexicographic order. This is what I managed to write, I do not claim that it is elegant code
import string
#first make a dictionary that gives the value of a letter, eg "C":3
d = dict.fromkeys(string.ascii_uppercase, 0)
i=1
for c in d.keys():
d[c] = i
i+=1
def lexico(str1,str2):#returns true if str1<=str2 in lexicographic order
print(str1,str2) #printing for debugging purpose
if str1 == '' and str2 == '':
return True
elif str1 != '' and str2 == '':
return False
elif str1 == '' and str2 != '':
return True
elif d[str1[0]] > d[str2[0]]:
return False
elif d[str1[0]] < d[str2[0]]:
return True
elif str1 == str2:
return True
else:
print(str1,str2) #printing for debugging purpose
lexico(str1[1:],str2[1:])
str1 = 'ANGELA'
str2 = 'AMY'
print(lexico(str1,str2))
I have really no idea what goes wrong here, but the output is as follows
ANGELA AMY
ANGELA AMY
NGELA MY
None
The function does not return anything, and I dont know why.
You are missing a return on this line: lexico(str1[1:],str2[1:]). It should be return lexico(str1[1:],str2[1:]).

Why does my Python recursive function not break?

I have this code that should break once it fulfills a certain condition, ie when the isuniquestring(listofchar) function returns True, but sometimes it doesn't do that and it goes into an infinite loop. I tried printing the condition to check if there's something wrong with the condition, but even when the condition is printed true the function still continues running, I have no idea why.
one of the strings that throws up an infinite loop is 'thisisazoothisisapanda', so when I do getunrepeatedlist('thisisazoothisisapanda'), it goes into an infinite loop.
would be really grateful if someone could help
thanks!
Here's my code:
def getunrepeatedlist(listofchar):
for ch in listofchar:
if isrepeatedcharacter(ch,listofchar):
listofindex = checkrepeatedcharacters(ch,listofchar)
listofchar = stripclosertoends(listofindex,listofchar)
print (listofchar)
print (isuniquestring(listofchar))
if isuniquestring(listofchar):
return listofchar
#print (listofchar)
else:
getunrepeatedlist(listofchar)
return listofchar
just for reference, these are the functions I called
def isrepeatedcharacter(ch,list):
if list.count(ch) == 1 or list.count(ch) == 0:
return False
else:
return True
def checkrepeatedcharacters(ch,list):
listofindex=[]
for indexofchar in range(len(list)):
if list[indexofchar] == ch:
listofindex.append(indexofchar)
return listofindex
def stripclosertoends(listofindices,listofchar):
stringlength = len(listofchar)-1
if listofindices[0] > (stringlength-listofindices[-1]):
newstring = listofchar[:listofindices[-1]]
elif listofindices[0] < (stringlength-listofindices[-1]):
newstring = listofchar[listofindices[0]+1:]
elif listofindices[0] == (stringlength-listofindices[-1]):
beginningcount = 0
endcount = 0
for index in range(listofindices[0]):
if isrepeatedcharacter(listofchar[index],listofchar):
beginningcount += 1
for index in range(listofindices[-1]+1,len(listofchar)):
if isrepeatedcharacter(listofchar[index],listofchar):
endcount += 1
if beginningcount < endcount:
newstring = listofchar[:listofindices[-1]]
else:
#print (listofindices[0])
newstring = listofchar[listofindices[0]+1:]
#print (newstring)
return newstring
def isuniquestring(list):
if len(list) == len(set(list)):
return True
else:
return False
It may be due to the fact that you are changing listofchar in your for loop. Try cloning that variable to a new name and use that variable for manipulations and return the new variable.

rfind implementation using find

I am new to python and I am trying to implement rfind function using find.
def rfind_imp(s,t):
ss = s
fpos = 0
while(True):
fpos = s.find(t,fpos)
ss=ss[fpos:]
if(ss):
fpos = fpos +1
else:
return fpos
print rfind_imp("I saw a donkey,I saw a saw "," ")
print "I saw a donkey,I saw a saw ".rfind(" ")
But the issue I am facing is I am getting 16th charcter as rfind value. Can some one help me find where I am doing a mistake. Also any suggestions for better implementation of rfind using find should be helpful.
I think your algorithm should be implemented like this:
def rfind_imp(s, t):
fpos = -1
while True:
pos = s.find(t, fpos + 1)
if pos == -1:
return fpos
fpos = pos
Another algorithm that's probably faster for strings with many ocurrences of t:
(Edit: made it work for strings with more than one character)
def rfind2(s, t):
pos = s[::-1].find(t[::-1])
if pos == -1:
return pos
return len(s) - pos - len(t)
Maybe something like:
def rfind_imp(s, t):
fpos = 0
while(True):
fpos = s.find(t, fpos)
if fpos == -1:
return pfpos
else:
pfpos = fpos
fpos += 1

Categories