canConstruct a memorization dynamic programming problem - python-3.x

I am stating to solve some dynamical programming problem, I came across the problem to solve if a string can be constructed from a list of string.
I have use this following method in python 3.8.
def canConstruct(target,workbank,memo={}):
if (target in memo):
return(memo[target])
if len(target)==0:
return(True)
for i in range (len(workbank)):
pos=target.find(workbank[i])
if (pos != -1):
suffix=target[pos:pos+len(workbank[i])]
out=canConstruct(suffix,workbank,memo)
if (out==True):
memo[target]=True
return(True)
memo[target]=False
return(False)
print(canConstruct('aabbc',['aa','b','c']))
instead of getting true I am getting the error maximum recursion depth exceeded in comparison.
I have checked my recursion limit it is 1000.
Can anyone tell me if I am doing anything wrong.
Thank you in advance.

Ok, there are few pitfalls in your code.
The main issue was, the for loop, because every time it calls the function, it started a new loop, hence the index of i was always one, this was creating the maximum recursion depth error.
The memo parameter, was been redundant to make it as a Dictionary,better in this case as a List.
This suffix=target[pos:pos+len(workbank[i])] had wrong position, it is supposed to be:
suffix = target[len(workbank[idx]):]]
Becase you need to leave behind was is already call and move forward right?
You were doing [0:2] which is 'aa' again. Insted you should do [2:] which is bbc
Solution
Note: I create as I understood the issue, if you expect a different output, please let me know in a comment below.
def canConstruct(target,workbank,memo=[], idx=0):
pos = target.find(workbank[idx])
if pos != -1:
memo.append(True)
idx += 1
try:
suffix = target[len(workbank[idx]):]
canConstruct(suffix,workbank,memo, idx)
except IndexError: # Here we exit the recursive call
pass
else: # In case it did not find string, append False
memo.append(False)
return all(memo) # in order to be True, all item in memo must be True
print(canConstruct('aabbc',['aa','bb','c']))
Output
# True

def canConstruct(target, wordbank, memo=None):
if memo is None:memo={}
if target in memo:return memo[target]
if target == '':return True
for word in wordbank:
if target.startswith(word):
suffix = target.replace(word, '', 1)
if canConstruct(suffix, wordbank, memo) == True:
memo[target] = True
return True
memo[target] = False
return False

Related

Checking words using "YNEOS"

In this problem, I take two strings from the user, the first string being s and the second string being t. If t is the reverse of s, I print "YES" else I print "NO".
Here is my code which gives me expected outputs:
s = input()
t = input()
if t == s[::-1]:
print("YES")
else:
print("NO")
But I found another approach that I am curious to understand, but the slicing part is making me confused. Here the code goes:
print("YNEOS"[input()!=input()[::-1]::2])
Trying to find a good explanation, so StackOverflow is what came to my mind before anything else.
Let's first extract the parts of that expression that concern the input/output and the string reversal. We then get this solution:
s = input()
t = input()
trev = t[::-1]
result = "YNEOS"[s != trev::2]
print(result)
The focus of the question is on the expression "YNEOS"[s != trev::2]
Now we get to the "trick" that is performed here. The expression s != trev can be either False or True. This boolean value becomes the first part in the slicing. You'd expect to have the start index of the slice at this position. But the boolean value will also work, as booleans are a subclass of integers, and False is 0 and True is 1. So the above expression evaluates to either:
"YNEOS"[0::2]
or
"YNEOS"[1::2]
The 2 serves as the step, and so "YNEOS"[0::2] will take the characters at indices 0, 2 and 4 ("YES"), while "YNEOS"[1::2] takes the characters at indices 1 and 3 ("NO").
I hope this clarifies it.

Index out of range in leetcode ide in code for finding the length of the longest substring without repeating characters

