///|
typealias Stack as Pile
///|
priv struct Piles[T](Array[Pile[T]])
///|
fn[T] is_empty(self : Piles[T]) -> Bool {
self.inner().is_empty()
}
///|
fn[T] put_back(self : Piles[T], singleton : T) -> Unit {
self.inner().push(Stack::{ top: singleton, stack: @list.empty() })
}
///|
fn[T] last(self : Piles[T]) -> Pile[T]? {
self.inner().last()
}
///|
fn[T] op_get(self : Piles[T], i : Int) -> Pile[T] {
self.inner()[i]
}
///|
fn put_by_binary_search(
self : Piles[BackPointer[(Int, Int)]],
new_idx~ : Int,
place~ : Int,
) -> Unit {
let mut lo = -1
let mut hi = self.inner().length()
while lo + 1 < hi {
let mid = (lo + hi) / 2
if self[mid].top.value.0 < new_idx {
lo = mid
} else {
hi = mid
}
}
if lo >= 0 {
let prev = Some(self[lo].top)
if lo + 1 < self.inner().length() {
self[lo + 1].push(BackPointer::{ value: (new_idx, place), prev })
} else {
self.put_back(BackPointer::{ value: (new_idx, place), prev })
}
}
}