Counting lowercase using recursion and low and high parameters - python

So im trying to create a recursive function that can count the amount of lowercase numbers in a word. This is what I have so far and im having difficulty implementing the low and high parameters that determine the range the function is checking.
def count_lowercase(s, low, high):
count = 0
if len(s) == 0:
return 0
elif s[low].islower():
count+=1
count_lowercase(s[low+1:high])
return count

You need to have the recursion step on the return, so they get called for every size until done.
This code does it, high defines the position of limit:
def count_lowercase(s, high=0):
count = 0
if len(s) == 0:
return 0
if high == 0:
high = len(s)
if s[0].islower():
count+=1
return count + count_lowercase(s[1:high+1])

You can use a function that checks if the first character is lowercase and recursively adds the number of lowercase characters in the rest of the string, or returns 0 if the string is empty:
def count_lowercase(s):
return len(s) and s[0].islower() + count_lowercase(s[1:])

Related

How do I optimize this recursive function that counts the number of n-digit hexadecimal numbers whose digits equal a sum?

def hexify(summ, l, count = 0):
if sum == 0:
return 1
for i in range(16):
if i < summ and l > 1:
count += hexify(summ-i, l-1)
elif i == summ and l > 0:
count += 1
return count
hexa = str(input())[2:] #input tag eg. 0x0121
summ = sum(int(digit, 16) for digit in hexa)
print(hexify(summ, len(hexa)) - 1)
What this code does is find the number of n-digit hexadecimal numbers whose digits equal to a certain sum. For example, if the given hexadecimal number is 0x12, the function would return 3 (meaning there are 3 hex numbers whose digits sum to three, excluding 0x12, which are 0x03 0x30 and 0x21).
The problem is the given constraints are 1 > 1 > 10, and the code stops functioning once the length l exceeds 6. How do I optimize this? (Recursion is required)
If you want to speed up your code you can use the cache decorator
#functools.cache(user_function)
Simple lightweight unbounded function cache. Sometimes called “memoize”.
Returns the same as lru_cache(maxsize=None), creating a thin wrapper
around a dictionary lookup for the function arguments. Because it
never needs to evict old values, this is smaller and faster than
lru_cache() with a size limit.
https://docs.python.org/dev/library/functools.html#functools.cached_property
from functools import cache
#cache
def hexify(summ, l, count = 0):
if sum == 0:
return 1
for i in range(16):
if i < summ and l > 1:
count += hexify(summ-i, l-1)
elif i == summ and l > 0:
count += 1
return count
hexa = str(input())[2:] #input tag eg. 0x0121
summ = sum(int(digit, 16) for digit in hexa)
print(hexify(summ, len(hexa)) - 1)

Incorrect sliding window algorithm (in python)

While trying this question: https://leetcode.com/problems/permutation-in-string/
"Given two strings s1 and s2, return true if s2 contains a permutation
of s1, or false otherwise.
In other words, return true if one of s1's permutations is the
substring of s2."
I came up with a sliding window solution, but I did not want to use an additional hash table for keeping track of the letters in the current window. I am struggling to figure out why it is not correct.
Fails with this example: "trinitrophenylmethylnitramine" "dinitrophenylhydrazinetrinitrophenylmethylnitramine"
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
s1_ht = {}
for char in s1:
if char in s1_ht:
s1_ht[char] += 1
else:
s1_ht[char] = 1
start = 0
counter = len(s1_ht)
for i in range(0, len(s2), 1):
if s2[i] in s1_ht:
s1_ht[s2[i]] -= 1
if s1_ht[s2[i]] == 0:
counter -= 1
if i - start + 1 == len(s1):
if counter == 0:
return True
if s2[start] in s1_ht:
s1_ht[s2[start]] += 1
if s1_ht[s2[start]] > 0:
counter += 1
start += 1
return False
Great solution. But there is a minor mistake here:
if s1_ht[s2[start]] > 0:
counter += 1
In these lines of code, you increment the counter although s1_ht[ s2[start] ] was not zero before the incrementation. Let me explain with an example. Suppose s1_ht['t'] = 4. Then you find s2[start] = 't'. Therefore you increment s1_ht['t'] and set it equal to 5. But then you increment the counter which leads to an error. You shouldn't increment the counter since it already covers the character 't'. Swap that line with this:
if s1_ht[s2[start]] == 1: # just before the incrementation, it was zero
counter += 1
It passes the Leetcode test cases with 61 ms runtime and 14 MB memory on my machine.

How to determine the complexity of python code?

