This is my solution for a Hackerrank problem. The problem was:There is a horizontal row of cubes. The length of each cube is given. You need to create a new vertical pile of cubes. The new pile should follow these directions: if cube_i is on top of cube_j then sideLength_j >= sideLength_i. When stacking the cubes, you can only pick up either the leftmost or the rightmost cube each time. Print Yes if it is possible to stack the cubes. Otherwise, print No. Do not print the quotation marks.Input FormatThe first line contains a single integer T, the number of test cases.  For each test case, there are 2 lines.  The first line of each test case contains , the number of cubes.  The second line contains space separated integers, denoting the sideLengths of each cube in that order.Constraints1 <= T <= 51 <= n <= 10**51 <= sideLength <= 2**31Output FormatFor each test case, output a single line containing either Yes or No without the quotes.Sample Input264 3 2 1 3 431 3 2Sample OutputYesNoExplanationIn the first test case, pick in this order: left - 4, right - 4, left - 3, right - 3, left - 2, right - 1.  In the second test case, no order gives an appropriate arrangement of vertical cubes. 3 will always come after either 1 or 2.My code is actually rather short:if __name__ == '__main__':    num_tests = int(input().strip())    for _ in range(num_tests):        num_cubes = int(input().strip())        cube_sidelengths = list(map(int, map(str.strip, input().strip().split())))        i, j = 0, len(cube_sidelengths)-1        pile = []        while i != j:            left, right = cube_sidelengths[i], cube_sidelengths[j]            # In case there is nothing in the pile just add the bigger one            if not pile:                if left > right:                    pile.append(left)                    i += 1                else:                    pile.append(right)                    j -= 1            else:                # Take the bigger of the left and right element and compare it                # to the last item on the pile. If it's bigger we can't pile                # it up, otherwise put it on the pile and continue                if left > right:                    if left > pile[-1]:                        print('No')                        break                    else:                        pile.append(left)                        i += 1                else:                    if right > pile[-1]:                        print('No')                        break                    else:                        pile.append(right)                        j -= 1        else:            print('Yes')But I'm actually not very satisfied with the code. It passes all Hackerrank tests but I can't help feeling that it's missing something - but I can't put my finger on it.An additional thing that has been bugging me was that it was part of the  Python collections problems but I haven't used anything from the collections module. It would be possible to use a deque here but that felt like overkill - because pop and popLeft are O(1) but just keeping the indices and accessing a list is also O(1) so it wouldn't even provide better asymptotic behaviour. So as additional question: Is there anything that could be improved by using a deque?Otherwise I would be very glad about any feedback how I could improve the code.
Piling Up with Python
python;programming challenge;python 3.x;collections
You don't need to build the pileWhy make the extra effort to pop and append where the only expected result is a boolean value (it is possible or not). Using your approach, all you need is a variable holding the last used cube to compare the next two to.You'd better return than printInstead of printing from your main part of the computation, return a meaningful result instead; and let the caller print something according to it. This forces you to build functions and make your code more reusable.In the same vein, separate the input parsing part from the core of your computation.Also incorporating @MrGrj advices, your code can look like:def can_pile_cubes(cube_lengths):    cube_on_top = None    left_index = 0    right_index = len(cube_lengths) - 1    while left_index < right_index:  # Avoid corner case of `cube_lengths` being an empty list        left_cube = cube_lengths[left_index]        right_cube = cube_lengths[right_index]        if cube_on_top is None:            if left_cube > right_cube:                cube_on_top = left_cube                left_index += 1            else:                cube_on_top = right_cube                right_index -= 1        else:            if left_cube > right_cube:                if left_cube > cube_on_top:                    return False                cube_on_top = left_cube                left_index += 1            else:                if right_cube > cube_on_top:                    return False                cube_on_top = right_cube                right_index -= 1    return Truedef parse_test_case():    input()  # Throw away number of cubes    return [int(x) for x in input().split()]if __name__ == '__main__':    num_tests = int(input())    for _ in range(num_tests):        can_pile = can_pile_cubes(parse_test_case())        print('Yes' if can_pile else 'No')Use efficient loopingNow looking at the code at hand, maintaining explicit indexes in a while loop does not feel very Pythonic. So let's take a closer look at the problem: checking that the biggest end of the two in the current state of the list is no bigger than the last poped item lead to the property that, if the list is pileable, its first part is in decreasing order up to a minimum and from this minimum onward the second part is in increasing order.This property is easy to check if we can access items by pairs. This is exactly what the pairwise recipe from itertools allow us to do.We thus just need to check that each pair in the list is in decreasing order and, once we found a pair that doesn't fit the condition, that all remaining pairs are in increasing order:import itertoolsdef pairwise(iterable):    first, second = itertools.tee(iterable)    next(second, None)    return zip(first, second)def can_pile_cubes(cube_lengths):    pairs = pairwise(cube_lengths)    # First part of the list, check if decreasing order    for first, second in pairs:        if first < second:            break    # Second part of the list, check if increasing order    for first, second in pairs:        if first > second:            return False    return Truedef parse_test_case():    input()  # Throw away number of cubes    return [int(x) for x in input().split()]if __name__ == '__main__':    num_tests = int(input())    for _ in range(num_tests):        can_pile = can_pile_cubes(parse_test_case())        print('Yes' if can_pile else 'No')