2025-01-19 13:03:16 +00:00
|
|
|
signature MAKE_BIN_VEC =
|
|
|
|
|
sig
|
|
|
|
|
type elem
|
|
|
|
|
|
|
|
|
|
val l: elem * elem -> bool
|
|
|
|
|
val eq: elem * elem -> bool
|
|
|
|
|
val g: elem * elem -> bool
|
|
|
|
|
end
|
|
|
|
|
|
2025-01-19 12:06:56 +00:00
|
|
|
signature BIN_VEC =
|
|
|
|
|
sig
|
2025-01-19 13:03:16 +00:00
|
|
|
type elem
|
|
|
|
|
|
|
|
|
|
val empty: elem vector
|
2025-01-22 18:22:34 +00:00
|
|
|
val isEmpty: elem vector -> bool
|
2025-01-19 13:03:16 +00:00
|
|
|
|
|
|
|
|
val sub: elem vector * int -> elem
|
2025-01-19 21:32:17 +00:00
|
|
|
val contains: elem * elem vector -> bool
|
2025-01-22 18:22:34 +00:00
|
|
|
val findMin: elem vector -> elem
|
2025-01-19 13:03:16 +00:00
|
|
|
|
|
|
|
|
val findInsPos: elem * elem vector -> int
|
|
|
|
|
val insert: elem vector * elem * int -> elem vector
|
|
|
|
|
val delete: elem vector * elem -> elem vector
|
2025-01-22 18:22:34 +00:00
|
|
|
val deleteMin: elem vector -> elem vector
|
2025-01-19 23:56:52 +00:00
|
|
|
val updateAtIdx: elem vector * elem * int -> elem vector
|
2025-01-20 12:23:30 +00:00
|
|
|
|
|
|
|
|
val fromList: elem list -> elem vector
|
2025-01-19 12:06:56 +00:00
|
|
|
end
|
|
|
|
|
|
2025-01-19 13:03:16 +00:00
|
|
|
functor MakeBinVec(Fn: MAKE_BIN_VEC): BIN_VEC =
|
2025-01-19 12:06:56 +00:00
|
|
|
struct
|
2025-01-19 13:03:16 +00:00
|
|
|
type elem = Fn.elem
|
2025-01-19 12:06:56 +00:00
|
|
|
|
2025-01-19 13:03:16 +00:00
|
|
|
val empty = Vector.fromList []
|
2025-01-19 12:06:56 +00:00
|
|
|
|
2025-01-22 18:22:34 +00:00
|
|
|
fun isEmpty vec = Vector.length vec = 0
|
|
|
|
|
|
|
|
|
|
fun deleteMin vec =
|
|
|
|
|
if Vector.length vec <= 1 then
|
|
|
|
|
Vector.fromList []
|
|
|
|
|
else
|
|
|
|
|
let
|
2025-01-30 12:55:36 +00:00
|
|
|
val len = Vector.length vec - 1
|
2025-01-22 18:22:34 +00:00
|
|
|
val slice = VectorSlice.slice (vec, 1, SOME len)
|
|
|
|
|
in
|
|
|
|
|
VectorSlice.vector slice
|
|
|
|
|
end
|
|
|
|
|
|
2025-01-19 13:03:16 +00:00
|
|
|
val sub = Vector.sub
|
2025-01-19 12:06:56 +00:00
|
|
|
|
2025-01-22 18:22:34 +00:00
|
|
|
fun findMin vec = Vector.sub (vec, 0)
|
|
|
|
|
|
2025-01-19 12:06:56 +00:00
|
|
|
fun reverseLinearSearch (pos, findNum, vec) =
|
|
|
|
|
if pos < 0 then
|
|
|
|
|
~1
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val curNum = Vector.sub (vec, pos)
|
|
|
|
|
in
|
2025-01-20 12:23:30 +00:00
|
|
|
if Fn.l (findNum, curNum) then pos
|
2025-01-19 12:06:56 +00:00
|
|
|
else reverseLinearSearch (pos - 1, findNum, vec)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
fun forwardLinearSearch (pos, findNum, vec) =
|
|
|
|
|
if pos = Vector.length vec then
|
|
|
|
|
Vector.length vec
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val curNum = Vector.sub (vec, pos)
|
|
|
|
|
in
|
2025-01-20 12:23:30 +00:00
|
|
|
if Fn.g (findNum, curNum) then pos + 1
|
2025-01-19 12:06:56 +00:00
|
|
|
else forwardLinearSearch (pos + 1, findNum, vec)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
fun helpFindInsPos (findNum, vec, low, high, prevMid) =
|
|
|
|
|
if high >= low then
|
|
|
|
|
let
|
|
|
|
|
val mid = low + ((high - low) div 2)
|
|
|
|
|
val curNum = Vector.sub (vec, mid)
|
|
|
|
|
in
|
2025-01-19 13:03:16 +00:00
|
|
|
if Fn.eq (curNum, findNum) then
|
2025-01-19 12:06:56 +00:00
|
|
|
mid
|
2025-01-19 13:03:16 +00:00
|
|
|
else if Fn.l (curNum, findNum) then
|
2025-01-19 12:06:56 +00:00
|
|
|
helpFindInsPos (findNum, vec, mid + 1, high, mid)
|
|
|
|
|
else
|
|
|
|
|
helpFindInsPos (findNum, vec, low, mid - 1, mid)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val curNum = Vector.sub (vec, prevMid)
|
|
|
|
|
in
|
2025-01-20 12:23:30 +00:00
|
|
|
if Fn.g (findNum, curNum) then
|
2025-01-19 13:03:16 +00:00
|
|
|
forwardLinearSearch (prevMid, findNum, vec)
|
|
|
|
|
else
|
|
|
|
|
reverseLinearSearch (prevMid, findNum, vec)
|
2025-01-19 12:06:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
fun findInsPos (findNum, vec) =
|
|
|
|
|
if Vector.length vec = 0 then ~1
|
|
|
|
|
else helpFindInsPos (findNum, vec, 0, Vector.length vec - 1, 0)
|
|
|
|
|
|
2025-01-19 21:32:17 +00:00
|
|
|
fun helpContains (findNum, vec, low, high) =
|
|
|
|
|
if high >= low then
|
|
|
|
|
let
|
|
|
|
|
val mid = low + ((high - low) div 2)
|
|
|
|
|
val curNum = Vector.sub (vec, mid)
|
|
|
|
|
in
|
|
|
|
|
if Fn.eq (curNum, findNum) then
|
|
|
|
|
true
|
|
|
|
|
else if Fn.l (curNum, findNum) then
|
|
|
|
|
helpContains (findNum, vec, mid + 1, high)
|
|
|
|
|
else
|
|
|
|
|
helpContains (findNum, vec, low, mid - 1)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
false
|
|
|
|
|
|
|
|
|
|
fun contains (findNum, vec) =
|
|
|
|
|
if Vector.length vec = 0 then false
|
|
|
|
|
else helpContains (findNum, vec, 0, Vector.length vec - 1)
|
|
|
|
|
|
2025-01-19 13:03:16 +00:00
|
|
|
(* insPos parameter should be the unmodified result of calling findInsPos.
|
|
|
|
|
* The reason the insert function does not call findInsPos directly is so,
|
|
|
|
|
* if two BinVecs are used (one for keys and another for values like a map)
|
|
|
|
|
* then the insert function can be used for both the key vector and value
|
|
|
|
|
* vector *)
|
|
|
|
|
fun insert (vec, elem, insPos) =
|
|
|
|
|
if insPos < 0 then
|
|
|
|
|
Vector.concat [Vector.fromList [elem], vec]
|
|
|
|
|
else if insPos = Vector.length vec then
|
|
|
|
|
Vector.concat [vec, Vector.fromList [elem]]
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val elem = Vector.fromList [elem]
|
|
|
|
|
val elem = VectorSlice.full elem
|
2025-01-19 12:06:56 +00:00
|
|
|
|
2025-01-19 13:03:16 +00:00
|
|
|
val s2len = Vector.length vec - insPos
|
|
|
|
|
val slice1 = VectorSlice.slice (vec, 0, SOME insPos)
|
|
|
|
|
val slice2 = VectorSlice.slice (vec, insPos, SOME s2len)
|
|
|
|
|
in
|
|
|
|
|
VectorSlice.concat [slice1, elem, slice2]
|
|
|
|
|
end
|
2025-01-19 12:06:56 +00:00
|
|
|
|
2025-01-19 13:03:16 +00:00
|
|
|
fun delete (vec, elem: elem) =
|
2025-01-19 12:06:56 +00:00
|
|
|
let
|
|
|
|
|
val insPos = findInsPos (elem, vec)
|
|
|
|
|
in
|
|
|
|
|
if insPos < 0 orelse insPos = Vector.length vec then
|
|
|
|
|
vec
|
|
|
|
|
else
|
|
|
|
|
let
|
|
|
|
|
val slice1 = VectorSlice.slice (vec, 0, SOME insPos)
|
|
|
|
|
|
|
|
|
|
val slice2Len = Vector.length vec - insPos - 1
|
|
|
|
|
val slice2 = VectorSlice.slice (vec, insPos + 1, SOME slice2Len)
|
|
|
|
|
in
|
|
|
|
|
VectorSlice.concat [slice1, slice2]
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-01-19 23:56:52 +00:00
|
|
|
|
|
|
|
|
fun updateAtIdx (vec, elem, idx) =
|
|
|
|
|
Vector.mapi
|
|
|
|
|
(fn (curIdx, curElem) => if curIdx <> idx then curElem else elem) vec
|
2025-01-20 12:23:30 +00:00
|
|
|
|
|
|
|
|
fun helpFromList ([], acc) = acc
|
|
|
|
|
| helpFromList (hd :: tl, acc) =
|
|
|
|
|
let
|
|
|
|
|
val pos = findInsPos (hd, acc)
|
|
|
|
|
val acc = insert (acc, hd, pos)
|
|
|
|
|
in
|
|
|
|
|
helpFromList (tl, acc)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
fun fromList lst = helpFromList (lst, empty)
|
2025-01-19 12:06:56 +00:00
|
|
|
end
|
2025-01-19 13:03:16 +00:00
|
|
|
|
2025-01-19 21:32:17 +00:00
|
|
|
structure IntSet =
|
2025-01-19 13:03:16 +00:00
|
|
|
MakeBinVec
|
|
|
|
|
(struct
|
|
|
|
|
type elem = int
|
|
|
|
|
|
|
|
|
|
val l = Int.<
|
|
|
|
|
fun eq (a, b) = a = b
|
|
|
|
|
val g = Int.>
|
|
|
|
|
end)
|
2025-01-19 22:45:51 +00:00
|
|
|
|
|
|
|
|
structure ValSet =
|
|
|
|
|
MakeBinVec
|
|
|
|
|
(struct
|
2025-01-20 11:17:00 +00:00
|
|
|
type elem = {distance: int, from: int}
|
2025-01-19 22:45:51 +00:00
|
|
|
|
2025-01-19 23:56:52 +00:00
|
|
|
(* l, e and q functions are not actually used in the ValSet
|
|
|
|
|
* because the IntSet is meant to contain keys while the ValSet
|
|
|
|
|
* is meant to contain corresponding values, like in a Map structure.
|
|
|
|
|
* However, it's required by the functor,
|
|
|
|
|
* and it is actually easy to implement so no issue. *)
|
2025-01-19 22:45:51 +00:00
|
|
|
|
2025-01-19 23:56:52 +00:00
|
|
|
fun l ({distance = a, ...}: elem, {distance = b, ...}: elem) = a < b
|
2025-01-19 22:45:51 +00:00
|
|
|
|
2025-01-19 23:56:52 +00:00
|
|
|
fun eq ({distance = a, ...}: elem, {distance = b, ...}: elem) = a = b
|
2025-01-19 22:45:51 +00:00
|
|
|
|
2025-01-19 23:56:52 +00:00
|
|
|
fun g ({distance = a, ...}: elem, {distance = b, ...}: elem) = a > b
|
2025-01-19 22:45:51 +00:00
|
|
|
end)
|
2025-01-22 18:22:34 +00:00
|
|
|
|
|
|
|
|
structure DistVec =
|
|
|
|
|
MakeBinVec
|
|
|
|
|
(struct
|
|
|
|
|
type elem = {distance: int, id: int, comesFrom: int}
|
|
|
|
|
|
|
|
|
|
fun l ({distance = a, ...}: elem, {distance = b, ...}: elem) = a < b
|
|
|
|
|
|
|
|
|
|
fun eq ({distance = a, ...}: elem, {distance = b, ...}: elem) = a = b
|
|
|
|
|
|
|
|
|
|
fun g ({distance = a, ...}: elem, {distance = b, ...}: elem) = a > b
|
|
|
|
|
end)
|
2025-01-31 03:46:28 +00:00
|
|
|
|
|
|
|
|
structure PlatSet =
|
|
|
|
|
MakeBinVec
|
|
|
|
|
(struct
|
|
|
|
|
type elem = {distance: int, id: int}
|
|
|
|
|
|
|
|
|
|
fun l ({id = a, ...}: elem, {id = b, ...}: elem) = a < b
|
|
|
|
|
|
|
|
|
|
fun eq ({id = a, ...}: elem, {id = b, ...}: elem) = a = b
|
|
|
|
|
|
|
|
|
|
fun g ({id = a, ...}: elem, {id = b, ...}: elem) = a > b
|
|
|
|
|
end)
|