Question Description:
Given a number
n
, returnTrue
ifn
is in the range 1..10, inclusive. UnlessoutsideMode
is True, in which case returnTrue
if the number is less or equal to 1, or greater or equal to 10.in1to10(5, False) → **True** in1to10(11, False) → **False** in1to10(11, True) → **True**
The link to the problem is here.
Below is my first attempt. Please feel free to review it based on best practices, style and any other efficient solution.
def in1to10(n, outside_mode):
if(n>1 and n<10):
return not outside_mode
else:
return outside_mode or n is 10 or n is 1
5 Answers 5
Please feel free to review it based on best practices, style and any other efficient solution.
@mjolka already provided a more natural alternative implementation I completely agree with: following the logic precisely as in the problem statement is natural and easy to understand. I think the reason why it's easier to understand than yours has to do with the fact that the ranges being evaluated in the 2 distinct cases depending on the value of outside_mode
have an overlap on the values 1 and 10. If the two ranges were complements of each other, things would be simpler.
As for style:
if(n>1 and n<10): return not outside_mode else: return outside_mode or n is 10 or n is 1
The parentheses in the if
condition are redundant.
And PEP8 recommends to put spaces around operators, so this would be better:
if n > 1 and n < 10:
Even better is to use Python's kick-ass ... < ... < ...
operator:
if 1 < n < 10:
Be careful with using is
. In this example it works as expected, but if you try to use for non-primitive types, it might not give what you expect:
>>> [1, 2] is [1, 2]
False
>>> (1, 2) is (1, 2)
False
Unless there is a specific reason to use is
, I think you should use ==
:
return outside_mode or n == 10 or n == 1
-
\$\begingroup\$ It's not just non-primitive types: Python "is" operator behaves unexpectedly with integers \$\endgroup\$Janne Karila– Janne Karila2014年10月17日 08:48:43 +00:00Commented Oct 17, 2014 at 8:48
The logic is confusing. A direct translation of the problem specification is possible, and clearer.
Let's deal with the first half of the problem:
Given a number \$n\,ドル return
True
if \$n\$ is in the range \1ドル ..10\,ドル inclusive.
Then it's natural to write:
def in1to10(n):
return 1 <= n <= 10
Now we can deal with the second half:
def in1to10(n, outside_mode):
if outside_mode:
return n <= 1 or n >= 10
return 1 <= n <= 10
-
\$\begingroup\$ Well you could do this but I tried to use python's verbose mode for high level translation, too many logical operators make it more confusing, don't you think? \$\endgroup\$Anirudh– Anirudh2014年10月17日 05:46:12 +00:00Commented Oct 17, 2014 at 5:46
-
\$\begingroup\$ The logical operators in the original code:
and
,not
,or
,or
= 4. In this answer:or
= 1. So, not sure what you mean... \$\endgroup\$janos– janos2014年10月17日 05:55:49 +00:00Commented Oct 17, 2014 at 5:55 -
\$\begingroup\$ I meant <=, >= mainly, where is =4 btw? :-s \$\endgroup\$Anirudh– Anirudh2014年10月17日 05:59:56 +00:00Commented Oct 17, 2014 at 5:59
-
2\$\begingroup\$ janos means that there are 4 logical operators in the original code. In mjolka's answer there are only 1 (
or
). \$\endgroup\$jsanc623– jsanc6232014年10月17日 06:10:13 +00:00Commented Oct 17, 2014 at 6:10 -
\$\begingroup\$ sorry I meant relational operators, my bad!! \$\endgroup\$Anirudh– Anirudh2014年10月17日 06:13:36 +00:00Commented Oct 17, 2014 at 6:13
Questions like this generally involve working out how to understand boolean operations. There is a difference between that understanding, and making things readable, but, your solution is:
def in1to10(n, outside_mode): if(n>1 and n<10): return not outside_mode else: return outside_mode or n is 10 or n is 1
I don't find that to be particularly horrible to read, but I think it is missing the point of whatever lesson you are supposed to be learning.
I actually prefer the suggestion from @mjolka):
def in1to10(n, outside_mode): if outside_mode: return n <= 1 or n >= 10 return 1 <= n <= 10
because it makes the 'flag' the logical differentiator. If it was me, I would write it @mjolka's way
On the other hand, the exercise is probably trying to teach you that you can !=
two boolean values as an XOR operation (or alternatively use ==
as a NOT-XOR operation). Consider the following two boolean variables: old
and working
:
old != working
is true when you're old
and not working
, or working
and not old
. It is false when you're old
and working
, or you're not old
and not working
. Since young people are supposed to be working, and old people are supposed to be retired, and assuming that people are happy in these states, then you could say:
happy = old != working
How does this relate to your problem?
Well, consider the following function:
def in1to10(n, outside_mode):
return n is 10 or n is 1 or (outside_mode != (1 < n < 10))
But, the line:
return n is 10 or n is 1 or (outside_mode != (1 < n < 10))
is probably the better way to do it all as a single boolean expression rather than the (more readable?) if-statement.
When I run that in this program:
#!/usr/bin/python
def in1to10(n, outside_mode):
return n is 10 or n is 1 or (outside_mode != (1 < n < 10))
for i in range(-5, 15):
print('input {:3d} inside {:5s} outside {:5s}'
.format(i, str(in1to10(i, False)), str(in1to10(i, True))))
I get the output:
input -5 inside False outside True input -4 inside False outside True input -3 inside False outside True input -2 inside False outside True input -1 inside False outside True input 0 inside False outside True input 1 inside True outside True input 2 inside True outside False input 3 inside True outside False input 4 inside True outside False input 5 inside True outside False input 6 inside True outside False input 7 inside True outside False input 8 inside True outside False input 9 inside True outside False input 10 inside True outside True input 11 inside False outside True input 12 inside False outside True input 13 inside False outside True input 14 inside False outside True
Note: What I am trying to say is that even though the boolean logic XOR is what the exercise probably wants, I would still write it with an if-statement (like @mjolka), but you still need to understand how the boolean XOR would work.
Solution
Python supports double-ended inequalities. To implement just the first part, write
def in1to10(n):
return 1 <= n <= 10
Adding support for outsideMode
...
def in1to10(n, outsideMode):
if outsideMode:
return not(1 < n < 10)
else:
return 1 <= n <= 10
Unfortunately, outsideMode
isn't not(1 <= n <= 10)
, so you can't do anything clever with XOR, like
# Wrong!
def in1to10(n, outsideMode):
return outsideMode ^ (1 <= n <= 10)
(Well, you could, but the added complication is not worth it.)
Style notes
In Python, it is conventional to omit parentheses for simple if
conditions. It is also more common to use lower_case_with_underscores
for parameter and local/instance variable names. See examples in PEP8.
CodingBat is inconsistent in the naming: it uses outsideMode
in the question, and outside_mode
in the text area.
It seems that your original code does not work correctly, as taking your code:
def in1to10(n, outside_mode):
if(n>1 and n<10):
return not outside_mode
else:
return outside_mode or n is 10 or n is 1
and calling it in this manner, with the expected output in the comment next to the func call:
print in1to10(-1, False) # → **False**
print in1to10(-1, True) # → **True**
print in1to10(1, False) # → **True**
print in1to10(1, True) # → **False**
print in1to10(10, False) # → **True**
print in1to10(10, True) # → **False**
print in1to10(5, False) # → **True**
print in1to10(5, True) # → **False**
print in1to10(11, False) # → **False**
print in1to10(11, True) # → **True**
print in1to10("adsf", "Asdf") # False
produces these responses (output → expected_output):
False → **False**
True → **True**
True → **True**
True → **False**
True → **True**
True → **False**
True → **True**
False → **False**
False → **False**
True → **True**
Asdf → **False**
Notice that your original answer does not catch nor raise an error when encountering a string val.
I've reworked your code to this:
def in1to10(n, outside_mode=False):
retval = True if outside_mode == False else False
return retval if 1 <= n <= 10 else not retval
which does the following:
- It defaults outside_mode to False, so that we can omit it and only give it a number to check if its within the range
- Checks if n is within a range elegantly
- Uses the retval var as a flip switch boolean
- Handles strings and outputs False if its a string
- Correctly outputs the expected output
This is the output of my version of the func (using the same calls and expected output as above in the original call) (output → expected_output):
False → **False**
True → **True**
True → **True**
False → **False**
True → **True**
False → **False**
True → **True**
False → **False**
False → **False**
True → **True**
False → **False**
-
3\$\begingroup\$ The specification makes it quite clear that the numbers 1 and 10 are in range in both modes. \$\endgroup\$Janne Karila– Janne Karila2014年10月17日 07:24:00 +00:00Commented Oct 17, 2014 at 7:24
-
\$\begingroup\$ Good point...in my defense, this was written up at 2am :) \$\endgroup\$jsanc623– jsanc6232014年10月17日 15:36:43 +00:00Commented Oct 17, 2014 at 15:36
-
\$\begingroup\$ hey take some rest.. \$\endgroup\$Anirudh– Anirudh2014年10月19日 15:03:04 +00:00Commented Oct 19, 2014 at 15:03
Explore related questions
See similar questions with these tags.