154 lines
3.9 KiB
Standard ML
154 lines
3.9 KiB
Standard ML
signature SEARCH_LIST =
|
|
sig
|
|
type t = {left: int vector list, right: int vector list}
|
|
val empty: t
|
|
|
|
val exists: int * t -> bool
|
|
val insert: int * t -> t
|
|
val append: int * t -> t
|
|
val delete: int * int * string * t -> t
|
|
|
|
val goToNum: int * t -> t
|
|
val mapFrom: int * int * t -> t
|
|
|
|
val toVector: t -> int vector
|
|
val toString: t -> string
|
|
end
|
|
|
|
structure SearchList : SEARCH_LIST =
|
|
struct
|
|
structure IntSet = MakeGapSet (
|
|
struct
|
|
type key = int
|
|
|
|
val maxNodeSize = 32
|
|
|
|
fun l (a: int, b) = a < b
|
|
fun eq (a: int, b) = a = b
|
|
fun g (a: int, b) = a > b
|
|
end
|
|
)
|
|
|
|
type t = IntSet.t
|
|
|
|
fun helpToVector (left, right) =
|
|
case left of
|
|
hd :: tl => helpToVector (tl, hd :: right)
|
|
| [] => Vector.concat right
|
|
|
|
(* for testing *)
|
|
fun toVector {left, right} = helpToVector (left, right)
|
|
|
|
|
|
val empty = IntSet.empty
|
|
|
|
fun insert (num, set) =
|
|
let
|
|
val () = print ("adding num: " ^ Int.toString num ^ "\n")
|
|
in
|
|
IntSet.add (num, set)
|
|
end
|
|
|
|
val append = IntSet.add
|
|
|
|
val goToNum = IntSet.moveTo
|
|
|
|
fun delete (start, length, searchString, set) =
|
|
if length > 0 then
|
|
let
|
|
val firstVec = toVector set
|
|
val finish = start + length
|
|
val start = start - String.size searchString + 1
|
|
val result = IntSet.removeMany (start, finish, set)
|
|
|
|
val secondVec = toVector result
|
|
|
|
val () = print ("delete start has " ^ Int.toString (Vector.length
|
|
firstVec) ^ "elements\n")
|
|
val () = print ("delete result has " ^ Int.toString (Vector.length
|
|
secondVec) ^ "elements\n")
|
|
in
|
|
result
|
|
end
|
|
else
|
|
set
|
|
|
|
fun isLessThanTarget (v1, v2) =
|
|
Vector.length v1 + Vector.length v2 <= 32
|
|
|
|
fun joinEndOfLeft (new, left) =
|
|
case left of
|
|
hd :: tail =>
|
|
if isLessThanTarget (new, hd) then
|
|
let val newHd = Vector.concat [hd, new]
|
|
in newHd :: tail
|
|
end
|
|
else
|
|
new :: left
|
|
| [] => new :: left
|
|
|
|
(* go all the way to the end of the list, mapping each hd,
|
|
* joining the hd to the left,
|
|
* and return when we have reached the end *)
|
|
fun mapRight (mapBy, left, right) =
|
|
case right of
|
|
hd :: tl =>
|
|
let val newHd = Vector.map (fn el => el + mapBy) hd
|
|
in mapRight (mapBy, joinEndOfLeft (newHd, left), tl)
|
|
end
|
|
| [] => {left = left, right = right}
|
|
|
|
fun moveRightAndMap (from, mapBy, left, right) =
|
|
case right of
|
|
hd :: tl =>
|
|
let
|
|
val lastIdx = Vector.length hd - 1
|
|
val last = Vector.sub (hd, lastIdx)
|
|
in
|
|
if from > last then
|
|
moveRightAndMap (from, mapBy, joinEndOfLeft (hd, left), tl)
|
|
else if from < last then
|
|
(* need to map in middle *)
|
|
let
|
|
val startIdx = BinSearch.equalOrMore (from, hd)
|
|
val mapEl = Vector.sub (hd, startIdx)
|
|
val newHd =
|
|
Vector.map (fn el => if el < from then el else el + mapBy) hd
|
|
in
|
|
mapRight (mapBy, joinEndOfLeft (newHd, left), tl)
|
|
end
|
|
else
|
|
(* from = last *)
|
|
let
|
|
val newHd =
|
|
Vector.map (fn el => if el < from then el else el + mapBy) hd
|
|
in
|
|
mapRight (mapBy, joinEndOfLeft (newHd, left), tl)
|
|
end
|
|
end
|
|
| [] => {left = left, right = right}
|
|
|
|
fun mapFrom (num, mapBy, lst) =
|
|
let
|
|
(* goToNum always places vector where num was found to the right list *)
|
|
val () = print ("mapping by " ^ Int.toString num ^ "\n")
|
|
val {left, right} = goToNum (0, lst)
|
|
in
|
|
moveRightAndMap (num, 0, left, right)
|
|
end
|
|
|
|
val exists = IntSet.exists
|
|
|
|
fun toString {left, right} =
|
|
let
|
|
val vec = toVector {left = left, right = right}
|
|
|
|
val () = print ("toString has " ^ Int.toString (Vector.length vec) ^
|
|
"elements\n")
|
|
|
|
val strList = Vector.foldr (fn (num, acc) => Int.toString num :: acc) [] vec
|
|
in
|
|
""
|
|
end
|
|
end
|