Skip to content

Commit 646a42f

Browse files
authored
implement generics in sparse table (#27)
1 parent 68ffdc7 commit 646a42f

File tree

4 files changed

+41
-36
lines changed

4 files changed

+41
-36
lines changed

st/st.mbt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
///|
2-
struct ST {
2+
struct ST[T] {
33
n : Int
4-
f : Array[Array[Int]]
4+
f : Array[Array[T]]
5+
op: (T, T) -> T
56
}
67

78
///| Build Sparse Table
@@ -17,21 +18,21 @@ struct ST {
1718
/// # Example
1819
/// ```
1920
/// let arr = [1,2,3,4,5,6,1,2]
20-
/// let _ = st(arr)
21+
/// let _ = from(arr, @cmp.maximum)
2122
/// ```
22-
pub fn st(data : Array[Int]) -> ST {
23+
pub fn[T: Default] from(data : Array[T], op: (T, T) -> T) -> ST[T] {
2324
let n = data.length()
2425
let range : Int = @math.log2(n.to_double()).to_int() + 1
25-
let f = make_2d(n + 1, range)
26+
let f: Array[Array[T]] = Array::makei(n+1, fn(_row: Int) {Array::make(range, T::default())} )
2627
for i = 0; i < n; i = i + 1 {
2728
f[i + 1][0] = data[i]
2829
}
2930
for j = 1; j <= range - 1; j = j + 1 {
3031
for i = 1; i + (1 << j) - 1 <= n; i = i + 1 {
31-
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1])
32+
f[i][j] = op(f[i][j - 1], f[i + (1 << (j - 1))][j - 1])
3233
}
3334
}
34-
ST::{ n, f }
35+
ST::{ n, f, op}
3536
}
3637
3738
///| Build Binary Indexed Tree
@@ -47,16 +48,16 @@ pub fn st(data : Array[Int]) -> ST {
4748
/// # Example
4849
/// ```
4950
/// let arr = [1,2,3,4,5,6,1,2]
50-
/// let st= @st.st(arr)
51-
/// inspect(st.max_elem(1, 1), content="1")
52-
/// inspect(st.max_elem(2, 8), content="6")
51+
/// let st= from(arr, @cmp.maximum)
52+
/// inspect(st.query(1, 1), content="1")
53+
/// inspect(st.query(2, 8), content="6")
5354
/// ```
54-
pub fn max_elem(self : ST, left : Int, right : Int) -> Int {
55+
pub fn[T] query(self : ST[T], left : Int, right : Int) -> T{
5556
if right < left {
5657
abort("Invalid range.")
5758
} else if left > self.n || right < 1 {
5859
abort("Range out of bounds.")
5960
}
6061
let k = @math.log2((right - left + 1).to_double()).to_int()
61-
max(self.f[left][k], self.f[right - (1 << k) + 1][k])
62+
(self.op)(self.f[left][k], self.f[right - (1 << k) + 1][k])
6263
}

st/st.mbti

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
package "Lampese/Algorithms-Moonbit/st"
33

44
// Values
5-
fn st(Array[Int]) -> ST
5+
fn[T : Default] st(Array[T], (T, T) -> T) -> ST[T]
66

77
// Types and methods
8-
type ST
9-
fn ST::max_elem(Self, Int, Int) -> Int
8+
type ST[T]
9+
fn[T] ST::query(Self[T], Int, Int) -> T
1010

1111
// Type aliases
1212

st/st_test.mbt

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
11
///|
2-
test {
2+
test "max query" {
33
let arr = [1, 2, 3, 4, 5, 6, 1, 2]
4-
let st = st(arr)
5-
inspect(st.max_elem(1, 1), content="1")
6-
inspect(st.max_elem(2, 8), content="6")
4+
let st = from(arr, @cmp.maximum)
5+
inspect(st.query(1, 1), content="1")
6+
inspect(st.query(2, 8), content="6")
7+
}
8+
///|
9+
test "min query" {
10+
let arr = [1, 2, 3, 4, 5, 6, 1, 2]
11+
let st = from(arr, @cmp.minimum)
12+
inspect(st.query(1, 1), content="1")
13+
inspect(st.query(2, 8), content="1")
14+
}
15+
///|
16+
test "gcd query" {
17+
fn gcd(a: Int, b: Int) -> Int {
18+
if b==0 {
19+
a
20+
} else {
21+
gcd(b, a%b)
22+
}
23+
}
24+
let arr = [4, 8, 16, 24, 48, 3]
25+
let st = from(arr, gcd)
26+
inspect(st.query(1, 2), content="4")
27+
inspect(st.query(3, 5), content="8")
728
}

st/utils.mbt

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)