forked from Neterukun1993/purely-functional-data-structures
-
Notifications
You must be signed in to change notification settings - Fork 0
/
list_stack.py
69 lines (55 loc) · 1.77 KB
/
list_stack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
from __future__ import annotations
from typing import TypeVar, Generic, Optional, Iterator
from src.basic.meta_singleton import MetaSingleton # type: ignore
T = TypeVar('T')
class ListStack(Generic[T], metaclass=MetaSingleton):
_head: T
_tail: ListStack[T]
def __init__(self,
head: Optional[T] = None,
tail: Optional[ListStack[T]] = None) -> None:
if head is not None:
self._head = head
if tail is not None:
self._tail = tail
def __bool__(self) -> bool:
return self is not ListStack[T]()
def __iter__(self) -> Iterator[T]:
ptr = self
while ptr:
yield ptr.head()
ptr = ptr.tail()
def cons(self, value: T) -> ListStack[T]:
return ListStack[T](value, self)
def head(self) -> T:
if self is ListStack[T]():
raise IndexError("head from empty list")
return self._head
def tail(self) -> ListStack[T]:
if self is ListStack[T]():
raise IndexError("tail from empty list")
return self._tail
def reverse(self) -> ListStack[T]:
ret = ListStack[T]()
for x in self:
ret = ret.cons(x)
return ret
def concat(self, other: ListStack[T]) -> ListStack[T]:
ret = other
for x in self.reverse():
ret = ret.cons(x)
return ret
def take(self, n: int) -> ListStack[T]:
ret = ListStack[T]()
for i, x in enumerate(self):
if i == n:
break
ret = ret.cons(x)
return ret.reverse()
def drop(self, n: int) -> ListStack[T]:
ret = self
for _ in range(n):
if not ret:
break
ret = ret.tail()
return ret