Olá José Henriques
É só uma sugestão, mas eu colocaria o conteúdo da pergunta na pergunta e não no corpo da resposta.
Vi a sua solução. O código é muito interessante, mas acho que tem alguns problemas. Por exemplo, você mencionou na resposta que o método first()
"é usada para subconjunto de períodos iniciais de dados de série temporal com base em um deslocamento de data". Porém, esse método não está definido na classe.
Outro problema foi quando você levantou a excessão nos métodos dequeue e rotate.
if self.is_empty(): raise Empty('The queue is empty')
Se eu não me engano, a excessão levantada deve pertencer à classe Exception (veja este link). Ela não pode ser simplemente Empty.
Deixo abaixo uma solução minha.
A implementação ArrayQueue é uma classe para filas que o autor do livro escreve no capítulo 6. Ela é:
class ArrayQueue(object):
DEFAULT_CAPACITY = 10
def __init__(self):
#Cria um fila vazia
self._data = [None]*ArrayQueue.DEFAULT_CAPACITY
self._size = 0
self._front = 0
def __len__(self):
#Retorna o numero de elementos da fila
return self._size
def is_empty(self):
#Retorn True se a fila esta vazia
return self._size == 0
def first(self):
#Retorna sem remover o primeiro elemento
if self.is_empty():
raise Exception("Queue is empty")
return self._data[self._front]
def dequeue(self):
#Remove o retorna o primeiro elemento
if self.is_empty():
raise Exception("Queue is empty")
answer = self._data[self._front]
self._data[self._front] = None
self._front = (self._front + 1)%len(self._data)
self._size -= 1
return answer
def enqueue(self, e):
#Adiciona um elemento ao fim da fila
if self._size == len(self._data):
self._resize(2*len(self._data))
avail = (self._front + self._size)%len(self._data)
self._data[avail] = e
self._size += 1
def _resize(self, cap):
#Aumenta o tamanho da fila para maior que len(self)
old = self._data
self._data = [None]*cap
walk = self._front
for k in range(self._size):
self._data[k] = old[walk]
walk = (1+walk)%len(old)
self._front = 0
Vamos modificar essa classe para introduzir dois novos métodos. Primeiro vamos reescrever o método print para que possamos imprimir as listas e ver o que está acontecento. Depois vamos escrever o método rotate(). A classe modificada é:
class ArrayQueue(object):
DEFAULT_CAPACITY = 10
def __init__(self):
#Cria um fila vazia
self._data = [None]*ArrayQueue.DEFAULT_CAPACITY
self._size = 0
self._front = 0
def __len__(self):
#Retorna o numero de elementos da fila
return self._size
def is_empty(self):
#Retorn True se a fila esta vazia
return self._size == 0
def first(self):
#Retorna sem remover o primeiro elemento
if self.is_empty():
raise Exception("Queue is empty")
return self._data[self._front]
def dequeue(self):
#Remove o retorna o primeiro elemento
if self.is_empty():
raise Exception("Queue is empty")
answer = self._data[self._front]
self._data[self._front] = None
self._front = (self._front + 1)%len(self._data)
self._size -= 1
return answer
def enqueue(self, e):
#Adiciona um elemento ao fim da fila
if self._size == len(self._data):
self._resize(2*len(self._data))
avail = (self._front + self._size)%len(self._data)
self._data[avail] = e
self._size += 1
def _resize(self, cap):
#Aumenta o tamanho da fila para maior que len(self)
old = self._data
self._data = [None]*cap
walk = self._front
for k in range(self._size):
self._data[k] = old[walk]
walk = (1+walk)%len(old)
self._front = 0
def __str__(self):
#Imprime a fila
separator = ", "
return "[" + separator.join([str(i) for i in self._data]) + "]"
def rotate(self):
#metodo que equivale a enqueue(dequeue))
if self.is_empty():
raise Exception("Queue is empty")
answer = self._data[self._front]
self._data[self._front] = None
self._front = (self._front + 1)%len(self._data)
avail = (self._front + self._size -1)%len(self._data)
self._data[avail] = answer
O método str nos permite imprimir a fila de maneira similar a uma lista em Python. A vantagem é que ele mostra também os slots ainda não ocupados. Já o método rotate() é a resposta o exercício. Note que ele é quase uma combinação dos métodos enqueue() e dequeue(), mas é mais eficiente, pois não é necessário modificar _size.
Podemos testar o método rotate() com o seguinte código:
if __name__ == "__main__":
fila1 = ArrayQueue()
fila1.enqueue("a")
fila1.enqueue("b")
fila1.enqueue("c")
print("###fila1###")
print(fila1)
print("###enqueue(dequeue))###")
fila1.enqueue(fila1.dequeue())
print(fila1)
fila2 = ArrayQueue()
fila2.enqueue("a")
fila2.enqueue("b")
fila2.enqueue("c")
print("###fila2###")
print(fila2)
print("###rotate()###")
fila2.rotate()
Criamos uma fila chamada fila1 e colocamos as strings "a", "b" e "c". Imprimimos a fila e depois usamos enqueue(dequeue()). Depois criamos outra fila chamada fila2 e colocamos os mesmos elementos. Aplicamos então o método rotate() e verificamos que o resultado final é o mesmo que usar enqueue(dequeue()). O output é:
###fila1###
[a, b, c, None, None, None, None, None, None, None]
###enqueue(dequeue))###
[None, b, c, a, None, None, None, None, None, None]
###fila2###
[a, b, c, None, None, None, None, None, None, None]
###rotate()###
[None, b, c, a, None, None, None, None, None, None]