





from typing import Any


class       lowercase					:



						"""simple docstring"""

						def __init__(     self      :		Any			,					lowerCamelCase_      :		Optional[int]       ):





										'''simple docstring'''







										_snake_case			:      Optional[Any]	    = data
										_snake_case			:      Optional[Any]	    = None







						def __repr__(     self      :		Tuple       ):





										'''simple docstring'''







										return f'''Node({self.data})'''



class       lowercase					:



						"""simple docstring"""

						def __init__(     self      :		Any       ):





										'''simple docstring'''







										_snake_case			:      Dict	    = None







						def __iter__(     self      :		Dict       ):





										'''simple docstring'''







										_snake_case			:      Optional[Any]	    = self.head
										while node:
														yield node.data
														_snake_case			:      Dict	    = node.next







						def __len__(     self      :		Optional[int]       ):





										'''simple docstring'''







										return sum(1 for _ in self       )







						def __repr__(     self      :		Union[str, Any]       ):





										'''simple docstring'''







										return "->".join([str(snake_case_       ) for item in self]       )







						def __getitem__(     self      :		Dict			,					lowerCamelCase_      :		List[Any]       ):





										'''simple docstring'''







										if not 0 <= index < len(self       ):
														raise ValueError('list index out of range.'       )
										for i, node in enumerate(self       ):
														if i == index:
																		return node
										return None







						def __setitem__(     self      :		Union[str, Any]			,					lowerCamelCase_      :		Any			,					lowerCamelCase_      :		Optional[Any]       ):





										'''simple docstring'''







										if not 0 <= index < len(self       ):
														raise ValueError('list index out of range.'       )
										_snake_case			:      Optional[Any]	    = self.head
										for _ in range(snake_case_       ):
														_snake_case			:      int	    = current.next
										_snake_case			:      Any	    = data







						def 		__UpperCAmelCase							(     self      :		List[Any]			,					lowerCamelCase_      :		Any       ):





										'''simple docstring'''







										self.insert_nth(len(self       )			,					snake_case_       )







						def 		__UpperCAmelCase							(     self      :		Any			,					lowerCamelCase_      :		Optional[int]       ):





										'''simple docstring'''







										self.insert_nth(0			,					snake_case_       )







						def 		__UpperCAmelCase							(     self      :		Optional[Any]			,					lowerCamelCase_      :		List[Any]			,					lowerCamelCase_      :		Optional[Any]       ):





										'''simple docstring'''







										if not 0 <= index <= len(self       ):
														raise IndexError('list index out of range'       )
										_snake_case			:      str	    = Node(snake_case_       )
										if self.head is None:
														_snake_case			:      str	    = new_node
										elif index == 0:
														_snake_case			:      Union[str, Any]	    = self.head  # link new_node to head
														_snake_case			:      List[str]	    = new_node
										else:
														_snake_case			:      Tuple	    = self.head
														for _ in range(index - 1       ):
																		_snake_case			:      Any	    = temp.next
														_snake_case			:      int	    = temp.next
														_snake_case			:      List[Any]	    = new_node







						def 		__UpperCAmelCase							(     self      :		Tuple       ):  # print every node data





										'''simple docstring'''







										print(self       )







						def 		__UpperCAmelCase							(     self      :		int       ):





										'''simple docstring'''







										return self.delete_nth(0       )







						def 		__UpperCAmelCase							(     self      :		List[str]       ):  # delete from tail





										'''simple docstring'''







										return self.delete_nth(len(self       ) - 1       )







						def 		__UpperCAmelCase							(     self      :		Tuple			,					lowerCamelCase_      :		Tuple = 0       ):





										'''simple docstring'''







										if not 0 <= index <= len(self       ) - 1:  # test if index is valid
														raise IndexError('List index out of range.'       )
										_snake_case			:      str	    = self.head  # default first node
										if index == 0:
														_snake_case			:      Optional[int]	    = self.head.next
										else:
														_snake_case			:      Dict	    = self.head
														for _ in range(index - 1       ):
																		_snake_case			:      Dict	    = temp.next
														_snake_case			:      str	    = temp.next
														_snake_case			:      List[str]	    = temp.next.next
										return delete_node.data







						def 		__UpperCAmelCase							(     self      :		Any       ):





										'''simple docstring'''







										return self.head is None







						def 		__UpperCAmelCase							(     self      :		Dict       ):





										'''simple docstring'''







										_snake_case			:      List[str]	    = None
										_snake_case			:      Optional[Any]	    = self.head

										while current:
														# Store the current node's next node.
														_snake_case			:      List[str]	    = current.next
														# Make the current node's next point backwards
														_snake_case			:      str	    = prev
														# Make the previous node be the current node
														_snake_case			:      str	    = current
														# Make the current node the next node (to progress iteration)
														_snake_case			:      Dict	    = next_node
										# Return prev in order to put the head at the end
										_snake_case			:      Dict	    = prev



