


from typing import Any




class        lowerCamelCase      :


	def __init__(						self							,    lowercase__):
							__UpperCAmelCase :       Optional[Any]  						=  data
							__UpperCAmelCase :       Tuple  						=  None


	def __repr__(						self):
							return F"Node({self.data})"






class        lowerCamelCase      :


	def __init__(						self):
							__UpperCAmelCase :       List[Any]  						=  None


	def __iter__(						self):
							__UpperCAmelCase :       Tuple  						=  self.head
							while node:
													yield node.data
													__UpperCAmelCase :       int  						=  node.next


	def __len__(						self):
							return sum(1 for _ in self)


	def __repr__(						self):
							return "->".join([str(lowercase__) for item in self])


	def __getitem__(						self							,    lowercase__):
							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							,    lowercase__							,    lowercase__):
							if not 0 <= index < len(self):
													raise ValueError('''list index out of range.''')
							__UpperCAmelCase :       Dict  						=  self.head
							for _ in range(lowercase__):
													__UpperCAmelCase :       Optional[int]  						=  current.next
							__UpperCAmelCase :       str  						=  data


	def    A(						self							,    lowercase__):
							self.insert_nth(len(self)							,    lowercase__)


	def    A(						self							,    lowercase__):
							self.insert_nth(0							,    lowercase__)


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


	def    A(						self):  # print every node data
							print(self)


	def    A(						self):
							return self.delete_nth(0)


	def    A(						self):  # delete from tail
							return self.delete_nth(len(self) - 1)


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


	def    A(						self):
							return self.head is None


	def    A(						self):
							__UpperCAmelCase :       Dict  						=  None
							__UpperCAmelCase :       int  						=  self.head

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






def 						__SCREAMING_SNAKE_CASE       (					)		->    None:




						'''simple docstring'''







						__UpperCAmelCase :       Dict  						=  LinkedList()
						assert linked_list.is_empty() is True
						assert str(lowercase_			) == ""

						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(lowercase_			) == i
												linked_list.insert_nth(lowercase_			,					i + 1			)
						assert str(lowercase_			) == "->".join(str(lowercase_			) for i in range(1			,					11			)			)

						linked_list.insert_head(0			)
						linked_list.insert_tail(11			)
						assert str(lowercase_			) == "->".join(str(lowercase_			) 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(lowercase_			) == 9
						assert str(lowercase_			) == "->".join(str(lowercase_			) 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			):
												__UpperCAmelCase :       Optional[int]  						=  -i
						assert all(linked_list[i] == -i for i in range(0			,					9			)			) is True

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




def 						__SCREAMING_SNAKE_CASE       (					)		->    None:




						'''simple docstring'''







						__UpperCAmelCase :       Optional[int]  						=  [
						    -9,
						    100,
						    Node(77345112			),
						    '''dlrow olleH''',
						    7,
						    5555,
						    0,
						    -1_9_2.5_5_5_5_5,
						    '''Hello, world!''',
						    7_7.9,
						    Node(10			),
						    None,
						    None,
						    1_2.2_0,
						]
						__UpperCAmelCase :       Tuple  						=  LinkedList()

						for i in test_input:
												linked_list.insert_tail(lowercase_			)

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

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

						# Delete the tail
						__UpperCAmelCase :       Any  						=  linked_list.delete_tail()
						assert result == 1_2.2
						assert (
						    str(lowercase_			) == "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
						__UpperCAmelCase :       int  						=  linked_list.delete_nth(10			)
						assert result is None
						assert (
						    str(lowercase_			) == "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(lowercase_			)
						    == "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(lowercase_			)
						assert (
						    str(lowercase_			)
						    == "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(lowercase_			)
						    == "None->None->Node(10)->77.9->Hello, world!->-192.55555->0->5555->"
						    "7->dlrow olleH->Node(77345112)->100->Node(Hello again, world!)"
						)




def 						__SCREAMING_SNAKE_CASE       (					)		->    Union[str, Any]:




						'''simple docstring'''







						from doctest import testmod

						testmod()

						__UpperCAmelCase :       Dict  						=  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(lowercase_			)
						print('''\nReading/changing Node data using indexing:'''			)
						print(f"Element at Position 1: {linked_list[1]}"			)
						__UpperCAmelCase :       List[str]  						=  input('''Enter New Value: '''			).strip()
						print('''New list:'''			)
						print(lowercase_			)
						print(f"length of linked_list is : {len(lowercase_			)}"			)


if __name__ == "__main__":
				main()





def 						__SCREAMING_SNAKE_CASE       (					lowercase_			,					lowercase_			)		->    str:




						'''simple docstring'''







						if a < 0 or b < 0:
												raise ValueError('''the value of both inputs must be positive'''			)
						__UpperCAmelCase :       Dict  						=  str(bin(lowercase_			)			)[2:]  # remove the leading "0b"
						__UpperCAmelCase :       List[Any]  						=  str(bin(lowercase_			)			)[2:]
						__UpperCAmelCase :       List[Any]  						=  max(len(lowercase_			)			,					len(lowercase_			)			)
						return "0b" + "".join(
						    str(int('''1''' in (char_a, char_b)			)			)
						    for char_a, char_b in zip(a_binary.zfill(lowercase_			)			,					b_binary.zfill(lowercase_			)			)			)


if __name__ == "__main__":
				import doctest

				doctest.testmod()

