Recursive function with alphabetical order - python

I want to define a recursive function that passes a str and returns a bool telling whether or not the characters in the parameter are in alphabetical order.
Like if I defined said sortfunc('abcdefg') it would return True; and sortfunc('banana') would return False.
How would I approach this? This is what I have so far... but I'm sort of stuck. I understand the concept of recursion but I don't know how to implement it.
def sortfunc(s):
if s == '':
return False
else:
return True if s[0] < s[1:] else False

Here's one possible method:
def is_sorted(s):
if len(s) == 1:
return True # Base case
elif s[0] <= s[1]:
return is_sorted(s[1:]) # Recursive case
else:
return False # Base case
Explanation:
So, whenever, we want to write a recursive function, we always need to think about the following:
How can I break the problem down into smaller steps?
What is the base case? (when I can stop the recursion?)
What is the recursive case? (when do I need to keep going?)
To me, the first step is always the trickiest one -- breaking the problem down. Usually, once we figure out this step, the rest falls into place.
There are usually many different ways to break a problem down, and to a certain extent, which one you pick is a bit arbitrary. In this case, I chose to break the problem down by repeatedly comparing the first two characters in the string.
If the two characters are in order, then I repeat the process, except I remove the first character. If I have only one character left in my string, or if the first two characters are out of order, I know that I can stop and return True or False respectively.
For example, if we visualize calling is_sorted('abcd'), it would look something like this:
call is_sorted('abcd')
'a' is less then 'b'
call is_sorted('bcd')
'b' is less then 'c'
call is_sorted('cd')
'c' is less then 'd'
call is_sorted('d')
only one character left, return True
return True
return True
return True
In contrast, if we tried calling is_sorted('azbc'), it would look something like this:
call is_sorted('azbc')
'a' is less then 'z'
call is_sorted('zbc')
'z' is NOT less than 'b', return False
return False
So then, here are the answers to the three steps:
How can I break the problem down into smaller steps?
Keep comparing the first two characters
What is the base case? (when I can stop the recursion?)
Either when the two characters are out of order, or if I have only one character left
What is the recursive case? (when do I need to keep going?)
If I have two or more characters left in my string.
Notice that the recursive case always requires a "leap of faith" -- you have to trust that calling the is_sorted method will accurately tell you if the rest of the string (besides the first two characters) is correctly sorted or not. It's a bit of an odd feeling -- it feels like we never explicitly told the code how to determine if the string is coded or not, or passed in any information, but it does so anyways!
However, that's part of the beauty of recursion: so long as we correctly define the base case(s) and recursive case(s), it'll magically work.

In your attempt you are missing the recursion part. Please check the following implementation.
def sortfunc(current_string, previous_character = ""):
if current_string == "":
return True # Base condition
if previous_character and previous_character > current_string[0]:
return False # Failure case
return sortfunc(current_string[1:], current_string[0]) # Recursion
If you want to know how to do this without recursion,
def sortfunc(current_string):
return "".join(sorted(current_string)) == current_string
Sample runs:
print sortfunc('abcdefg') # True
print sortfunc('banana') # False

