Skip to content
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
43 changes: 43 additions & 0 deletions treap/README.mbt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Treap

Randomized binary search tree for MoonBit. Each node stores a randomly assigned
priority so the structure stays balanced in expectation, while still behaving
like an ordered map keyed by `Compare` values.

## Highlights
- Generic in both key and value types; only requires `Compare` on keys.
- Supports `insert`, `get`, `contains`, `remove`, `clear`, `len`, and `is_empty`.
- Deterministic pseudo-random priorities keep the tree reproducible in tests.

## Quick Start
```moonbit
test "README treap usage" {
let treap : Treap[Int, String] = Treap::new()
treap.insert(8, "eight")
treap.insert(3, "three")
treap.insert(5, "five")
assert_eq(treap.len(), 3)
assert_eq(treap.get(5), Some("five"))
assert_eq(treap.contains(7), false)

treap.insert(5, "FIVE")
assert_eq(treap.get(5), Some("FIVE"))
assert_eq(treap.remove(3), true)
assert_eq(treap.contains(3), false)

treap.clear()
assert_eq(treap.is_empty(), true)
}
```

## API Overview
- `Treap::new()` – construct an empty treap.
- `insert(key, value)` – upsert a key/value pair.
- `get(key)` – retrieve the stored value or `None`.
- `contains(key)` – boolean membership query.
- `remove(key)` – delete the entry if present.
- `clear()` – empty the structure while retaining capacity.
- `len()` / `is_empty()` – observe current occupancy.

> ℹ️ The internal priority generator is deterministic, making results stable
> across runs while still preserving the balancing guarantees of treaps.
1 change: 1 addition & 0 deletions treap/README.md
1 change: 1 addition & 0 deletions treap/moon.pkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
226 changes: 226 additions & 0 deletions treap/treap.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
///|
struct Node[K, V] {
key : K
mut value : V
priority : Int
mut left : Node[K, V]?
mut right : Node[K, V]?
}

///|
fn[K, V] Node::new(key : K, value : V, priority : Int) -> Node[K, V] {
Node::{ key, value, priority, left: None, right: None }
}

///|
fn[K : Compare, V] split(
node_opt : Node[K, V]?,
key : K,
) -> (Node[K, V]?, Node[K, V]?) {
match node_opt {
None => (None, None)
Some(node_value) => {
let node = node_value
if key.compare(node.key) < 0 {
let (less, greater) = split(node.left, key)
node.left = greater
(less, Some(node))
} else {
let (less, greater) = split(node.right, key)
node.right = less
(Some(node), greater)
}
}
}
}

///|
fn[K : Compare, V] merge(
left_opt : Node[K, V]?,
right_opt : Node[K, V]?,
) -> Node[K, V]? {
match (left_opt, right_opt) {
(None, right_side) => right_side
(left_side, None) => left_side
(Some(left_value), Some(right_value)) => {
let left = left_value
let right = right_value
if left.priority > right.priority {
let merged = merge(left.right, Some(right))
left.right = merged
Some(left)
} else {
let merged = merge(Some(left), right.left)
right.left = merged
Some(right)
}
}
}
}

///|
fn[K : Compare, V] insert_node(
node_opt : Node[K, V]?,
key : K,
value : V,
priority : Int,
) -> (Node[K, V]?, Bool) {
match node_opt {
None => (Some(Node::new(key, value, priority)), true)
Some(node_value) => {
let node = node_value
let cmp = key.compare(node.key)
if cmp == 0 {
node.value = value
(Some(node), false)
} else if priority > node.priority {
let (less, greater) = split(Some(node), key)
let new_node = Node::new(key, value, priority)
new_node.left = less
new_node.right = greater
(Some(new_node), true)
} else if cmp < 0 {
let (new_left, inserted) = insert_node(node.left, key, value, priority)
node.left = new_left
(Some(node), inserted)
} else {
let (new_right, inserted) = insert_node(
node.right,
key,
value,
priority,
)
node.right = new_right
(Some(node), inserted)
}
}
}
}

///|
fn[K : Compare, V] remove_node(
node_opt : Node[K, V]?,
key : K,
) -> (Node[K, V]?, Bool) {
match node_opt {
None => (None, false)
Some(node_value) => {
let node = node_value
let cmp = key.compare(node.key)
if cmp == 0 {
let merged = merge(node.left, node.right)
(merged, true)
} else if cmp < 0 {
let (new_left, removed) = remove_node(node.left, key)
node.left = new_left
(Some(node), removed)
} else {
let (new_right, removed) = remove_node(node.right, key)
node.right = new_right
(Some(node), removed)
}
}
}
}

///|
fn[K : Compare, V] find_node(node_opt : Node[K, V]?, key : K) -> V? {
match node_opt {
None => None
Some(node_value) => {
let node = node_value
let cmp = key.compare(node.key)
if cmp == 0 {
Some(node.value)
} else if cmp < 0 {
find_node(node.left, key)
} else {
find_node(node.right, key)
}
}
}
}

///|
pub struct Treap[K, V] {
mut root : Node[K, V]?
mut size : Int
mut rng_state : Int
}

///|
pub fn[K, V] Treap::new() -> Treap[K, V] {
Treap::{ root: None, size: 0, rng_state: 123_456_789 }
}

