Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uSTL: Queue, Deque and Pair #39

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
105 changes: 105 additions & 0 deletions examples/udeque.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# UDeque

## Introduction

UDeque is class which is simplifying working with deque.
bleudev marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (documentation): Typo in UDeque Introduction

UDeque is a class which simplifies working with deque.

It has many methods, properties, magic methods.
bleudev marked this conversation as resolved.
Show resolved Hide resolved

Firstly, import `UDeque` from `ufpy`
```python
from ufpy import UDeque
```

## Create UDeque

For creating UDeque you should use this code:
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d = UDeque((1, 2, 3, 4, 5))
```

## Get end/begin

To get end you can use:
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d[0] # 1
d.end() # 1
```

To get begin you can use:
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d[1] # 5
d.begin() # 5
```

> [!NOTE]
> 0 - first element
> 1 - last element
Comment on lines +34 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (documentation): Clarification in UDeque Get end/begin Section

Clarify that 0 refers to the first element and 1 refers to the last element in the context of the end and begin methods.

Suggested change
> 0 - first element
> 1 - last element
> 0 - refers to the first element
> 1 - refers to the last element


## Add end/begin

To add end you can use
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d.addend(6) # [1, 2, 3, 4, 5, 6]
```

To add begin you can use
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d.addbegin(0) # [0, 1, 2, 3, 4, 5, 6]
```

## Set end/begin

To set end you can use
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d.setend(7) # [0, 1, 2, 3, 4, 5, 7]
```

To set begin you can use
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d.setbegin(7) # [7, 1, 2, 3, 4, 5, 7]
```
> [!NOTE]
> Also you can use indexes:
> ```python
> d[0] = 1 # [1, 1, 2, 3, 4, 5, 7]
> d[1] = 1 # [1, 1, 2, 3, 4, 5, 1]
> ```
> But it is undesirable to use
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (documentation): Clarification in UDeque Add end/begin Section

Expand on why it is undesirable to use indexes directly.

Suggested change
> But it is undesirable to use
> But it is undesirable to use indexes directly because it can lead to errors and reduce code readability. Instead, consider using methods provided by the deque class to manipulate elements.


## Delete end/begin

For deleting end use
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d.popend() # [7, 1, 2, 3, 4, 5]
```

For deleting begin use
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
d.popbegin(7) # [1, 2, 3, 4, 5]
```

> [!NOTE]
> To delete end or begin you also can use `del`:
> ```python
> del d[0] # [2, 3, 4, 5]
> del d[1] # [2, 3, 4]
> ```
> But it is undesirable to use

## Get length of deque

You can get length of dict using inbuilt `len()` function
bleudev marked this conversation as resolved.
Show resolved Hide resolved

```python
d2 = UDeque((1, 2, 3, 4, 5))
len(d2) # 5
```

## Reserve
To reserve deque's end and begin use inbuilt `reserved()` function
bleudev marked this conversation as resolved.
Show resolved Hide resolved
```python
reserved(d2) # [5, 1]
```

> [!NOTE]
> `reserved()` returns `[end, begin]`
88 changes: 88 additions & 0 deletions ufpy/udeque.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from __future__ import annotations
from typing import TypeVar, Generic, Iterable, Any

__all__ = (
"UDeque"
)

VT = TypeVar("VT")

class UDeque(Generic[VT]):
def __init__(self, __list: Iterable[VT] = []):
bleudev marked this conversation as resolved.
Show resolved Hide resolved
bleudev marked this conversation as resolved.
Show resolved Hide resolved
self.__list = list(__list)

def addend(self, value: VT):
self.__list.append(value)

def addbegin(self, value: VT):
self.__list.insert(0, value)

def popend(self):
return self.__list.pop()

def popbegin(self):
return self.__list.pop(0)

def setend(self, value: VT):
bleudev marked this conversation as resolved.
Show resolved Hide resolved
self[1] = value

def setbegin(self, value: VT):
bleudev marked this conversation as resolved.
Show resolved Hide resolved
self[0] = value

def end(self) -> VT:
if self:
return self.__list[-1]
else:
return None
bleudev marked this conversation as resolved.
Show resolved Hide resolved
bleudev marked this conversation as resolved.
Show resolved Hide resolved
bleudev marked this conversation as resolved.
Show resolved Hide resolved

def begin(self) -> VT:
if self:
return self.__list[0]
else:
return None
bleudev marked this conversation as resolved.
Show resolved Hide resolved

def copy(self) -> UDeque:
return UDeque(self.__list.copy())

def is_empty(self) -> bool:
return len(self) == 0

def reversed(self) -> UDeque:
return self.__reversed__()
bleudev marked this conversation as resolved.
Show resolved Hide resolved

def __len__(self) -> int:
return len(self.__list)

def __nonzero__(self) -> bool:
return not self.is_empty()

def __getitem__(self, index: Any) -> VT:
if isinstance(index, int):
if index in (0, 1):
return self.__list[index]
else:
raise IndexError(f"{index} out of range (0, 1)")
bleudev marked this conversation as resolved.
Show resolved Hide resolved
bleudev marked this conversation as resolved.
Show resolved Hide resolved
bleudev marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Incorrect index range check in getitem

The index range check in __getitem__ should allow for any valid index within the list, not just 0 and 1. This will cause an IndexError for valid indices beyond 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Incorrect index range check in setitem

The index range check in __setitem__ should allow for any valid index within the list, not just 0 and 1. This will cause an IndexError for valid indices beyond 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Incorrect index range check in delitem

The index range check in __delitem__ should allow for any valid index within the list, not just 0 and 1. This will cause an IndexError for valid indices beyond 1.


def __setitem__(self, index: int, value: VT):
if isinstance(index, int):
if index == 0:
self.__list[index] = value
elif index == 1:
self.__list[-index] = value
else:
raise IndexError(f"{index} out of range (0, 1)")

def __delitem__(self, index: int):
if isinstance(index, int):
if index == 0:
del self.__list[index]
elif index == 1:
del self.__list[-index]
else:
raise IndexError(f"{index} out of range (0, 1)")

def __reversed__(self) -> UDeque:
return UDeque((self.end(), self.begin()))
bleudev marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +87 to +88
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Incorrect reversed implementation

The __reversed__ method should return a deque with elements in reverse order, not just the end and begin elements.


def __str__(self) -> str:
return str(self.__list)
Loading