import numpy as np

np.__version__

author = 'kyubyong. longinglove@nate.com'

"""
Explanation: Soring, searching, and counting
End of explanation
"""


x = np.array([[1,4],[3,1]])
out = np.sort(x, axis=1)
x.sort(axis=1)
assert np.array_equal(out, x)
print out

"""
Explanation: Sorting
Q1. Sort x along the second axis.
End of explanation
"""


surnames =    ('Hertz',    'Galilei', 'Hertz')
first_names = ('Heinrich', 'Galileo', 'Gustav')
print np.lexsort((first_names, surnames))

"""
Explanation: Q2. Sort pairs of surnames and first names and return their indices. (first by surname, then by name).
End of explanation
"""


x = np.array([[1,4],[3,1]])
out = np.argsort(x, axis=1)
print out

"""
Explanation: Q3. Get the indices that would sort x along the second axis.
End of explanation
"""


x = np.random.permutation(10)
print "x =", x
print "\nCheck the fifth element of this new array is 5, the first four elements are all smaller than 5, and 6th through the end are bigger than 5\n", 
out = np.partition(x, 5)
x.partition(5) # in-place equivalent
assert np.array_equal(x, out)
print out


"""
Explanation: Q4. Create an array such that its fifth element would be the same as the element of sorted x, and it divide other elements by their value.
End of explanation
"""


x = np.random.permutation(10)
print "x =", x
partitioned = np.partition(x, 3)
indices = np.argpartition(x, 3)
print "partitioned =", partitioned
print "indices =", partitioned
assert np.array_equiv(x[indices], partitioned)

"""
Explanation: Q5. Create the indices of an array such that its third element would be the same as the element of sorted x, and it divide other elements by their value.
End of explanation
"""


x = np.random.permutation(10).reshape(2, 5)
print "x =", x
print "maximum values =", np.max(x, 1)
print "max indices =", np.argmax(x, 1)
print "minimum values =", np.min(x, 1)
print "min indices =", np.argmin(x, 1)


"""
Explanation: Searching
Q6. Get the maximum and minimum values and their indices of x along the second axis.
End of explanation
"""


x = np.array([[np.nan, 4], [3, 2]])
print "maximum values ignoring NaNs =", np.nanmax(x, 1)
print "max indices =", np.nanargmax(x, 1)
print "minimum values ignoring NaNs =", np.nanmin(x, 1)
print "min indices =", np.nanargmin(x, 1)

"""
Explanation: Q7. Get the maximum and minimum values and their indices of x along the second axis, ignoring NaNs.
End of explanation
"""


x = np.array([[1, 2, 3], [1, 3, 5]])
print "Values bigger than 2 =", x[x>2]
print "Their indices are ", np.nonzero(x > 2)
assert np.array_equiv(x[x>2], x[np.nonzero(x > 2)])
assert np.array_equiv(x[x>2], np.extract(x > 2, x))

"""
Explanation: Q8. Get the values and indices of the elements that are bigger than 2 in x.
End of explanation
"""


x = np.array([[1, 2, 3], [1, 3, 5]])
print np.flatnonzero(x>2)
assert np.array_equiv(np.flatnonzero(x), x.ravel().nonzero())

"""
Explanation: Q9. Get the indices of the elements that are bigger than 2 in the flattend x.
End of explanation
"""


x = np.arange(-5, 4).reshape(3, 3)
print np.where(x <0, 0, x)

"""
Explanation: Q10. Check the elements of x and return 0 if it is less than 0, otherwise the element itself.
End of explanation
"""


x = [1, 3, 5, 7, 9]
y = [0, 4, 2, 6]
np.searchsorted(x, y)

"""
Explanation: Q11. Get the indices where elements of y should be inserted to x to maintain order.
End of explanation
"""


x = [[0,1,7,0,0],[3,0,0,2,19]]
print np.count_nonzero(x)
assert np.count_nonzero(x) == len(x[x!=0])

"""
Explanation: Counting
Q12. Get the number of nonzero elements in x.
End of explanation
"""


