"""Module containing implementation of a binary heap."""


class BinaryHeap(object):
    """Implementation of Binary heap: methods: push and pop."""

    def __init__(self, iterable=None, minmax='min'):
        """Construct new binary heap."""
        self._list = [0]
        try:
            self._minmax = {
                'min': 1,
                'max': -1
            }[minmax]
        except KeyError:
            raise ValueError("min/max optional parameter must be 'min' or 'max'")
        if iterable is not None:
            try:
                for item in iterable:
                    self.push(item)
            except TypeError:
                raise TypeError("Optional binary heap argument must be iterable.")

    def push(self, val):
        """Push value to heap."""
        self._list.append(val)
        self._organize_up(len(self._list) - 1)

    def pop(self):
        """Swap root with last item -> remove old root -> heapify heap."""
        try:
            self._swap(1, -1)
            to_pop = self._list.pop()
            self._organize_down(1)
            return to_pop
        except IndexError:
            raise IndexError('Cannot pop from an empty heap.')

    def _organize_up(self, child_i):
        """Organize heap starting from node i and moving up towards root."""
        parent_i = child_i // 2
        while child_i > 1 and self._minmax * self._list[child_i] < self._minmax * self._list[parent_i]:
            self._swap(parent_i, child_i)
            child_i, parent_i = parent_i, parent_i // 2

    def _swap(self, i, k):
        """Swap nodes at indexes i and k."""
        self._list[i], self._list[k] = self._list[k], self._list[i]

    def _minmaxchild(self, i):
        """Get the min/max child of the parent at index i."""
        children = [(self._minmax * self._list[c], c)
                    for c in (2 * i, 2 * i + 1) if c < len(self._list)]
        return min(children)

    def _organize_down(self, parent_i):
        """Compare parent with child, swap and continue to organize if needed."""
        try:
            while True:
                child_value, child_i = self._minmaxchild(parent_i)
                parent_value = self._minmax * self._list[parent_i]
                if child_value < parent_value:
                    self._swap(parent_i, child_i)
                    parent_i = child_i
                else:
                    return
        except ValueError:
            return

@@ -50,16 +50,44 @@
 eap.%22%22%22%0A
+from operator import lt, gt%0A
 %0A%0Aclass 
@@ -327,16 +327,31 @@
 ._minmax
+, self._compare
  = %7B%0A   
@@ -370,17 +370,25 @@
  'min': 
-1
+(min, lt)
 ,%0A      
@@ -404,18 +404,25 @@
  'max': 
--1
+(max, gt)
 %0A       
@@ -1356,24 +1356,62 @@
 ds root.%22%22%22%0A
+        # import pdb; pdb.set_trace()%0A
         pare
@@ -1448,19 +1448,20 @@
 ile 
-child
+parent
 _i %3E 
-1
+0
  and
@@ -1463,33 +1463,32 @@
 0 and self._
-minmax * 
+compare(
 self._list%5Bc
@@ -1498,25 +1498,9 @@
 d_i%5D
- %3C self._minmax *
+,
  sel
@@ -1516,16 +1516,17 @@
 arent_i%5D
+)
 :%0A      
@@ -1873,31 +1873,16 @@
 ren = %5B(
-self._minmax * 
 self._li
@@ -1978,19 +1978,28 @@
  return 
-min
+self._minmax
 (childre
@@ -2262,23 +2262,8 @@
 ue =
- self._minmax *
  sel
@@ -2299,16 +2299,30 @@
      if 
+self._compare(
 child_va
@@ -2324,18 +2324,17 @@
 ld_value
- %3C
+,
  parent_
@@ -2338,16 +2338,17 @@
 nt_value
+)
 :%0A      

refactor heap to handle tuple data for use in prio. queue