def    A__(		):
				_snake_case			:      Optional[Any]	    = LinkedList()
				assert linked_list.is_empty() is True
				assert str(__lowerCAmelCase			) == ""

				try:
								linked_list.delete_head()
								raise AssertionError  # This should not happen.
				except IndexError:
								assert True  # This should happen.

				try:
								linked_list.delete_tail()
								raise AssertionError  # This should not happen.
				except IndexError:
								assert True  # This should happen.

				for i in range(10			):
								assert len(__lowerCAmelCase			) == i
								linked_list.insert_nth(__lowerCAmelCase						,      i + 1			)
				assert str(__lowerCAmelCase			) == "->".join(str(__lowerCAmelCase			) for i in range(1						,      11			)			)

				linked_list.insert_head(0			)
				linked_list.insert_tail(11			)
				assert str(__lowerCAmelCase			) == "->".join(str(__lowerCAmelCase			) for i in range(0						,      12			)			)

				assert linked_list.delete_head() == 0
				assert linked_list.delete_nth(9			) == 10
				assert linked_list.delete_tail() == 11
				assert len(__lowerCAmelCase			) == 9
				assert str(__lowerCAmelCase			) == "->".join(str(__lowerCAmelCase			) for i in range(1						,      10			)			)

				assert all(linked_list[i] == i + 1 for i in range(0						,      9			)			) is True

				for i in range(0						,      9			):
								_snake_case			:      Tuple	    = -i
				assert all(linked_list[i] == -i for i in range(0						,      9			)			) is True

				linked_list.reverse()
				assert str(__lowerCAmelCase			) == "->".join(str(__lowerCAmelCase			) for i in range(-8						,      1			)			)

def    A__(		):
				_snake_case			:      Optional[int]	    = [
				    -9,
				    1_00,
				    Node(77_34_51_12			),
				    """dlrow olleH""",
				    7,
				    55_55,
				    0,
				    -192.55_555,
				    """Hello, world!""",
				    77.9,
				    Node(10			),
				    None,
				    None,
				    12.20,
				]
				_snake_case			:      Any	    = LinkedList()

				for i in test_input:
								linked_list.insert_tail(__lowerCAmelCase			)

				# Check if it's empty or not
				assert linked_list.is_empty() is False
				assert (
				    str(__lowerCAmelCase			) == "-9->100->Node(77345112)->dlrow olleH->7->5555->0->"
				    "-192.55555->Hello, world!->77.9->Node(10)->None->None->12.2"
				)

				# Delete the head
				_snake_case			:      Optional[int]	    = linked_list.delete_head()
				assert result == -9
				assert (
				    str(__lowerCAmelCase			) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
				    "Hello, world!->77.9->Node(10)->None->None->12.2"
				)

				# Delete the tail
				_snake_case			:      Union[str, Any]	    = linked_list.delete_tail()
				assert result == 12.2
				assert (
				    str(__lowerCAmelCase			) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
				    "Hello, world!->77.9->Node(10)->None->None"
				)

				# Delete a node in specific location in linked list
				_snake_case			:      Union[str, Any]	    = linked_list.delete_nth(10			)
				assert result is None
				assert (
				    str(__lowerCAmelCase			) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
				    "Hello, world!->77.9->Node(10)->None"
				)

				# Add a Node instance to its head
				linked_list.insert_head(Node('Hello again, world!'			)			)
				assert (
				    str(__lowerCAmelCase			)
				    == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->"
				    "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None"
				)

				# Add None to its tail
				linked_list.insert_tail(__lowerCAmelCase			)
				assert (
				    str(__lowerCAmelCase			)
				    == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->"
				    "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None->None"
				)

				# Reverse the linked list
				linked_list.reverse()
				assert (
				    str(__lowerCAmelCase			)
				    == "None->None->Node(10)->77.9->Hello, world!->-192.55555->0->5555->"
				    "7->dlrow olleH->Node(77345112)->100->Node(Hello again, world!)"
				)