///|
pub fn[K, V] len(self : Treap[K, V]) -> Int {
self.size
}

///|
pub fn[K, V] is_empty(self : Treap[K, V]) -> Bool {
self.size == 0
}

///|
pub fn[K, V] clear(self : Treap[K, V]) -> Unit {
self.root = None
self.size = 0
}

///|
fn[K, V] Treap::next_priority(self : Treap[K, V]) -> Int {
let modulus = 2_147_483_647
let mut state = (self.rng_state * 1_103_515_245 + 12_345) % modulus
if state < 0 {
state = -state
}
if state == 0 {
state = 1
}
self.rng_state = state
state
}

///|
pub fn[K : Compare, V] Treap::insert(
self : Treap[K, V],
key : K,
value : V,
) -> Unit {
let priority = self.next_priority()
let (new_root, inserted) = insert_node(self.root, key, value, priority)
self.root = new_root
if inserted {
self.size = self.size + 1
}
}

///|
pub fn[K : Compare, V] Treap::get(self : Treap[K, V], key : K) -> V? {
find_node(self.root, key)
}

///|
pub fn[K : Compare, V] Treap::contains(self : Treap[K, V], key : K) -> Bool {
match self.get(key) {
Some(_) => true
None => false
}
}

///|
pub fn[K : Compare, V] Treap::remove(self : Treap[K, V], key : K) -> Bool {
let (new_root, removed) = remove_node(self.root, key)
self.root = new_root
if removed {
self.size = self.size - 1
}
removed
}

///|
pub impl[K, V] Default for Treap[K, V] with default() {
Treap::new()
}
29 changes: 29 additions & 0 deletions treap/treap.mbti
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Generated using `moon info`, DON'T EDIT IT
package "Lampese/Algorithms-Moonbit/treap"

// Values

// Errors

// Types and methods
type Node[K, V]

pub struct Treap[K, V] {
mut root : Node[K, V]?
mut size : Int
mut rng_state : Int
}
fn[K, V] Treap::clear(Self[K, V]) -> Unit
fn[K : Compare, V] Treap::contains(Self[K, V], K) -> Bool
fn[K : Compare, V] Treap::get(Self[K, V], K) -> V?
fn[K : Compare, V] Treap::insert(Self[K, V], K, V) -> Unit
fn[K, V] Treap::is_empty(Self[K, V]) -> Bool
fn[K, V] Treap::len(Self[K, V]) -> Int
fn[K, V] Treap::new() -> Self[K, V]
fn[K : Compare, V] Treap::remove(Self[K, V], K) -> Bool
impl[K, V] Default for Treap[K, V]

// Type aliases

// Traits

80 changes: 80 additions & 0 deletions treap/treap_test.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
///|
test "treap basic operations" {
let treap : Treap[Int, Int] = Treap::new()
assert_eq(treap.is_empty(), true)
treap.insert(10, 100)
treap.insert(5, 50)
treap.insert(20, 200)
assert_eq(treap.len(), 3)
assert_eq(treap.is_empty(), false)
assert_eq(treap.get(10), Some(100))
assert_eq(treap.get(5), Some(50))
assert_eq(treap.get(20), Some(200))
assert_eq(treap.contains(15), false)
}

///|
test "treap duplicate update preserves size" {
let treap : Treap[Int, String] = Treap::new()
treap.insert(1, "one")
treap.insert(2, "two")
treap.insert(3, "three")
assert_eq(treap.len(), 3)
treap.insert(2, "TWO")
assert_eq(treap.len(), 3)
assert_eq(treap.get(2), Some("TWO"))
}

///|
test "treap removal cases" {
let treap : Treap[Int, Int] = Treap::new()
let values = [7, 3, 10, 1, 5, 9, 12]
for value in values {
treap.insert(value, value * 2)
}
assert_eq(treap.len(), values.length())
assert_eq(treap.remove(3), true)
assert_eq(treap.contains(3), false)
assert_eq(treap.remove(10), true)
assert_eq(treap.contains(10), false)
assert_eq(treap.remove(8), false)
assert_eq(treap.len(), values.length() - 2)
assert_eq(treap.get(9), Some(18))
assert_eq(treap.get(12), Some(24))
}

///|
test "treap clear resets structure" {
let treap : Treap[Int, Int] = Treap::default()
for value in [1, 2, 3, 4, 5] {
treap.insert(value, value)
}
assert_eq(treap.len(), 5)
treap.clear()
assert_eq(treap.len(), 0)
assert_eq(treap.is_empty(), true)
assert_eq(treap.get(3), None)
assert_eq(treap.remove(3), false)
}

///|
test "treap handles larger sequence" {
let treap : Treap[Int, Int] = Treap::new()
for value in 0..<100 {
treap.insert(value, value)
}
assert_eq(treap.len(), 100)
for value in 0..<100 {
assert_eq(treap.get(value), Some(value))
}
for value in 0..<50 {
assert_eq(treap.remove(value), true)
}
assert_eq(treap.len(), 50)
for value in 0..<50 {
assert_eq(treap.contains(value), false)
}
for value in 50..<100 {
assert_eq(treap.contains(value), true)
}
}
Loading