This below giving expected output in pycharm and the other side it's getting index out of range in line return length_of_substring[-1] in leetcode.
why it is getting such error?
class Solution:
def lengthOfLongestSubstring(self, string):
unique_list = []
length_of_substring = []
for i in string:
if i not in unique_list:
unique_list.append(i)
else:
length_of_substring.append(len(unique_list))
unique_list.clear()
unique_list.append(i)
length_of_substring.sort()
return length_of_substring[-1]
if __name__ == '__main__':
s = input()
obj = Solution()
result = Solution.lengthOfLongestSubstring(obj, s)
print(result)
First of all: when posting here you should clearly specify (i) the goal of your code and (ii) a self contained minimum example.
In your case it is very difficult to answer your question, because you do not make clear what your code is actually trying to achieve.
Regarding your error message:
Your code does not account for the fact that a string could also consist of only unique elements (e.g. "abcd"). In that case the else clause of your code is never reached and length_of_substring will remain empty. If you then call length_of_substring[-1] it raises an error message.

When i change True to False in the first code my output stays same.Why is that?

My code:
liste = ["345","sadas","324a","14","zxc"]
for i in liste:
try:
int(i) == True #(make it false for example)
print(i)
except:
pass
for i in liste:
try:
i = int(i)
print(i)
except:
pass
output:
345
14
Here as you can see there are two different codes and the question is only write the numbers not letters.(By using try-except). But my question is when i change True to False in the first code my output stays same.Why is that?
This:
int(i) == True #(make it false for example)
first try to make an int of i, and if the operation succeeds, compares it with True, then discard the result of the test. IOW, the whole comparison ends up being a no-op ((functionally speaking - the code is still executed), and could as well be replaced with just
`int(i)`
Of course since the result of the comparison is discarded, you could test against just any value that's comparable with an int (another int, a float, a bool etc), this would make absolutely no difference.
As a side note: this:
try:
something()
except:
pass
is pure evil - it catches absolutely everything (including a SystemExit) and ignore it. I understand this is just a quick test code snippet, but do yourself a favour and never do this in real code - always specify the exact exception(s) you expect and can handle at this point in the code, and if you want to ignore them, at least log them somewhere so you know what really happens in your code.
when i change True to False in the first code my output stays same
Because you're not doing anything with that result, as compared to
if int(i) == True:
print(i)
Or simply
if int(i):
print(i)
But, more appropriate would be
if i.isdigit():
print(i)

Index out of range - Python

I was programming at CodeWars using Kata, when i got this error:
Traceback:
in
in title_case
IndexError: list index out of range
Here is my code:
def title_case(title, minor_words=1):
string = title.split()
outList = []
if minor_words != 1:
split = minor_words.split()
minor = [x.lower() for x in split]
out = ""
for i in range(0, len(string)):
word = ""
for j in range(0,len(string[i])):
elem = ""
elem += string[i][j]
if j == 0:
word += elem.upper()
else:
word += elem.lower()
if i != len(string)-1:
outList.append(word+" ")
else:
outList.append(word)
list = [x.lower() for x in outList]
print ((list[0]))#Just for debug
if minor_words != 1:
for i in range(0, len(outList)):
if (list[i] in minor):
print("OI")#Just for debug
out += list[i]
else:
out += outList[i]
return out
Well, this happened when trying to execute the code, of course!
One way to initialize this function would be:
title_case('a clash of KINGS', 'a an the of')
Well the 0 elemeny exists, but it says it doesn't, I don't know why, because when I write "print(list)" it shows me the elements of list, in this case, "['a', 'clash', 'of', 'kings']".
What can I do?
Okay, so based on reading this code I think the result you desire from:
title_case('a clash of KINGS', 'a an the of') is:
A Clash of Kings
So it looks like you are stepping through a lot of hoops trying to get there. While I was going through the code it took me a while to see what was actually happening. I also took the liberty to make your variables more consistently named. Rather than mixing caseLetter and case_letter randomly I made it consistent. I also made your loops easier to read. Also for the minorWords argument. Might as well have it passed as a list rather than converting it to a list inside the function. Anyway, I hope this is of help.
def titleCase(title, minorWords=[]):
titleList = [x.lower() for x in title.split()]
outList = []
for Word in titleList:
if Word not in minorWords:
Word = Word.capitalize()
outList.append(Word)
return " ".join(outList)
TitleCased = titleCase("a clash of KINGS", ["an", "the", "of"])
print (TitleCased)
Which outputs A Clash of Kings, which I believe, based on your question and how I understood your code is what you wanted to achieve? Or if you include a in your minorWords, it would be:
a Clash of Kings
Regardless, hope this answers your question!

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