code: from __future__ import annotations
  
  from collections.abc import Iterable
  from dataclasses import dataclass
  from typing import Any
  
  
  class _lowercase					:
  
  
  
  
  
         """simple docstring"""
  
  
  
  
         lowerCAmelCase__       =					('_front', '_back', '_len')
  
  
         @dataclass
         class _lowercase					:
  
  
  
  
  
                """simple docstring"""
  
  
  
  
                lowerCAmelCase__       =					None
                lowerCAmelCase__       =					None
                lowerCAmelCase__       =					None
  
  
  
  
  
  
         class _lowercase					:
  
  
  
  
  
                """simple docstring"""
  
  
  
  
                lowerCAmelCase__       =					('_cur',)
  
  
  
                def __init__(    self     ,   UpperCAmelCase  ):
  
  
  
  
  
  
  
                       '''simple docstring'''
  
  
  
  
  
  
                       _lowercase				=	cur
  
  
  
                def __iter__(    self  ):
  
  
  
  
  
  
  
                       '''simple docstring'''
  
  
  
  
  
  
                       return self
  
  
  
                def     _UpperCAmelCase       (    self  ):
  
  
  
  
  
  
  
                       '''simple docstring'''
  
  
  
  
  
  
                       if self._cur is None:
                              # finished iterating
                              raise StopIteration
                       _lowercase				=	self._cur.val
                       _lowercase				=	self._cur.next_node
  
                       return val
  
  
  
  
  
  
         def __init__(    self     ,   UpperCAmelCase = None  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                _lowercase				=	None
                _lowercase				=	None
                _lowercase				=	0
  
                if iterable is not None:
                       # append every value to the deque
                       for val in iterable:
                              self.append(a_  )
  
  
  
         def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                _lowercase				=	self._Node(a_     ,   a_     ,   a_  )
                if self.is_empty():
                       # front = back
                       _lowercase				=	_lowercase				=	node
                       _lowercase				=	1
                else:
                       # connect nodes
                       _lowercase				=	node
                       _lowercase				=	self._back
                       _lowercase				=	node  # assign new back to the new node
  
                       self._len += 1
  
                       # make sure there were no errors
                       assert not self.is_empty(), "Error on appending value."
  
  
  
         def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                _lowercase				=	self._Node(a_     ,   a_     ,   a_  )
                if self.is_empty():
                       # front = back
                       _lowercase				=	_lowercase				=	node
                       _lowercase				=	1
                else:
                       # connect nodes
                       _lowercase				=	self._front
                       _lowercase				=	node
                       _lowercase				=	node  # assign new front to the new node
  
                       self._len += 1
  
                       # make sure there were no errors
                       assert not self.is_empty(), "Error on appending value."
  
  
  
         def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                for val in iterable:
                       self.append(a_  )
  
  
  
         def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                for val in iterable:
                       self.appendleft(a_  )
  
  
  
         def     _UpperCAmelCase       (    self  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                assert not self.is_empty(), "Deque is empty."
  
                _lowercase				=	self._back
                _lowercase				=	self._back.prev_node  # set new back
                # drop the last node - python will deallocate memory automatically
                _lowercase				=	None
  
                self._len -= 1
  
                return topop.val
  
  
  
         def     _UpperCAmelCase       (    self  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                assert not self.is_empty(), "Deque is empty."
  
                _lowercase				=	self._front
                _lowercase				=	self._front.next_node  # set new front and drop the first node
                _lowercase				=	None
  
                self._len -= 1
  
                return topop.val
  
  
  
         def     _UpperCAmelCase       (    self  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                return self._front is None
  
  
  
         def __len__(    self  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                return self._len
  
  
  
         def __eq__(    self     ,   UpperCAmelCase  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                if not isinstance(a_     ,   a_  ):
                       return NotImplemented
  
                _lowercase				=	self._front
                _lowercase				=	other._front
  
                # if the length of the dequeues are not the same, they are not equal
                if len(self  ) != len(a_  ):
                       return False
  
                while me is not None and oth is not None:
                       # compare every value
                       if me.val != oth.val:
                              return False
                       _lowercase				=	me.next_node
                       _lowercase				=	oth.next_node
  
                return True
  
  
  
         def __iter__(    self  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                return Deque._Iterator(self._front  )
  
  
  
         def __repr__(    self  ):
  
  
  
  
  
  
  
                '''simple docstring'''
  
  
  
  
  
  
                _lowercase				=	[]
                _lowercase				=	self._front
                while aux is not None:
                       # append the values in a list to display
                       values_list.append(aux.val  )
                       _lowercase				=	aux.next_node
  
                return F'''[{", ".join(repr(a_  ) for val in values_list  )}]'''
  
  
  if __name__ == "__main__":
      import doctest
  
      doctest.testmod()
  
  
  
style_context: import numpy as np
  
  
  def 					__lowerCAmelCase			(  _A ,_A="utf-8" ,_A="surrogatepass"					):
  
  
  
  							"""simple docstring"""
  
  
  							_lowercase				=	bin(int.from_bytes(text.encode(_A ,_A					) ,"""big"""					)					)[2:]
  							return bits.zfill(8 * ((len(_A					) + 7) // 8)					)
  
  
  def 					__lowerCAmelCase			(  _A ,_A="utf-8" ,_A="surrogatepass"					):
  
  
  
  							"""simple docstring"""
  
  
  							_lowercase				=	int(_A ,2					)
  							return n.to_bytes((n.bit_length() + 7) // 8 ,"""big"""					).decode(_A ,_A					) or "\0"
  
  
  def 					__lowerCAmelCase			(  _A ,_A					):
  
  
  
  							"""simple docstring"""
  
  
  							if size_par + len(_A					) <= 2**size_par - (len(_A					) - 1):
  														raise ValueError("""size of parity don't match with size of data"""					)
  
  							_lowercase				=	[]
  							_lowercase				=	[]
  							_lowercase				=	[bin(_A					)[2:] for x in range(1 ,size_par + len(_A					) + 1					)]
  
  							# sorted information data for the size of the output data
  							_lowercase				=	[]
  							# data position template + parity
  							_lowercase				=	[]
  							# parity bit counter
  							_lowercase				=	0
  							# counter position of data bits
  							_lowercase				=	0
  
  							for x in range(1 ,size_par + len(_A					) + 1					):
  														# Performs a template of bit positions - who should be given,
  														# and who should be parity
  														if qtd_bp < size_par:
  																					if (np.log(_A					) / np.log(2					)).is_integer():
  																												data_out_gab.append("""P"""					)
  																												_lowercase				=	qtd_bp + 1
  																					else:
  																												data_out_gab.append("""D"""					)
  														else:
  																					data_out_gab.append("""D"""					)
  
  														# Sorts the data to the new output size
  														if data_out_gab[-1] == "D":
  																					data_ord.append(data[cont_data]					)
  																					cont_data += 1
  														else:
  																					data_ord.append(_A					)
  
      # Calculates parity
  							_lowercase				=	0  # parity bit counter
  							for bp in range(1 ,size_par + 1					):
  														# Bit counter one for a given parity
  														_lowercase				=	0
  														# counter to control the loop reading
  														_lowercase				=	0
  														for x in data_ord:
  																					if x is not None:
  																												try:
  																																			_lowercase				=	(bin_pos[cont_loop])[-1 * (bp)]
  																												except IndexError:
  																																			_lowercase				=	"""0"""
  																												if aux == "1" and x == "1":
  																																			cont_bo += 1
  																					cont_loop += 1
  														parity.append(cont_bo % 2					)
  
  														qtd_bp += 1
  
  							# Mount the message
  							_lowercase				=	0  # parity bit counter
  							for x in range(0 ,size_par + len(_A					)					):
  														if data_ord[x] is None:
  																					data_out.append(str(parity[cont_bp]					)					)
  																					cont_bp += 1
  														else:
  																					data_out.append(data_ord[x]					)
  
  							return data_out
  
  
  def 					__lowerCAmelCase			(  _A ,_A					):
  
  
  
  							"""simple docstring"""
  
  
  							_lowercase				=	[]
  							# Parity bit counter
  							_lowercase				=	0
  							# Counter p data bit reading
  							_lowercase				=	0
  							# list of parity received
  							_lowercase				=	[]
  							_lowercase				=	[]
  
  							for x in range(1 ,len(_A					) + 1					):
  														# Performs a template of bit positions - who should be given,
  														#  and who should be parity
  														if qtd_bp < size_par and (np.log(_A					) / np.log(2					)).is_integer():
  																					data_out_gab.append("""P"""					)
  																					_lowercase				=	qtd_bp + 1
  														else:
  																					data_out_gab.append("""D"""					)
  
  														# Sorts the data to the new output size
  														if data_out_gab[-1] == "D":
  																					data_output.append(data[cont_data]					)
  														else:
  																					parity_received.append(data[cont_data]					)
  														cont_data += 1
  
  							# -----------calculates the parity with the data
  							_lowercase				=	[]
  							_lowercase				=	[]
  							_lowercase				=	[bin(_A					)[2:] for x in range(1 ,size_par + len(_A					) + 1					)]
  
  							#  sorted information data for the size of the output data
  							_lowercase				=	[]
  							# Data position feedback + parity
  							_lowercase				=	[]
  							# Parity bit counter
  							_lowercase				=	0
  							# Counter p data bit reading
  							_lowercase				=	0
  
  							for x in range(1 ,size_par + len(_A					) + 1					):
  														# Performs a template position of bits - who should be given,
  														# and who should be parity
  														if qtd_bp < size_par and (np.log(_A					) / np.log(2					)).is_integer():
  																					data_out_gab.append("""P"""					)
  																					_lowercase				=	qtd_bp + 1
  														else:
  																					data_out_gab.append("""D"""					)
  
  														# Sorts the data to the new output size
  														if data_out_gab[-1] == "D":
  																					data_ord.append(data_output[cont_data]					)
  																					cont_data += 1
  														else:
  																					data_ord.append(_A					)
  
      # Calculates parity
  							_lowercase				=	0  # parity bit counter
  							for bp in range(1 ,size_par + 1					):
  														# Bit counter one for a certain parity
  														_lowercase				=	0
  														# Counter to control loop reading
  														_lowercase				=	0
  														for x in data_ord:
  																					if x is not None:
  																												try:
  																																			_lowercase				=	(bin_pos[cont_loop])[-1 * (bp)]
  																												except IndexError:
  																																			_lowercase				=	"""0"""
  																												if aux == "1" and x == "1":
  																																			cont_bo += 1
  																					cont_loop += 1
  														parity.append(str(cont_bo % 2					)					)
  
  														qtd_bp += 1
  
  							# Mount the message
  							_lowercase				=	0  # Parity bit counter
  							for x in range(0 ,size_par + len(_A					)					):
  														if data_ord[x] is None:
  																					data_out.append(str(parity[cont_bp]					)					)
  																					cont_bp += 1
  														else:
  																					data_out.append(data_ord[x]					)
  
  							_lowercase				=	parity_received == parity
  							return data_output, ack
  
  
  