Without less programming logic!
-> Split the string to an array and send this array to function
-> we can easily compare values by converting them to respective ascii values
sortfunc(str) {
for(int i=0;i<str.length;i++){
if ( (int) str[i] >(int) str[i+1] ) {
result = true
}
else
result = false;
return result;
}

Related

python function returns true when it should return false

I am trying to write a function to check whether a string is palindrome or not, but every string is showing as palindrome
def is_palindrome(input_string):
x=0
reverse_string = ""
while x<len(input_string):
reverse_string+=input_string[x]
x=x+1
if input_string == reverse_string:
return True
else:
return False
print(is_palindrome("abc")) # Should be False but it return True
In your code, the variabile "reverse_string" will always be equal to "input_string" since you are just appending the characters in the same order with the += operator.
A simple way to reverse a string in Python is to use slicing like that:
def is_palindrome(input_string):
if input_string == input_string[::-1]:
return True
return False
input_string[::-1] means "start from the first index to the last in the reverse order (-1)"
Your problem is in the reversal of the string. (your x is going from 0 to len(input_string)-1 but it should go the other way)
That's why it's important to break code into functions that do one and only one thing (at least in the beginning)
In this case is an overkill, but it will help you when your code grows more complex.
your function can then be simplified as:
def is_palindrome(input_string):
return input_string == reverse_string(input_string)
If you look at it is self explanatory. Is the input string equal to its reverse?
Now we need to implement the function reverse_string.
The advantage of having a function that just reverses a string is that we can do a lot of tests on it to check just this particular function
In your case, you can use negative indexes, or you can start with the index set to len(input_string)-1 and go towards 0.
But it's also a good moment to learn about string slicing and how to do things in a pythonic way, so the reverse function can be written as:
def reverse_string(input_string):
return input_string[::-1]
Feel free to put your own implementation of reverse_string if you are not yet confident with string slicing, but with this function you have separated two different things: reversing a string and checking is string is a palindrome. You can even reuse that reverse_string function later on.
Now we can test it with many cases until we are confident that it works as expected.
I'd recommend taking a look at unit tests it might seem too much for such an easy problem, but it will help you a lot in the future.
Just test what happens if you pass a palindrome, a non-palindrome, an empty string, a number, a None...

Python returns generator object without yield

I am trying to generate a function which tells me if a word is an isogram (contains duplicate values). However, this code always returns a generator object.
def is_isogram(string):
return (True if (string.lower().count(letter) == 1) else False for letter in string.lower())
I know how to solve the problem, I was just wondering what is wrong with my code.
I suppose your function is intended to return a boolean, but the return statement has an iteration happening, where each value is mapped to a boolean. The parentheses give you an iterator over those booleans. The function's description suggests that the function should return True when the input has duplicate letters, but the mapping gives True when a letter is not duplicate. So you have three problems:
The iterator
The multiple booleans, when you want one boolean
The booleans indicate the inverse of what you want to return
So your idea for an algorithm should be changed to this:
def is_isogram(string):
return any(letter for letter in string.lower() if string.lower().count(letter) > 1)
Side note: this algorithm is not efficient. More efficient is to create a set:
def is_isogram(string):
return len(set(string.lower())) < len(string)
By wrapping your returned value into parenthesis you've created a generator expression, check https://peps.python.org/pep-0289/ for details.

Part of IF statement is True, but not the whole thing

I'm doing a Codewars drill but I don't know how to solve it entirely.
Here's what I have so far
def special_number(number):
special = '012345'
strnum = str(number)
for i in strnum:
if i in special:
return "Special!!"
else:
return "NOT!!"
The number I'm struggling to get around is "39"
3 is in the special numbers list so that part is True.
9 is not.
I know that it is reading the 3 first and seeing that it's in the special numbers so its returning Special!!. But, I want it to keep going and see that 9 is not in the special numbers list so ultimately it will return "NOT!!"
Is there some small tweak that I can make so that it does do what I want?
As far as small tweak solutions goes, a common pattern is slightly counter-intuitive. Because return stops execution, we only return 'special' if none of the digits are non-special
for i in strnum:
if i not in special:
return "NOT!!"
return "Special!!"
A return will immediately stop the function. If you want to iterate all values, then one option is to use all() function
special = '012345'
def special_number(number):
global special
strnum = str(number)
return 'Special!!' if all(i in special for i in strnum) else "NOT!!"

Python Programming Multiple Choice

I was studying for a CS common exam, and I was doing a few practice tests. I couldn't understand why this question returned "=" instead of "False". I really don't understand
splitLine = aStr.split()
def mostlyLongWords(aStr, threshold):
splitLine = aStr.split()
shortCount = 0
longCount = 0
for word in splitLine:
if len(word) < threshold:
shortCount += 1
else:
longCount += 1
if shortCount > longCount:
return False
if longCount > longCount:
return True
return '='
seussLine = 'There is no one alive who is you-er than you'
print(mostlyLongWords(seussLine, 5))
a. True
b. False
c. =
d. SyntaxError:incompatible return types
e. None of the above
Assuming you've copied that faithfully, this is a trick question. There are two serious bugs in the code, that cause it to not act as expected, and you're presumably supposed to find those bugs.
What you'd like it to do is count up the number of short and long words, and return False, '=', or True depending on how they compare. Since the test sentence has 7 short words and 3 long, it should return False.
But the if checks are indented inside the for loop. That means that, instead of doing the check after all the words have been counted up, you're doing it after every single word. So as soon as there's an imbalance, 1 > 0, and therefore you're just checking whether the first word is long, not whether most of the words are long. Since 'There' is long (5 or more characters), it should return True.
But there's another mistake; The second comparison is not longCount > shortCount, it's longCount > longCount. That's obviously never going to be true. So, the program will loop until either the number of short words pulls ahead of the number of long words—in which case it will return False—or it will just fall out of the loop and return '='. In this case, as soon as you get to the word 'no', shortWords is 2, longWords is 1, therefore it returns False.
If the correct answer was supposed to be =, then either you didn't copy it faithfully, or the answer is just wrong. One possibility is that there's a third bug that you unwittingly corrected while copying the question over. For example, I notice that you've got a splitLine = aStr.split() outside the function. That's a strange thing to do, and it ought to be a NameError. But if there's a line like, say, aStr = '' somewhere earlier in the code that you haven't shown us, then you'd be setting a valid global variable named splitLine. And if there's a typo in the actual code like, say, splitline = aStr.split(), then your function would be looping over that global variable. If it were, say, ''.split(), or 'There there', then, in combination with the other two bugs, that would lead to '=' being returned.

Count occurrences of a given character in a string using recursion

I have to make a function called countLetterString(char, str) where
I need to use recursion to find the amount of times the given character appears in the string.
My code so far looks like this.
def countLetterString(char, str):
if not str:
return 0
else:
return 1 + countLetterString(char, str[1:])
All this does is count how many characters are in the string but I can't seem to figure out how to split the string then see whether the character is the character split.
The first step is to break this problem into pieces:
1. How do I determine if a character is in a string?
If you are doing this recursively you need to check if the first character of the string.
2. How do I compare two characters?
Python has a == operator that determines whether or not two things are equivalent
3. What do I do after I know whether or not the first character of the string matches or not?
You need to move on to the remainder of the string, yet somehow maintain a count of the characters you have seen so far. This is normally very easy with a for-loop because you can just declare a variable outside of it, but recursively you have to pass the state of the program to each new function call.
Here is an example where I compute the length of a string recursively:
def length(s):
if not s: # test if there are no more characters in the string
return 0
else: # maintain a count by adding 1 each time you return
# get all but the first character using a slice
return 1 + length( s[1:] )
from this example, see if you can complete your problem. Yours will have a single additional step.
4. When do I stop recursing?
This is always a question when dealing with recursion, when do I need to stop recalling myself. See if you can figure this one out.
EDIT:
not s will test if s is empty, because in Python the empty string "" evaluates to False; and not False == True
First of all, you shouldn't use str as a variable name as it will mask the built-in str type. Use something like s or text instead.
The if str == 0: line will not do what you expect, the correct way to check if a string is empty is with if not str: or if len(str) == 0: (the first method is preferred). See this answer for more info.
So now you have the base case of the recursion figured out, so what is the "step". You will either want to return 1 + countLetterString(...) or 0 + countLetterString(...) where you are calling countLetterString() with one less character. You will use the 1 if the character you remove matches char, or 0 otherwise. For example you could check to see if the first character from s matches char using s[0] == char.
To remove a single character in the string you can use slicing, so for the string s you can get all characters but the first using s[1:], or all characters but the last using s[:-1]. Hope that is enough to get you started!
Reasoning about recursion requires breaking the problem into "regular" and "special" cases. What are the special cases here? Well, if the string is empty, then char certainly isn't in the string. Return 0 in that case.
Are there other special cases? Not really! If the string isn't empty, you can break it into its first character (the_string[0]) and all the rest (the_string[1:]). Then you can recursively count the number of character occurrences in the rest, and add 1 if the first character equals the char you're looking for.
I assume this is an assignment, so I won't write the code for you. It's not hard. Note that your if str == 0: won't work: that's testing whether str is the integer 0. if len(str) == 0: is a way that will work, and if str == "": is another. There are shorter ways, but at this point those are probably clearest.
First of all you I would suggest not using char or str. Str is a built function/type and while I don't believe char would give you any problems, it's a reserved word in many other languages. Second you can achieve the same functionality using count, as in :
letterstring="This is a string!"
letterstring.count("i")
which would give you the number of occurrences of i in the given string, in this case 3.
If you need to do it purely for speculation, the thing to remember with recursion is carrying some condition or counter over which each call and placing some kind of conditional within the code that will change it. For example:
def countToZero(count):
print(str(count))
if count > 0:
countToZero(count-1)
Keep it mind this is a very quick example, but as you can see on each call I print the current value and then the function calls itself again while decrementing the count. Once the count is no longer greater than 0 the function will end.
Knowing this you will want to keep track of you count, the index you are comparing in the string, the character you are searching for, and the string itself given your example. Without doing the code for you, I think that should at least give you a start.
You have to decide a base case first. The point where the recursion unwinds and returns.
In this case the the base case would be the point where there are no (further) instances of a particular character, say X, in the string. (if string.find(X) == -1: return count) and the function makes no further calls to itself and returns with the number of instances it found, while trusting its previous caller information.
Recursion means a function calling itself from within, therefore creating a stack(at least in Python) of calls and every call is an individual and has a specified purpose with no knowledge whatsoever of what happened before it was called, unless provided, to which it adds its own result and returns(not strictly speaking). And this information has to be supplied by its invoker, its parent, or can be done using global variables which is not advisable.
So in this case that information is how many instances of that particular character were found by the parent function in the first fraction of the string. The initial function call, made by us, also needs to be supplied that information, since we are the root of all function calls and have no idea(as we haven't treaded the string) of how many Xs are there we can safely tell the initial call that since I haven't gone through the string and haven't found any or zero/0 X therefore here's the string entire string and could you please tread the rest of it and find out how many X are in there. This 0 as a convenience could be the default argument of the function, or you have to supply the 0 every time you make the call.
When will the function call another function?
Recursion is breaking down the task into the most granular level(strictly speaking, maybe) and leave the rest to the (grand)child(ren). The most granular break down of this task would be finding a single instance of X and passing the rest of the string from the point, exclusive(point + 1) at which it occurred to the next call, and adding 1 to the count which its parent function supplied it with.
if not string.find(X) == -1:
string = string[string.find(X) + 1:]
return countLetterString(char, string, count = count + 1)`
Counting X in file through iteration/loop.
It would involve opening the file(TextFILE), then text = read(TextFile)ing it, text is a string. Then looping over each character (for char in text:) , remember granularity, and each time char (equals) == X, increment count by +=1. Before you run the loop specify that you never went through the string and therefore your count for the number X (in text) was = 0. (Sounds familiar?)
return count.
#This function will print the count using recursion.
def countrec(s, c, cnt = 0):
if len(s) == 0:
print(cnt)
return 0
if s[-1] == c:
countrec(s[0:-1], c, cnt+1)
else:
countrec(s[0:-1], c, cnt)
#Function call
countrec('foobar', 'o')
With an extra parameter, the same function can be implemented.
Woking function code:
def countLetterString(char, str, count = 0):
if len(str) == 0:
return count
if str[-1] == char:
return countLetterString(char, str[0:-1], count+1)
else:
return countLetterString(char, str[0:-1], count)
The below function signature accepts 1 more parameter - count.
(P.S : I was presented this question where the function signature was pre-defined; just had to complete the logic.)
Hereby, the code :
def count_occurrences(s, substr, count=0):
''' s - indicates the string,
output : Returns the count of occurrences of substr found in s
'''
len_s = len(s)
len_substr = len(substr)
if len_s == 0:
return count
if len_s < len_substr:
return count
if substr == s[0:len_substr]:
count += 1
count = count_occurrences(s[1:], substr, count) ## RECURSIVE CALL
return count
output behavior :
count_occurences("hishiihisha", "hi", 0) => 3
count_occurences("xxAbx", "xx") => 1 (not mandatory to pass the count , since it's a positional arg.)

Categories