def    A__(		):
				from doctest import testmod

				testmod()

				_snake_case			:      List[Any]	    = LinkedList()
				linked_list.insert_head(input('Inserting 1st at head '			).strip()			)
				linked_list.insert_head(input('Inserting 2nd at head '			).strip()			)
				print('\nPrint list:'			)
				linked_list.print_list()
				linked_list.insert_tail(input('\nInserting 1st at tail '			).strip()			)
				linked_list.insert_tail(input('Inserting 2nd at tail '			).strip()			)
				print('\nPrint list:'			)
				linked_list.print_list()
				print('\nDelete head'			)
				linked_list.delete_head()
				print('Delete tail'			)
				linked_list.delete_tail()
				print('\nPrint list:'			)
				linked_list.print_list()
				print('\nReverse linked list'			)
				linked_list.reverse()
				print('\nPrint list:'			)
				linked_list.print_list()
				print('\nString representation of linked list:'			)
				print(__lowerCAmelCase			)
				print('\nReading/changing Node data using indexing:'			)
				print(F'''Element at Position 1: {linked_list[1]}'''			)
				_snake_case			:      List[Any]	    = input('Enter New Value: '			).strip()
				print('New list:'			)
				print(__lowerCAmelCase			)
				print(F'''length of linked_list is : {len(__lowerCAmelCase			)}'''			)


if __name__ == "__main__":
		main()







"""simple docstring"""



from typing import List

from .keymap import KEYMAP, get_character

def  _A(		lowerCAmelCase							):

							def decorator(lowerCAmelCase							):
														A__       :     Any								=			getattr(lowerCAmelCase			,  """handle_key"""			,  []							)
														handle += [key]
														setattr(lowerCAmelCase			,  """handle_key"""			,  lowerCAmelCase							)
														return func

							return decorator

def  _A(		*lowerCAmelCase							):

							def decorator(lowerCAmelCase							):
														A__       :     Optional[Any]								=			getattr(lowerCAmelCase			,  """handle_key"""			,  []							)
														handle += keys
														setattr(lowerCAmelCase			,  """handle_key"""			,  lowerCAmelCase							)
														return func

							return decorator
class 						__UpperCAmelCase    (__A     ):







			'''simple docstring'''





			def __new__(			cls   ,      snake_case_   ,      snake_case_   ,      snake_case_							):







										'''simple docstring'''


										A__       :     Union[str, Any]								=			super().__new__(cls   ,      snake_case_   ,      snake_case_   ,      snake_case_							)
										if not hasattr(snake_case_   ,      """key_handler"""							):
																	setattr(snake_case_   ,      """key_handler"""   ,      {}							)
										setattr(snake_case_   ,      """handle_input"""   ,      KeyHandler.handle_input							)

										for value in attrs.values():
																	A__       :     Dict								=			getattr(snake_case_   ,      """handle_key"""   ,      []							)
																	for key in handled_keys:
																								A__       :     Optional[Any]								=			value
										return new_cls





			@staticmethod
			def 		lowerCamelCase					(			cls							):







										'''simple docstring'''


										A__       :     int								=			get_character()
										if char != KEYMAP["undefined"]:
																	A__       :     Union[str, Any]								=			ord(snake_case_							)
										A__       :     int								=			cls.key_handler.get(snake_case_							)
										if handler:
																	A__       :     int								=			char
																	return handler(cls							)
										else:
																	return None





def  _A(		cls							):
							return KeyHandler(cls.__name__			,  cls.__bases__			,  cls.__dict__.copy()							)





