#!/usr/bin/python3
# ====================================================================
# stack (LIFO queue)
#
# Notes:
# 1. queue.Queue and collections.deque serve different purposes.
# queue.Queue is intended for allowing different threads to
# communicate using queued messages/data, whereas collections.deque
# is simply intended as a data structure.
# 2. Deque (Doubly Ended Queue)
# 3. TOS = Top Of Stack
#
# Useful URL: www.geeksforgeeks.org/deque-in-python/
# ====================================================================
from collections import deque
# --------------------------------------------------------------------
# --- LIFO queue class
# --------------------------------------------------------------------
class Stack:
# initialize stack
def __init__(self):
self.stack = deque()
# pop from TOS
def pop(self) -> any:
if len(self.stack) == 0: return None
return self.stack.pop()
# push onto TOS
def push(self,e:any):
self.stack.append(e)
return
# modify TOS
def modify_tos(self,e:any):
if len(self.stack) == 0: return False
self.stack[-1] = e
return True
# is stack empty?
def is_empty(self):
if len(self.stack) == 0: return True
return False
# return copy of TOS
def tos(self):
if len(self.stack) == 0: return None
return self.stack[-1]
# length of stack
# (return the number elements)
def length(self):
return len(self.stack)
# clear (empty) stack
# (return the count of elements removed)
def clear(self):
i = 0
for _ in range(len(self.stack)):
self.stack.pop()
i += 1
return i
# return stack as a list of token
def as_list(self):
return list(self.stack)
# --------------------------------------------------------------------
# ---- main
# --------------------------------------------------------------------
if __name__ == '__main__':
import user_interface as ui
# ---- user enter stack element value
def enter_stack_element():
e = ui.get_user_input('Enter stack element: ')
if not e: return None # empty string
return e
menu = '''
------ Test collections.deque as LIFO Stack ------
--------------------------------------------------
Option Description
------ ------------------------------------------
1 push onto stack
2 pop from stack (element removed)
3 top of stack (element not removed)
4 modify top of stack
5 is stack empty?
6 stack length
7 clear stack
8 display stack as list
9 display stack as string'''
print(menu)
stack = Stack()
while True:
# ---- ask the user to select option
print()
s = ui.get_user_input('Enter option: ')
if not s: break
tf,opt = ui.is_integer(s)
if not tf:
print()
print(f'Illegal option ({s}) - try again')
continue
if opt == 0: # exit program
break
if opt == 1: # push onto stack
e = enter_stack_element()
if e is not None: stack.push(e)
continue
if opt == 2: # pop from stack
print(f'{stack.pop()} (poped from TOS)')
continue
if opt == 3: # copy of top of stack
print(f'{stack.tos()} (copied from TOS)')
continue
if opt == 4: # modify top of stack
e = enter_stack_element()
if e is not None: print(stack.modify_tos(e))
continue
if opt == 5: # is stack empty
print(stack.is_empty())
continue
if opt == 6: # stack length
print(stack.length())
continue
if opt == 7: # clear (empty) stack
count = stack.clear()
continue
if opt == 8: # stack as list
print(stack.as_list())
continue
if opt == 9: # stack as string
print(','.join(stack.as_list()))
continue
print()
print(f'Unknown option ({opt}) - try again')