similar code logic, two different answers - python

why does the output of these two functions give different outputs when the logic or idea is the same and they are working with the same string?
def solution(inputString):
a = ""
b = a[::-1]
if a == b:
return True
else:
return False
print(solution("az"))
def ans(something):
if something == reversed(something):
print(True)
else:
print(False)
ans('az')

This is I think because you are not using your inputString parameter in the function solution(). This may be closer to what you want:
def solution(inputString):
a = inputString
b = a[::-1]
if a == b:
return True
else:
return False

when the logic or idea is the same
No, the solution and ans functions have different logic.
solution uses the common way of reversing a string, thats fine
However, the second function uses reversed() function, which does:
reversed(seq)
Return a reverse iterator. seq must be an object which has a __reversed__() method or supports the sequence protocol ...
It does not return the reversed string as you'd probably expected.
To put that in perspective, the following code returns False:
print("oof" == reversed("foo"))
Because the return value of reversed("foo") is an <reversed object> and not the reversed String.

Related

Proper Subset function in Python

I want a function that will say if a subset is proper. So if they are identical it will return True, if they aren't then False. I have a very simple design but it doesn't account for the set's properties, which is if there are duplicates in the set it will delete them. It will also be identifical if one set is IN the other set.
Here's my code:
def proper_subset(S,T):
if S == T:
return True
else:
return False
Here's some test cases on what it does and what it SHOULD do:
#What it does
S = {1,2}
T = {1,2,3}
proper_subset(S,T)
>>> False
#What it should do
S = {1,2}
T = {1,2,3}
proper_subset(S,T)
>>> True
Please help!
In python the set entity supports addition and subtraction. So you can just check the lengths of the subtraction operations.
def properSubset(S,T):
return len(S-T)==0 and len(T-S)>0
Also as the comments mention you can just use '<'
def properSubset(S,T):
return S<T

Mapping a Boolean function over a list

I'm new to programming so this is probably a silly question!
I'm trying to write a function that takes a list of letter grades and returns a Boolean true or false depending on whether it is a passing grade
## Calculate total units passed
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
else:
if letterGrade == 'NCN':
passed = False
else:
if letterGrade == 'WN':
passed = False
else:
True
return passed
unitsPassed = map(unitPassed,courseGradeLetter)
I've attempted to do this by creating a function that tests if a grade is a passing grade, and then map this over a list of grade.
The problem is that I get the following error for a list that contains more than one element:
local variable 'passed' referenced before assignment
If I try it with a list containing one element I get the correct result.
Any ideas why this is?
Thanks.
--
Thanks everyone, your answers have helped me a lot!
Some have already pointed your error and posted the most pythonic solutions, but anyway - here's another code review, but this time a step by step one:
First point: learn to use elif instead of nesting if clauses in else clauses:
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
elif letterGrade == 'NCN':
passed = False
elif letterGrade == 'WN':
passed = False
else:
passed = True
return passed
As you can see this is already more readable.
Second point: in Python we favor "early returns" - ie, in this kind of tests, instead of setting a variable in all branches and returning it at the end, we return directly (which avoids elif/else chains etc):
def unitPassed(letterGrade):
if letterGrade == 'N':
return False
if letterGrade == 'NCN':
return False
if letterGrade == 'WN':
return False
return True
Which makes the code even more straightforward.
And of course the last refactoring is to avoid the multiple tests when possible, as posted by Dadep and digitake (but using a tuple instead of a list because we dont need the overhead of a list here):
def unitPassed(letterGrade):
return letterGrade not in ("N", "NCN", "WN")
Also, you are using map() in your code snippet but while map() is still perfectly valid and appropriate, the more idiomatic (and marginally faster) version here would be a list comprehension:
passed = [unitPassed(letter) for letter in courseGradeLetter]
And since unitPassed is now basically a simple short expression, you can just inline it (unless of course you need this function elsewhere):
passed = [letter not in ('N', 'NCN', 'NWN') for letter in courseGradeLetter]
how about this
def unitPassed(letterGrade):
return letterGrade not in ['N', 'NCN', 'WN']
unitsPassed = map(unitPassed,courseGradeLetter)
you can redefine your function as :
>>> def unitPassed(letterGrade):
... GP=['N', 'NCN', 'WN']
... if letterGrade in GP:
... return False
... return True
...
>>> letterGrade='DE'
>>> unitPassed(letterGrade)
True
>>> letterGrade='NCN'
>>> unitPassed(letterGrade)
False
The error is in the 3rd else statement, i.e. in line 13.
Change True to passed = True
Also, you can make your function clean,
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
elif letterGrade == 'NCN':
passed = False
elif letterGrade == 'WN':
passed = False
else:
passed = True
return passed

