ANSI_COLOR_RESET = "\x1b[0m" ANSI_COLOR_YELLOW = "\x1b[33m" ANSI_BOLD = "\x1b[1m" ANSI_COLOR_GREEN = "\x1b[32m" CONSOLE_COLOR_DEFAULT = ANSI_COLOR_RESET CONSOLE_COLOR_PROMPT = ANSI_COLOR_YELLOW CONSOLE_COLOR_USER_INPUT = ANSI_BOLD + ANSI_COLOR_GREEN # Iterative search # Actively searches and prevents a pattern from being returned class IterSearch: def __init__(self, pattern): self.pattern = list(pattern) self.buffer = [] def __call__(self, char): self.buffer += [char] if self.pattern[: len(self.buffer)] == self.buffer: if len(self.buffer) >= len(self.pattern): self.buffer.clear() return [] _tmp = self.buffer[:] self.buffer.clear() return _tmp class Circle: def __init__(self, size, default=0): self.list = [default] * size self.maxsize = size self.size = 0 self.offset = 0 def append(self, elem): if self.size < self.maxsize: self.list[self.size] = elem self.size += 1 else: self.list[self.offset] = elem self.offset = (self.offset + 1) % self.maxsize def __getitem__(self, val): if isinstance(val, int): if 0 > val or val >= self.size: raise IndexError("Index out of range") return ( self.list[val] if self.size < self.maxsize else self.list[(self.offset + val) % self.maxsize] ) elif isinstance(val, slice): start, stop, step = val.start, val.stop, val.step if step is None: step = 1 if start is None: start = 0 if stop is None: stop = self.size if start < 0: start = self.size + start if stop < 0: stop = self.size + stop indices = range(start, stop, step) return [ self.list[(self.offset + i) % self.maxsize] for i in indices if i < self.size ] else: raise TypeError("Invalid argument type") if __name__ == "__main__": c = Circle(5) c.append(1) print(c.list) print(c[:]) assert c[0] == 1 assert c[:5] == [1] for i in range(2, 5 + 1): c.append(i) print(c.list) print(c[:]) assert c[0] == 1 assert c[:5] == [1, 2, 3, 4, 5] for i in range(5 + 1, 9 + 1): c.append(i) print(c.list) print(c[:]) assert c[0] == 5 assert c[:5] == [5, 6, 7, 8, 9] # assert c[:-5] == [5,6,7,8,9] assert c[:10] == [5, 6, 7, 8, 9]