First off, this IS homework, so I am not expecting any direct answers. I need to take two strings defined by a function (semordnilap(str1, str2)) and I need to see if they are equal when one is reversed. I was wondering if I can call these separately out of the function with semordnilap(str1[0:1) == semordnilap(str2[-1]) I tried this a few ways and I must not be thinking about it correctly, plus of course there is the kicker of trying to do this recursively. Any advise or direction would be helpful.
def semordnilap(str1, str2):
'''
str1: a string
str2: a string
returns: True if str1 and str2 are semordnilap
False otherwise.
'''
if len(str1) != len(str2):
return False
if len(str1) <= 1 or len(str2) <= 1:
return False
if semordnilap(str1[0]) != semordnilap(str2[-1]):
return False
else:
return True
This is what I have so far, getting error of TypeError: semordnilap() takes exactly 2 arguments (1 given)
Given two strings str1 and str2, the easiest way to compare if one is equal to the reverse of the other is by using slicing:
str1 = 'racecar'
str2 = 'racecar'
str1 == str2[::-1]
Out[57]: True
Which is really just checking if str1 is a palindrome (i.e. a reverse of itself).
If you really want to use recursion, you also want to be using slicing: check if str1[0] == str2[-1], and then recursively call your function on str1[1:] and str2[:-1].
The [::-1] syntax is extended slicing syntax, which is valid for strings as well as lists and other sequences.
To reverse a string you use 'this is a string'[::-1].
[::-1] Is slice notation which says include everything from the start to the end of the string but do it in reverse.
'abcdefghijk'[6:1:-2] outputs 'gec' because it goes from the 6th index (starting with 0) up to but not including the first index, in reverse steps of 2.
Read up more on slice notation:Explain Python's slice notation, http://docs.python.org/2.3/whatsnew/section-slices.html
def semordnilap(str1, str2):
if str1 == str2[::-1]: return True
else: return False
One way to do it recursively:
def semordnilap(str1, str2):
if not (len(str1) or len(str2)): return True
if not (len(str1) and len(str2)): return False
if str1[0] != str2[-1]: return False
return semordnilap(str1[1:], str2[:-1])
The first line checks if both strings are empty (0 evaluates to False, any other number is True). len(str1) returns the length as an integer.
Then it checks if only one of the strings is empty in which case they are not equal.
Then it checks if the first letter is the same as the last letter.
Then it repeats the process with the each string (minus the first letter of str1 and minus the last letter of str2). It goes until one of the base cases is reached. The base case is what is returned. So it will only return True when then first letter was equal to the last letter each round until both strings ran out of characters at the same time.
Related
write a function that takes as an argument a list and a string, and returns a boolean based on whether or not all the letters in the string appear somewhere in the list.
my_function(["hello","world"],"hold")
should return True
and
my_function(["hello","world"],"down")
should return False
This function will take in the input arr and string and compute, as you would expect. To explain the code, I start by building an 'index' to compare against, I called it, di. From there I loop through every character of every string inside of arr. From there, if they are all true, then return true, otherwise false. As for how that comparison was written (all(di[key] for key in di) it builds a true and false tuple and then all checks if all items in the list-like item are true.
def my_function(arr,string):
di = {c:False for c in string}
for value in arr:
for character in value:
if character in di:
di[character] = True
return all(di[key] for key in di)
I was looking for a way to write code that checks whether a certain string is a part of another string. I understand that it is easy to do when we have numbers, but I don't know how to do it with strings.
For example, I have this function
a = is_part("motherland", "land")
I need to know that "land" is a part of the word "motherland" (return True or False). Is it possible to check this?
UPDATE: How can I create a restriction when the second word always has to be in the end of the first one. For example, in case when I check whether "eight" is a part of "eighteen" it returns False because "eight" is not at the end of the first word
This should help:
>>> "land" in "motherland"
True
>>> "banana" in "motherland"
False
Here is a function that determines whether a string target is contained within another string some_string.
def is_part(some_string, target):
return target in some_string
>>> is_part('motherland', 'land')
True
>>> is_part('motherland', 'father')
False
>>> is_part('motherland', '')
True
If you don't like an empty string returning true, change the return statement to
return (target in some_string) if target else False
If, on the other hand, you need to implement it yourself:
def is_part(some_string, target):
if target:
target_len = len(target)
for i in range(len(some_string)):
if some_string[i:i+target_len] == target:
return True
return False
NUMBERS = "123456789"
def digit_checker(x):
for t in x:
if t in NUMBERS:
y = True
else:
y = False
return y
sentence = input("Enter a string to check if its all digits: ")
checker = digit_checker(sentence)
print(checker)
As the title states, how would I find if the string has all digits without using the str.isdigit or a try/except. The code keeps checking the first character and not all. How do I fix that?
NUMBERS = "123456789"
def digit_checker(x):
y = True
for t in x:
if t not in NUMBERS:
y = False
return y
You can use all and a generator expression:
NUMBERS = "1234567890"
def digit_checker(x):
return all(t in NUMBERS for t in x)
This will go through each character in x and see if it is in NUMBERS. If not, all will immediately stop checking and return False. Otherwise, it will return True after it has confirmed that every character is a digit. Below is a demonstration:
>>> NUMBERS = "1234567890"
>>> def digit_checker(x):
... return all(t in NUMBERS for t in x)
...
>>> digit_checker('12345')
True
>>> digit_checker('12345a')
False
>>>
Note too that it would be more efficient if you made NUMBERS a set:
NUMBERS = set("1234567890")
That way, t in NUMBERS will perform an O(1) (constant) hash lookup rather than an O(n) (linear) search through the string. Granted, on strings this small, the performance impact of the linear search is not too worrisome. However, that will quickly change whenever you are working with larger strings.
Actually, it looks like it is checking every character, but because it sets y for every character, it is the "numberless" of the last character that determines the value returned, regardless of what the other characters are.
Instead, you should initialize y to True, and only set it to False if you ever find a non-number. In fact, when that happens, you can immediately return.
If you are chefcking for the fact that all the letters are numbers, you can try the following expression:
def digit_checker(x):
return all( t in NUMBERS for t in x )
It is exactly the same as your code except it will also check whether all the characters within x are numbers. This is what has been missing in your code. The return value is always overwritten by the last check. Of course, using a loop and breaking out might be more efficient unless all does that internally for the generator expression, in which case the two are exactly equivalent.
NUMBERS = "1234567890" # Did you miss the 0?
def digit_checker(x):
all_digits = True
for t in x:
if t not in NUMBERS:
all_digits = False
break
return all_digits
A different approach would be to check them as sets:
def digit_checker(x):
return True if set(x).difference(set(NUMBERS)) == set() else False
Perhaps if you clear up the variable names the problem will be more clear:
def digit_checker(sentence):
is_number = True
for character in sentence:
if character in NUMBERS:
is_number = True
else:
is_number = False
return is_number
As you can see, you are evaluating if it is a number for each character, and changing the is_number variable each time. So, only the last character will result in proper evaluation.
You probably want to just return False when a non-digit is first detected. Try if character not in NUMBERS set is_number to False and break the loop.
There are some good answers to do that. Here's another way to do it. You can count the number of characters that are not digits, by storing them in a list, the length of this list should be zero.
NUMBERS = "1234567890"
def digit_checker(x):
return len([t for t in x if t not in NUMBERS]) == 0
print digit_checker('123') #True
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Right now I'm trying to use recursion of a function with two parameters to find whether or not the second is included in the first. As an example:
def recurseString(full, inclusive):
...............
With this I would take something along the lines of:
recurseString('jack','kcj')
and this would return "True" whereas something like:
recurseString('stan','xun')
would return "False"
I'm rather new to python so this is rather confusing. Any ideas on how to go about this problem?
I am guessing that you are looking for ...
In [51]: def recurseString(a,b):
....: if b == '': return True
....: else:
....: if len(b) == 1: return b in a
....: else: return (b[0] in a) and recurseString(a, b[1:])
....:
In [52]: recurseString('jack', 'kjc')
Out[52]: True
In [53]: recurseString('stan', 'xun')
Out[53]: False
However, there is no need for recursion. This is much better solved using all like so:
In [57]: all( [s in 'jack' for s in 'kjc'] )
Out[57]: True
which is far more Pythonic.
It is also possible to use reduce which is more functional but much less readable, since Python has much better ways of handling this.
In [60]: reduce(lambda x,y: (x and (y in 'jack')) , 'kjc', True)
Out[60]: True
Finally, this wouldn't be complete without using the set notation:
In [65]: (set('kjc') - set('jack')) == set()
Out[65]: True
So as you can see, the recursive version is the least suitable for this problem!
This will return True even if there are duplicate letters in inclusive but but only one in full:
def recurseString(full, inclusive):
if not inclusive:
return True
return inclusive[0] in full and recurseString(full, inclusive[1:])
>>> print recurseString('jack','kkkcccjjj')
True
The following requires full to contain the same number of duplicate letters - if inclusive has three k's full must have three k's:
def recurseString(full, inclusive, first_call = True):
# first time through, sort the arguments to make the algorithm easier
if first_call:
full, inclusive = map(sorted, (full, inclusive))
first_call = False
# two base cases, inclusive has been exhausted
if not inclusive:
return True
try:
index = full.index(inclusive[0])
except ValueError:
# and (2nd base case) first item of inclusive is not in full
return False
return recurseString(full[index+1:], inclusive[1:], first_call)
>>> print recurseString('jack','kkkcccjjj')
False
>>> print recurseString('jckackjkjc','kkkcccjjj')
True
>>>
Using the index method seemed like cheating -
def foo(full, inclusive, first_call = True):
if first_call:
full, inclusive = map(sorted, (full, inclusive))
if not full and inclusive:
return False
if not inclusive:
return True
if inclusive[0] == full[0]:
inclusive = inclusive[1:]
return foo(full[1:], inclusive, False)
assert not foo('','kkkcccjjj')
assert not foo('sun','xun')
assert not foo('jack','kkkcccjjj')
assert foo('s', 's')
assert foo('jckackjkjc','kkkcccjjj')
assert foo('','')
assert foo('a','')
To think about any problem recursively, you have to break it into a base case (or sometimes multiple base cases), and a recursive case (or sometimes multiple recursive cases).
I'm going to assume that "included by" means "each character in inclusive is also in full, and in fact each character that appears in inclusive N times is also in full at least N times".
So, if inclusive is empty, it's vacuously True.
But if the full is empty and inclusive is not, it's False.
Otherwise, if the first character of full is in inclusive, it's true iff full[1:] contains inclusive minus that character.
Otherwise, it's true iff full[1:] contains inclusive.
Now you just have to translate that to code.
If you don't need to handle repeated characters, you can simplify this by just testing inclusive[0] and recursing on inclusive[1:], instead of recursing on full[1:].
def recurseString(str1,str2):
if str2 == "": # str2 == "" all str2 letters are in str1
return True
elif str2[0] in str1:
return recurseString(str1, str2[1:]) # move to next letter in str2
return False # if we get here we have found a letter that is not in str1
In [22]: recurseString('stan','xun')
Out[22]: False
In [23]: recurseString('jack','kcj')
Out[23]: True
I don't know why you need recursive to implement it, it's difficult to read and understand.
MY GOD, It's a challenge for me to read my code.
def recurseSring(full, inclusive):
for i in range(len(full)):
for j in range(len(inclusive)):
if full[i] == inclusive[j]:
if recurseSring(full[i + 1:], inclusive[j + 1:]):
return True
if full[i] == inclusive[j] and len(inclusive) == 1:
return True
return False
if __name__ == "__main__":
if recurseSring('lifenglifeng001', 'lifeng'):
print('OK, equal')
else:
print('NOT equal')
Short but sweet.
def recurseString(full, incl):
return incl[:1] in full and (incl[:1] == '' or recurseString(full, incl[1:]))
The 'and' ensures both parts of the expression are true.
The first part - takes the first character of inclusive and searches for it in the full string:
incl[:1] in full #returns '' if incl is ''
The second part - this is true if you search with a null string (incl), have come to the end of incl OR if the recursive call is true called with the tail of incl used as the second arg:
incl[:1] == '' or recurseString(full, incl[1:])
#null check is first to prevent overflow
There's a simple approach for this without recursion: create two sets with the strings you want and check if one set is inside the other one.
def contains(text, chars):
textset = set(text)
charset = set(chars)
return charset.issubset(textset)
print contains("jackie", "ice") # True
print contains('jack','kcj') # True
print contains('stan','xun') # False
def func_palindrome(stri):
if len(stri) == 0 or 1:
return True
if stri[0] != stri[-1]:
return False
return func_palindrome(stri[1:-1])
I'm not sure if this function, that checks if the string is a palindrome can be considered as a recursive code or not. That becuase I can simply change the last return value from return func_palindrome(str[1:-1]) to True and nothing will change
Your issue is here:
if len(str) == 0 or 1 :
should be
if len(str) == 0 or len(str) == 1:
By just doing if len(str) == 0 or 1 it is evaluating to True always as it is interpreted as (len(str) == 0) or 1
Also, I would rename str to something else, as str is a builtin type
Any function that calls itself is technically a recursive function.
Any function that checks its arguments for a "base case", and otherwise calls itself with a "smaller" version of its arguments, is a usefully recursive function.
Of course a recursive function can still be broken, or even pointless. For example, consider this function:
def recursive_length(a):
if not a:
return 0
return 0 + recursive_length(a[1:])
My stupid bug in the last line doesn't mean this is not a recursive function. I'm recursively summing up N copies of the number 0, instead of N copies of the number 1, so I could have done the same thing by just writing return 0. But that's just because the sum of N copies of 0 is always 0, not because my function fails to be recursive.
So, what if there were a problem in the base case?
def recursive_length(a):
if a is not None:
return 0
return 1 + recursive_length(a[1:])
Now, it never actually recurses… but it's still a recursive function. It's just a recursive function with a bug in the base case.
You don't need to do this recursively, but you can, particularly if you don't mind a lot of extra space and poor performance for long strings.
Here are two nonrecursive ways:
#!/usr/bin/python3
def is_palindrome1(string1):
string2_list = list(string1)
string2_list.reverse()
string2 = ''.join(string2_list)
return string1 == string2
def is_palindrome2(string):
len_string = len(string)
for index in range(len_string // 2):
character1 = string[index:index+1]
character2 = string[len_string-index-1:len_string-index]
if character1 == character2:
# This character is good
pass
else:
return False
# all characters matched
return True
for string in [ '393', '339', 'aibohphobia', 'aibobphobia' ]:
assert is_palindrome1(string) == is_palindrome2(string)
print(is_palindrome1(string))
print(is_palindrome2(string))