Python Identifying Suffix within set of strings

doing an exercise on CheckIO and I'm wondering as to why this won't work. Given a set of strings, I'm trying to return True if any of the strings are suffixes of any other string in the set. False otherwise. Using itertools I'm generating the necessary permutations in tuples first. Then for each tuple (each i), I wanted to see the hard way if the second tuple was in the end of the first tuple (option1). The otherway was using the .endwith function (option2), but neither will work for me. Why are these two options flawed?
import itertools
def checkio(words_set):
for i in itertools.permutations(words_set, 2):
#option1 ---- if i[1] in i[0][-len(i[1]):]:
#option2 ---- if i[0].endswith(i[1]):
return True
else:
return False
examples:
checkio({"hello", "lo", "he"}) == True
checkio({"hello", "la", "hellow", "cow"}) == False
I know this works as an answer. But just wondering why my original methods wouldn't take.
def checkio(words_set):
for w1 in words_set:
for w2 in words_set:
if w1.endswith(w2) and w1 != w2:
return True
return False
Your return False should be at the end of the for loop, otherwise the function will return True/False at every first comparison and will ignore all subsequent comparisons:
import itertools
def checkio(words_set):
for i in itertools.permutations(words_set, 2):
if i[0].endswith(i[1]):
return True
return False
Since it's an exercise, I won't give you the full answer, but are you sure that you really want to return False in the else clause?
Its because you return False right after the first check. and if it fails it will returns False you need to put it out of your for loop!
But as a more pythonic way you can use combinations and a generator expression within any function :
>>> from itertools import combinations
>>> s={"hello", "lo", "he"}
>>> any(i.endswith(j) or j.endswith(i) for i,j in (combinations(s,2)))
True
>>> s2={"hello", "la", "hellow", "cow"}
>>> any(i.endswith(j) or j.endswith(i) for i,j in (combinations(s2,2)))
False

Int conditional always returning true? Python

I have a function called check defined like so
def check(n):
if n > 17325551999:
return True
return False
which is always returning true. eg
>check(1000000000)
True
>check(5)
True
Can anyone give me some insight as to why this is happening? Is it because the number is larger than the largest possible int?
edit: I've added a picture of my python prompt.
Updated answer:
From your screenshot it is clear you didn't post the same code here as what you are actually running:
def check(num):
if n > 17325551999:
return True
return False
either raises a NameError for 'n' or tests n as a global if it is defined. The actual parameter to the function is called num, and is completely ignored in the function.
In other words, you'd have to assign to the n global to make your version work.
The fix is to test the right parameter:
def check(num):
return num > 17325551999
Previous answer before the screenshot was posted:
You are not passing in integers. With integers your code works just fine:
>>> def check(n):
... if n > 17325551999:
... return True
... return False
...
>>> check(5)
False
Instead you are probably passing in strings instead:
>>> check('5')
True
In Python 2, numbers always sort before strings (a mistake remedied in Python 3), so any number is always going to be 'smaller' than a string:
>>> '0' > 0
True
Avoid this problem by making sure your function is called with an integer argument, or explicitly convert n in the function:
def check(n):
return int(n) > 17325551999:
Note that the > operator already returns True or False, no need to use if here.

python - Not sure if recursive or not

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))

Categories

Resources