I'm going through a basic python exercise, stumbled upon this query.
Given a non-negative number "num", return True if num is within 2 of a multiple of 10.
Here's the my solution:
def near_ten(num):
return (num % 10) in range(8, 10) or (num % 10) in range(0, 3)
It shows "All Correct", but I'm feeling like my code is bit digressive as I have hard-coded the "numbers within 2 of a multiple of 10".
Can one please review this line if its the right approach?
2 Answers 2
I would suggest you to go further in hard coding those values: I mean I would write:
def is_near_ten(num):
return (num % 10) in [0, 1, 2, 8, 9]
You can see visually the difference (less instructions) and you can confirm that:
>>> import timeit
>>> timeit.timeit('(128 % 10) in [0, 1, 2, 8, 9]')
0.23481132300003082
>>> timeit.timeit('(128 % 10) in range(8, 10) or (128 % 10) in range(0, 3)')
1.3901589560000502
You can notice that further hard coding those values as suggested makes your function more than 5 times faster.
-
1\$\begingroup\$ Of-course, in proper code, you'd move those hardcoded values to PSEUDO_CONSTS. \$\endgroup\$2017年11月28日 11:50:10 +00:00Commented Nov 28, 2017 at 11:50
-
4\$\begingroup\$ While a perfectly valid answer, I disagree with hardcoding the distances as a
list
. I think it would make more sense if one could dynamically set the 'close' value, e.g.is_near(number, limit)
. \$\endgroup\$Daniel– Daniel2017年11月28日 11:50:13 +00:00Commented Nov 28, 2017 at 11:50
A hard-coded solution without lists:
def near_ten(num):
return ((num%10) <= 2) or ((num%10) >= 8)
A generalized version, as some commenters asked for:
def near_num(num,mult,diff):
return ((num%mult) <= diff) or ((num%mult) >= (mult-diff))
def near_ten(num):
return near_num(num,10,2)
The times I got for this were: (using existing answers to compare against)
>>> import timeit
>>> timeit.timeit('(128%10) in range(0,3) or (128%10) in range(8,10)')
0.5436179637908936
>>> timeit.timeit('(128%10) in [0,1,2,8,9]')
0.15247392654418945
>>> timeit.timeit('(128%10) <= 2) or ((128%10) >= (10-2))')
0.11723899841308594
So, it seems a little faster than even the hard-coded list.
I thought about adding a variable to store the value of (num%mult)
, but figure that a smart compiler should automatically put that in a temporary variable for reuse.
-
\$\begingroup\$ I thought about adding a variable to store the (num%mult), but figure that a smart compiler should automatically put that in a temporary variable for reuse. So, I am curious as to opinions on how that would affect speed, memory, and (most importantly to me) readability. \$\endgroup\$Ghost8472– Ghost84722017年11月28日 16:46:38 +00:00Commented Nov 28, 2017 at 16:46
-
2\$\begingroup\$ I added the context from your comment in your post - Refer to the section When shouldn't I comment? on Comment everywhere. You could potentially post a new question if you have working code, and reference this post... \$\endgroup\$2017年11月28日 16:49:29 +00:00Commented Nov 28, 2017 at 16:49
-
\$\begingroup\$ @SamOnela thanks for linking to that article on commenting, I hadn't seen it yet. I went back and forth on whether to edit my post, or add a comment. I think I can argue my comment was part of "Add relevant but minor or transient information to a post" because my comment addresses an alternative style to what I advocated. I fixed your edit, as it broke the context of my post. \$\endgroup\$Ghost8472– Ghost84722017年11月28日 17:09:34 +00:00Commented Nov 28, 2017 at 17:09
-
\$\begingroup\$ okay- sorry about that. \$\endgroup\$2017年11月28日 17:10:59 +00:00Commented Nov 28, 2017 at 17:10
-
\$\begingroup\$ @SamOnela thank you. Sorry I was being snippy. I do think you are right that my comment should have been part of the post. Also, thank you for pointing out the context issues, and I will try to avoid asking new questions in my answers/comments. \$\endgroup\$Ghost8472– Ghost84722017年11月28日 17:20:43 +00:00Commented Nov 28, 2017 at 17:20
return ((num + 2) % 10) in range(0, 5)
orreturn ((num + 2) % 10) < 5
\$\endgroup\$