diff --git a/exercises/ex14/dllist.py b/exercises/ex14/dllist.py new file mode 100644 index 0000000..92d988b --- /dev/null +++ b/exercises/ex14/dllist.py @@ -0,0 +1,134 @@ +class DoubleLinkedListNode(object): + def __init__(self, value, prev, nxt): + self.value = value + self.next = nxt + self.prev = prev + + def __repr__(self): + nval = self.next and self.next.value or None + pval = self.prev and self.prev.value or None + return f"[{repr(pval)}, {self.value}, {repr(nval)}]" + + +class DoubleLinkedList(object): + def __init__(self): + self.begin = None + self.end = None + + def count(self): + """ + Returns number of items. + Regresa la cantidad de ítems. + """ + count = 0 + node = self.begin + while node: + count += 1 + node = node.next + return count + + def push(self, obj): + """ + Appends a new item on the end of the list. + Añade un nuevo ítem al final de la lista. + """ + node = DoubleLinkedListNode(obj, self.end, None) + if self.begin is None: + self.begin = node + self.end = self.begin + else: + self.end.next = node + self.end = node + + def pop(self): + """ + Removes the last item and returns its value. + Remueve el último ítem y regresa su valor. + """ + if self.end is None: + value = None + else: + value = self.end.value + if self.end == self.begin: + self.end = self.begin = None + else: + self.end = self.end.prev + self.end.next = None + return value + + def unshift(self): + """ + Removes the first item and returns its value. + Remueve el primer ítem y regresa su valor. + """ + if self.begin is None: + value = None + else: + value = self.begin.value + if self.begin == self.end: + self.begin = self.end = None + else: + self.begin = self.begin.next + self.begin.prev = None + return value + + def shift(self, obj): + """ + Appends a new item on the begin of the list. + Añade un nuevo ítem al inicio de la lista. + """ + node = DoubleLinkedListNode(obj, None, self.begin) + if self.begin is None: + self.begin = node + self.end = self.begin + else: + self.begin.prev = node + self.begin = node + + def remove(self, obj): + """ + Removes a item by its value and return its list index. + Remueve un ítem según su valor y regresa su índice en la lista. + """ + count = 0 + node = self.begin + while node.next: + if obj == node.value: + break + count += 1 + node = node.next + if node.next: + node.value = node.next.value + node.next = node.next.next + else: + node.value = node.next = node.prev = node = None + return count + + def get(self, index): + """ + Returns item value at list index. + Regresa el valor del ítem en el índice de la lista. + """ + count = 0 + node = self.begin + while count != index: + count += 1 + node = node.next + if node: + return node.value + else: + return None + + def first(self): + """ + Returns value of first item. + Regresa el valor del primer ítem. + """ + return self.begin.value + + def last(self): + """ + Returns value of last item. + Regresa el valor del último ítem. + """ + return self.end.value diff --git a/exercises/ex14/test_dllist.py b/exercises/ex14/test_dllist.py new file mode 100644 index 0000000..b30d884 --- /dev/null +++ b/exercises/ex14/test_dllist.py @@ -0,0 +1,97 @@ +from dllist import DoubleLinkedList + + +def test_push(): + colors = DoubleLinkedList() + colors.push("Pthalo Blue") + assert colors.count() == 1 + colors.push("Ultramarine Blue") + assert colors.count() == 2 + + +def test_pop(): + colors = DoubleLinkedList() + colors.push("Magenta") + colors.push("Alizarin") + assert colors.pop() == "Alizarin" + assert colors.count() == 1 + assert colors.pop() == "Magenta" + assert colors.count() == 0 + assert colors.pop() is None + + +def test_get(): + colors = DoubleLinkedList() + colors.push("Vermillion") + assert colors.get(0) == "Vermillion" + colors.push("Sap Green") + assert colors.get(0) == "Vermillion" + assert colors.get(1) == "Sap Green" + colors.push("Cadmium Yellow Light") + assert colors.get(0) == "Vermillion" + assert colors.get(1) == "Sap Green" + assert colors.get(2) == "Cadmium Yellow Light" + assert colors.pop() == "Cadmium Yellow Light" + assert colors.get(0) == "Vermillion" + assert colors.get(1) == "Sap Green" + assert colors.get(2) is None + colors.pop() + assert colors.get(0) == "Vermillion" + colors.pop() + assert colors.get(0) is None + + +def test_unshift(): + colors = DoubleLinkedList() + colors.push("Viridian") + colors.push("Sap Green") + colors.push("Van Dyke") + assert colors.unshift() == "Viridian" + assert colors.unshift() == "Sap Green" + assert colors.unshift() == "Van Dyke" + assert colors.unshift() is None + assert colors.count() == 0 + + +def test_shift(): + colors = DoubleLinkedList() + colors.shift("Cadmium Orange") + assert colors.count() == 1 + colors.shift("Carbazole Violet") + assert colors.count() == 2 + assert colors.pop() == "Cadmium Orange" + assert colors.count() == 1 + assert colors.pop() == "Carbazole Violet" + assert colors.count() == 0 + + +def test_first(): + colors = DoubleLinkedList() + colors.push("Cadmium Red Light") + assert colors.first() == "Cadmium Red Light" + colors.push("Hansa Yellow") + assert colors.first() == "Cadmium Red Light" + colors.shift("Pthalo Green") + assert colors.first() == "Pthalo Green" + + +def test_last(): + colors = DoubleLinkedList() + colors.push("Cadmium Red Light") + assert colors.last() == "Cadmium Red Light" + colors.push("Hansa Yellow") + assert colors.last() == "Hansa Yellow" + colors.shift("Pthalo Green") + assert colors.last() == "Hansa Yellow" + + +def test_remove(): + colors = DoubleLinkedList() + colors.push("Cobalt") + colors.push("Zinc White") + colors.push("Nickle Yellow") + colors.push("Perinone") + assert colors.remove("Cobalt") == 0 + assert colors.remove("Perinone") == 2 + assert colors.remove("Nickle Yellow") == 1 + assert colors.remove("Zinc White") == 0