



class 	lowercase		:






	"""simple docstring"""


	def __init__(			self			:		List[str]		,						__UpperCAmelCase			:		int  )    ->				Any:
							UpperCAmelCase_=     data
							UpperCAmelCase_=     None
							UpperCAmelCase_=     None




	def __str__(			self			:		str  )    ->				Tuple:
							return F"""{self.data}"""






class 	lowercase		:






	"""simple docstring"""


	def __init__(			self			:		Union[str, Any]  )    ->				List[str]:
							UpperCAmelCase_=     None
							UpperCAmelCase_=     None




	def __iter__(			self			:		List[str]  )    ->				str:
							UpperCAmelCase_=     self.head
							while node:
													yield node.data
													UpperCAmelCase_=     node.next




	def __str__(			self			:		List[str]  )    ->				Union[str, Any]:
							return "->".join([str(__SCREAMING_SNAKE_CASE  ) for item in self]  )




	def __len__(			self			:		Tuple  )    ->				Any:
							return sum(1 for _ in self  )




	def 						_SCREAMING_SNAKE_CASE	(			self			:		List[str]		,						__UpperCAmelCase			:		int  )    ->				Dict:
							self.insert_at_nth(0		,						__SCREAMING_SNAKE_CASE  )




	def 						_SCREAMING_SNAKE_CASE	(			self			:		Tuple		,						__UpperCAmelCase			:		List[Any]  )    ->				Dict:
							self.insert_at_nth(len(self  )		,						__SCREAMING_SNAKE_CASE  )




	def 						_SCREAMING_SNAKE_CASE	(			self			:		List[Any]		,						__UpperCAmelCase			:		Optional[int]		,						__UpperCAmelCase			:		Tuple  )    ->				Optional[Any]:
							UpperCAmelCase_=     len(self  )

							if not 0 <= index <= length:
													raise IndexError("""list index out of range"""  )
							UpperCAmelCase_=     Node(__SCREAMING_SNAKE_CASE  )
							if self.head is None:
													UpperCAmelCase_=     UpperCAmelCase_=     new_node
							elif index == 0:
													UpperCAmelCase_=     new_node
													UpperCAmelCase_=     self.head
													UpperCAmelCase_=     new_node
							elif index == length:
													UpperCAmelCase_=     new_node
													UpperCAmelCase_=     self.tail
													UpperCAmelCase_=     new_node
							else:
													UpperCAmelCase_=     self.head
													for _ in range(0		,						__SCREAMING_SNAKE_CASE  ):
																			UpperCAmelCase_=     temp.next
													UpperCAmelCase_=     new_node
													UpperCAmelCase_=     temp.previous
													UpperCAmelCase_=     temp
													UpperCAmelCase_=     new_node




	def 						_SCREAMING_SNAKE_CASE	(			self			:		str  )    ->				str:
							return self.delete_at_nth(0  )




	def 						_SCREAMING_SNAKE_CASE	(			self			:		str  )    ->				Optional[Any]:
							return self.delete_at_nth(len(self  ) - 1  )




	def 						_SCREAMING_SNAKE_CASE	(			self			:		str		,						__UpperCAmelCase			:		Optional[Any]  )    ->				Optional[Any]:
							UpperCAmelCase_=     len(self  )

							if not 0 <= index <= length - 1:
													raise IndexError("""list index out of range"""  )
							UpperCAmelCase_=     self.head  # default first node
							if length == 1:
													UpperCAmelCase_=     UpperCAmelCase_=     None
							elif index == 0:
													UpperCAmelCase_=     self.head.next
													UpperCAmelCase_=     None
							elif index == length - 1:
													UpperCAmelCase_=     self.tail
													UpperCAmelCase_=     self.tail.previous
													UpperCAmelCase_=     None
							else:
													UpperCAmelCase_=     self.head
													for _ in range(0		,						__SCREAMING_SNAKE_CASE  ):
																			UpperCAmelCase_=     temp.next
													UpperCAmelCase_=     temp
													UpperCAmelCase_=     temp.previous
													UpperCAmelCase_=     temp.next
							return delete_node.data




	def 						_SCREAMING_SNAKE_CASE	(			self			:		Optional[Any]		,						__UpperCAmelCase			:		Union[str, Any]  )    ->				Any:
							UpperCAmelCase_=     self.head

							while current.data != data:  # Find the position to delete
													if current.next:
																			UpperCAmelCase_=     current.next
													else:  # We have reached the end an no value matches
																			raise ValueError("""No data matching given value"""  )

							if current == self.head:
													self.delete_head()

							elif current == self.tail:
													self.delete_tail()

							else:  # Before: 1 <--> 2(current) <--> 3
													UpperCAmelCase_=     current.next  # 1 --> 3
													UpperCAmelCase_=     current.previous  # 1 <--> 3
							return data




	def 						_SCREAMING_SNAKE_CASE	(			self			:		Tuple  )    ->				List[Any]:
							return len(self  ) == 0



def  __a  (					)   ->				None:






						'''simple docstring'''



						UpperCAmelCase_=     DoublyLinkedList()
						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_at_nth(lowerCAmelCase_    ,i + 1       )
						assert str(lowerCAmelCase_       ) == "->".join(str(lowerCAmelCase_       ) for i in range(1    ,11       )       )

						linked_list.insert_at_head(0       )
						linked_list.insert_at_tail(11       )
						assert str(lowerCAmelCase_       ) == "->".join(str(lowerCAmelCase_       ) for i in range(0    ,12       )       )

						assert linked_list.delete_head() == 0
						assert linked_list.delete_at_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       )       )


if __name__ == "__main__":
	from doctest import testmod

	testmod()









from .prime_check import Test

Test()




