'''Stack ADT.

Operations:
	pop: remove and return top item
        push(item): store item on top of stack
        is_empty: return whether stack is empty.
'''

class Stack:

    '''A last-in, first-out (LIFO) stack of items'''

    def __init__(self):
        '''A new empty Stack.'''

        self.top = None
        
    def pop(self):
        '''Remove and return the top item.'''

        value, self.top = self.top.value, self.top.nxt
        return value

    def is_empty(self):
        '''Return whether the stack is empty.'''

        return not self.top
    
    def push(self, o):
        '''Place o on top of the stack.'''

        self.top = LListNode(o, self.top)

class LListNode:
    '''Linked List node that can reference next node.'''
    
    def __init__(self, value=None, nxt=None):
        '''Create a LListNode with value and reference to next LListNode'''
        
        self.value, self.nxt = value, nxt
        
    def __str__(self):
        '''Represent this node as a string.'''
        
        return '(' + str(self.value) + ', ' + str(self.nxt) + ')' # recursive!
        
        
if __name__  ==  '__main__':
    import time
    s = Stack()
    ranges = [2, 3, 4, 5]

    for r in ranges:
        items = range(10**r)

        # start the clock
        start = time.time()
    
        for i in items:
            s.push(i)
        
        for i in items:
            s.pop()
        
        end = time.time()
        print ("It took {} to push/pop {} items".format(end - start, len(items)))