I need to understand the complexity of the following code. I am familiar with the concepts of all the Big O() notation and also have read a lot of blogs but I cant figure how to apply to big programs.
Following is the code for largest pallindrome number from 100 to 999:
def isPaindrome(number):
stringNum = str(number)
firstDigit_index,lastDigit_index=0,len(stringNum)-1
isPalindrome = False
while(lastDigit_index > 0 and firstDigit_index < lastDigit_index):
#print(stringNum[f],"==",stringNum[l],"......")
if(stringNum[firstDigit_index]==stringNum[lastDigit_index]):
isPalindrome = True
else:
isPalindrome = False
break
firstDigit_index = firstDigit_index + 1
lastDigit_index = lastDigit_index - 1
if(isPalindrome):
return number
else:
return 0
max = 0
startRange = 100
endRange = 999
for i in range(endRange*endRange,startRange*startRange,-1):
factors = []
result = isPaindrome(i)
if(result!=0):
for i in range(startRange,endRange+1):
if(result%i==0):
factors.append(i)
if(len(factors)>1):
sumFactor = factors[(len(factors))-1] + factors[(len(factors))-2]
mul = factors[(len(factors))-1] * factors[(len(factors))-2]
if(sumFactor>max and mul==result):
max = sumFactor
print("Largest Palindrome made from product of two 3 digit numbers(",factors[(len(factors))-1],",",factors[(len(factors))-2] ,") is", result,".")
If anyone could just make me understant step by step how to calculate I'd be grateful.
As I mentioned, your isPalindrome function is literally incorrect, as you're not changing the indexes. I changed a bit of your also, so this is the version I'm analysing. (I'm only analysing the isPalindrome function, since I actually couldn't understand what the main function is doing), sorry!
def isPalindrome(n):
num = str(n)
head, tail = 0, len(num) - 1
while tail > head:
if num[head] != num[tail]: # Not symmetrical!! WARNING!
return False
head += 1 # move position
tail -= 1 # move position
return True
This code on average is O(|n|) i.e. O(log N) where N is the number. This is because on average, the if comparison has 50% chance of breaking (returning False) and 50% of continuing. Therefore the expected number of comparisons would be |n|/4 which is O(|n|).

Python function unable to return result

Below is a function which is supposed to return longest palindromic substring of a string. Though the function itself looks alright but for some strange reason It is not returning the string. Any Idea what I am missing here?
def largest(string, repeat=None):
if len(string) <= 1 and repeat:
return repeat[max(repeat.keys())]
elif len(string) <= 1:
return string
list_str = list(string)
repeat = repeat or {}
end_index = -1
while len(list_str)+end_index:
construct = list_str[0:len(list_str)+end_index+1]
reversed_construct = construct.copy()
reversed_construct.reverse()
if construct == reversed_construct:
repeat[len(construct)] = ''.join(construct)
end_index -= 1
string = string[1:]
largest(string, repeat=repeat)
In a order to return a value from a recursive function, one must put return recursive_function(x) so that when a value is returned it is placed in a position where the data can be accessed by the function 'above' it, so to speak.
def Factorial(total,counter):
if counter == 0: #tests whether the counter is at 0
return(total) #if it is at 0 return the product of the consectutive numbers between 0 and starting counter
total *= counter #set the total to itself times the current pass counter
return Recursion(total,(counter-1)) #return the value of this function passing the total and the counter -1
You see that in this example for me to hold the value that was passed previously I have to return it so that after all the recursions are completed they will all pass the data back up the chain of function.

Finding the number of matching letters in two different string at the same indices

I am having trouble finish python code.
overlap('','hello') → 0.
I have managed to get the number back when the length of the strings match but if one of the strings has a smaller length than the other. I keep getting index out of range. Can someone help me finish this.
def overlap(string1,string2):
count = 0
for i in range(len(string1)):
for j in range(len(string2)):
if string1[i] == string2[j]:
count = count + 1
i+=1
else:
i+=1
return count
When running this with a function call. if both strings are equal it gives me the correct number, but if one is smaller or longer then its index out of range.
Thanks
Create one for loop which iterates through min(len(string1), len(string2)) and you would avoid problem when one string is smaller than another, see sample below:
def overlap(string1,string2):
count = 0
for i in range(min(len(string1), len(string2))):
if string1[i] == string2[i]:
count = count + 1
return count
print overlap('summer','winter') #2
print overlap('abcb','dbeb') #2
print overlap('summer','sum') #3
print overlap('','winter') #0
Good Luck!
Replace the nested loops and repeat only for the smaller length.
def overlap(string1, string2):
count=0;
len1= len(string1)
len2= len(string2)
smallLen= len1
if len2<len1:
smallLen= len2
for i in range(smallLen):
if string1[i]== string2[i]:
count+= 1
return count
Thinking about it in order of things that need to be done, you have to first figure out which of the two given strings have the shortest length because that will be your bound for the amount of loop iterations. In Python you can do a conditional assignment like:
maxloop = len(str1) if len(str1) <= len(str2) else len(str2)
You make the condition <= because it doesnt matter which is chosen if they're equal, so just pick the first.
Now that you have the amount of iterations you'll do, you can set up the loop and counter:
count = 0
for i in range(maxloop):
if str1[i] == str2[i]:
count += 1
The single if statement is checking the character at position i in both strings and seeing if they are equal, and if they are, then it'll add one to the overlap counter. Then simply return the count after the loop has terminated.
Try this:
count = 0
if len(string1) < len(string2):
for i in range(len(string1)):
if string1[i] == string2[i]:
count += 1
else:
for i in range(len(string2)):
if string1[i] == string2[i]:
count += 1
return count

Categories

Resources