From time to time I practice my python skills in codewars. What I like about it is the clever solutions some people come up with. Let’s look at some examples where I learned some useful tricks.
Is Integer Array? (6 kyu)
This sounds like an easy one. Here is the task:
Write a function with the signature shown below:
def is_int_array(arr):
return True
returns true
/ True
if every element in an array is an integer or a float with no decimals.
returns true
/ True
if array is empty.
returns false
/ False
for every other input.
I assumed this was an easy one-liner, something like
def is_int_array(arr):
return all([i.is_integer() for i in arr if i not isinstance(i, int)])
or something like this. However, I did not consider all the edge cases:
test.assert_equals(is_int_array([]), True, "Input: []")
test.assert_equals(is_int_array([1, 2, 3, 4]), True, "Input: [1, 2, 3, 4]")
test.assert_equals(is_int_array([-11, -12, -13, -14]), True, "Input: [-11, -12, -13, -14]")
test.assert_equals(is_int_array([1.0, 2.0, 3.0]), True, "Input: [1.0, 2.0, 3.0]")
test.assert_equals(is_int_array([1, 2, None]), False, "Input: [1,2, None]")
test.assert_equals(is_int_array(None), False, "Input: None")
test.assert_equals(is_int_array(""), False, "Input: ''")
test.assert_equals(is_int_array([None]), False, "Input: [None]")
test.assert_equals(is_int_array([1.0, 2.0, 3.0001]), False, "Input: [1.0, 2.0, 3.0001]")
test.assert_equals(is_int_array(["-1"]), False, "Input: ['-1']")
I didn’ know that 1.is_integer()
returns a SyntaxError
, for example.
My actual solution covers all edge cases:
def check_array(arr):
# check if array is empty array
if arr == []:
return True
# check if array is None or empty string
if not arr:
return False
# loop through each element in array
for element in arr:
# check if element is an integer or a float with no decimals
if not (isinstance(element, int) or (isinstance(element, float) and element.is_integer())):
# return False if not
return False
# return True if all elements pass the check
return True
This solution works, but it’s not pretty.
Let’s look at other peoples’ solutions. I like this one because it’s short:
def is_int_array(arr):
try:
return list(map(int, arr)) == arr
except:
return False
However, many developers hate try
/except
blocks. In addition, this solution creates a new list by mapping each element to an integer.
This may not be very efficient.
The most upvoted solution is this one:
def is_int_array(a):
return isinstance(a, list) and all(isinstance(x, (int, float)) and x == int(x) for x in a)
It’s clever because it immediately returns False
if arr
is not a list, saving computation.
It also early stops if it finds a False
value in the loop. And, it’s a one-liner!
Elevator Distance (7 kyu)
Imagine you start on the 5th floor of a building, then travel down to the 2nd floor, then back up to the 8th floor. You have travelled a total of 3 + 6 = 9 floors of distance.
Given an array representing a series of floors you must reach by elevator, return an integer representing the total distance travelled for visiting each floor in the array in order.
// simple examples
elevatorDistance([5,2,8]) = 9
elevatorDistance([1,2,3]) = 2
elevatorDistance([7,1,7,1]) = 18
// if two consecutive floors are the same,
//distance travelled between them is 0
elevatorDistance([3,3]) = 0
Array will always contain at least 2 floors. Random tests will contain 2-20 elements in array, and floor values between 0 and 30.
This is a reminder to myself to use zip
more. First, here is the solution I came up with, pretty straightforward:
def elevator_distance(array):
res = 0
for i in range(len(array)-1):
res += abs(int(array[i]) - int(array[i+1]))
return res
This works, but zip
is way more elegant:
def elevator_distance(array):
return sum(abs(a - b) for a, b in zip(array, array[1:]))
I also found this numpy
solution interesting, because it makes use of the vectorized approach:
import numpy as np
def elevator_distance(array):
return np.sum(np.abs(np.diff(array)))