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

feat: add more function to deque #77

Merged
merged 3 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions deque/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ dq.front() // Some(2)
dq.length() // 3
```

If you only want to pop an element without getting the return value, you can use `pop_front_exn()` with `pop_back_exn()`.
These two functions will panic if the queue is empty.

```moonbit
let dq = Deque::[1, 2, 3, 4, 5]
dq.pop_front_exn()
dq.front() // Some(2)
dq.pop_back_exn()
dq.back() // Some(3)
```

### Clear

You can use `clear` to clear a deque. But note that the memory it already occupies does not change.
Expand Down Expand Up @@ -122,12 +133,15 @@ deque supports vector-like `iter/iteri/map/mapi` functions and their inverse for
dq.mapi(fn(i, elem) { elem + i })
```

### TODO List
### Search & Contains

You can use `contains()` to find out if a value is in the deque, or `search()` to find its index in the deque.

```moonbit
let dq = Deque::[1, 2, 3, 4, 5]
dq.contains(1) // true
dq.contains(6) // false
dq.search(1) // Some(0)
dq.search(6) // None
```

- [ ] fold/foldr
- [ ] reverse
- [ ] contains
- [ ] search
- [ ] swap
- [ ] resize
- [ ] fill
96 changes: 90 additions & 6 deletions deque/deque.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,38 @@ pub fn push_back[T](self : Deque[T], value : T) -> Unit {
self.len += 1
}

/// Removes a fornt element from a deque.
///
/// Panics if the deque is empty.
/// # Example
/// ```
/// let dq = Deque::[1, 2, 3, 4, 5]
/// dq.pop_front_exn()
/// ```
pub fn pop_front_exn[T](self : Deque[T]) -> Unit {
if self.len == 0 {
abort("The deque is empty!")
bobzhang marked this conversation as resolved.
Show resolved Hide resolved
}
self.head = if self.head < self.buf.length() - 1 { self.head + 1 } else { 0 }
self.len -= 1
}

/// Removes a back element from a deque.
///
/// Panics if the deque is empty.
/// # Example
/// ```
/// let dq = Deque::[1, 2, 3, 4, 5]
/// dq.pop_back_exn()
/// ```
pub fn pop_back_exn[T](self : Deque[T]) -> Unit {
if self.len == 0 {
bobzhang marked this conversation as resolved.
Show resolved Hide resolved
abort("The deque is empty!")
}
self.tail = if self.tail > 0 { self.tail - 1 } else { self.buf.length() - 1 }
self.len -= 1
}

/// Removes a fornt element from a deque and returns it, or `None` if it is empty.
///
/// # Example
Expand Down Expand Up @@ -228,9 +260,11 @@ test "push_and_pop" {
/// println(dq[2]) // 3
/// ```
pub fn op_get[T](self : Deque[T], index : Int) -> T {
if index >= self.len {
if index < 0 || index >= self.len {
let len = self.len
abort("index out of bounds: the len is \(len) but the index is \(index)")
abort(
"index out of bounds: the len is from 0 to \(len) but the index is \(index)",
)
}
if self.head + index < self.buf.length() {
self.buf[self.head + index]
Expand Down Expand Up @@ -263,9 +297,11 @@ test "op_get" {
/// println(dq[2]) // 1
/// ```
pub fn op_set[T](self : Deque[T], index : Int, value : T) -> Unit {
if index >= self.len {
if index < 0 || index >= self.len {
let len = self.len
abort("index out of bounds: the len is \(len) but the index is \(index)")
abort(
"index out of bounds: the len is from 0 to \(len) but the index is \(index)",
)
}
if self.head + index < self.buf.length() {
self.buf[self.head + index] = value
Expand Down Expand Up @@ -317,8 +353,8 @@ test "iter" {

test "iter2" {
let v = Deque::[1, 2, 3, 4, 5]
v.pop_front() |> ignore
v.pop_back() |> ignore
v.pop_front_exn()
v.pop_back_exn()
let mut sum = 0
v.iter(fn { x => sum += x })
@assertion.assert_eq(sum, 9)?
Expand Down Expand Up @@ -489,3 +525,51 @@ test "is_empty" {
dq.push_back(3)
@assertion.assert_false(dq.is_empty())?
}

/// Search the deque index for a given element.
///
/// # Example
/// ```
/// let dq = Deque::[3, 4, 5]
/// dq.search(3) // Some(0)
/// ```
pub fn search[T : Eq](self : Deque[T], value : T) -> Option[Int] {
for i = 0; i < self.len; i = i + 1 {
if self.buf[i] == value {
return Some(i)
}
}
None
}

test "search" {
let dq = Deque::[3, 4, 5]
@assertion.assert_eq(dq.search(3), Some(0))?
@assertion.assert_eq(dq.search(4), Some(1))?
@assertion.assert_eq(dq.search(5), Some(2))?
@assertion.assert_eq(dq.search(6), None)?
}

/// Checks if the vector contains an element.
///
/// # Example
/// ```
/// let dq = Deque::[3, 4, 5]
/// dq.contains(3) // true
/// ```
pub fn contains[T : Eq](self : Deque[T], value : T) -> Bool {
for i = 0; i < self.len; i = i + 1 {
if self.buf[i] == value {
return true
}
}
false
}

test "contains" {
let dq = Deque::[3, 4, 5]
@assertion.assert_true(dq.contains(3))?
@assertion.assert_true(dq.contains(4))?
@assertion.assert_true(dq.contains(5))?
@assertion.assert_false(dq.contains(6))?
}