add 'SearchList.exists' function to fcore/search-list.sml function, and make sure we check if mmatchedIdx exists before inserting or appending (so we maintain set-like semantics where each number exists only once)
This commit is contained in:
@@ -69,4 +69,28 @@ struct
|
|||||||
fun equalOrMore (findNum, vec) =
|
fun equalOrMore (findNum, vec) =
|
||||||
helpBinSearch (findNum, vec, 0, Vector.length vec - 1)
|
helpBinSearch (findNum, vec, 0, Vector.length vec - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local
|
||||||
|
fun helpExists (findNum, vec, low, high) =
|
||||||
|
let
|
||||||
|
val mid = low + ((high - low) div 2)
|
||||||
|
in
|
||||||
|
if high >= low then
|
||||||
|
let
|
||||||
|
val midVal = Vector.sub (vec, mid)
|
||||||
|
in
|
||||||
|
if midVal = findNum then
|
||||||
|
true
|
||||||
|
else if midVal < findNum then
|
||||||
|
helpExists (findNum, vec, mid + 1, high)
|
||||||
|
else
|
||||||
|
helpExists (findNum, vec, low, mid - 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
in
|
||||||
|
fun exists (findNum, vec) =
|
||||||
|
helpExists (findNum, vec, 0, Vector.length vec - 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ struct
|
|||||||
case tl of
|
case tl of
|
||||||
tlhd :: tltl =>
|
tlhd :: tltl =>
|
||||||
helpNextMatch (0, tlhd, tltl, absIdx, searchString, matchedChrs)
|
helpNextMatch (0, tlhd, tltl, absIdx, searchString, matchedChrs)
|
||||||
| [] =>
|
| [] => NONE
|
||||||
NONE
|
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val hdChr = String.sub (hd, idx)
|
val hdChr = String.sub (hd, idx)
|
||||||
@@ -14,10 +13,8 @@ struct
|
|||||||
in
|
in
|
||||||
if hdChr = searchChr then
|
if hdChr = searchChr then
|
||||||
if matchedChrs + 1 = String.size searchString then
|
if matchedChrs + 1 = String.size searchString then
|
||||||
let
|
let val matchedIdx = absIdx - String.size searchString + 1
|
||||||
val matchedIdx = absIdx - String.size searchString + 1
|
in SOME matchedIdx
|
||||||
in
|
|
||||||
SOME matchedIdx
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
helpNextMatch
|
helpNextMatch
|
||||||
@@ -36,13 +33,11 @@ struct
|
|||||||
helpNextMatch (strIdx, hd, tl, absIdx, searchString, 0)
|
helpNextMatch (strIdx, hd, tl, absIdx, searchString, 0)
|
||||||
else
|
else
|
||||||
(case tl of
|
(case tl of
|
||||||
tlhd :: tltl =>
|
tlhd :: tltl =>
|
||||||
let
|
let val strIdx = strIdx - String.size hd
|
||||||
val strIdx = strIdx - String.size hd
|
in helpNextMatch (strIdx, tlhd, tltl, absIdx, searchString, 0)
|
||||||
in
|
end
|
||||||
helpNextMatch (strIdx, tlhd, tltl, absIdx, searchString, 0)
|
| [] => NONE)
|
||||||
end
|
|
||||||
| [] => NONE)
|
|
||||||
end
|
end
|
||||||
| [] => NONE
|
| [] => NONE
|
||||||
|
|
||||||
@@ -53,12 +48,26 @@ struct
|
|||||||
in
|
in
|
||||||
case nextMatch (bufferIdx, absIdx, rightStrings, searchString) of
|
case nextMatch (bufferIdx, absIdx, rightStrings, searchString) of
|
||||||
SOME matchedIdx =>
|
SOME matchedIdx =>
|
||||||
let
|
(* Edge case: we may be searching for a string like "a"
|
||||||
val searchList = SearchList.append (matchedIdx, searchList)
|
* when the buffer represents "aaa aaa aaa".
|
||||||
in
|
* In this case, there will be continual matches that are consecutive
|
||||||
|
* and we need to check every char in the buffer which is absIdx + 1.
|
||||||
|
* However, we can skip to matchedIdx + 1 if matchedIdx already exists
|
||||||
|
* in the searchList because we know the string between
|
||||||
|
* [absIdx ... matchedIdx - 1] contains no matches.
|
||||||
|
* This check is important to preserve the set-like semaantics
|
||||||
|
* of the searchList too: SearchList.append does not check for this.
|
||||||
|
* *)
|
||||||
|
if SearchList.exists (matchedIdx, searchList) then
|
||||||
helpFromStart
|
helpFromStart
|
||||||
(app, origIdx, matchedIdx + 1, buffer, searchString, searchList)
|
(app, origIdx, matchedIdx + 1, buffer, searchString, searchList)
|
||||||
end
|
else
|
||||||
|
let
|
||||||
|
val searchList = SearchList.append (matchedIdx, searchList)
|
||||||
|
in
|
||||||
|
helpFromStart
|
||||||
|
(app, origIdx, absIdx + 1, buffer, searchString, searchList)
|
||||||
|
end
|
||||||
| NONE =>
|
| NONE =>
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToIdx (origIdx, buffer)
|
val buffer = LineGap.goToIdx (origIdx, buffer)
|
||||||
@@ -82,36 +91,44 @@ struct
|
|||||||
(* searches for matchedIdx within a range from the buffer instead of from start *)
|
(* searches for matchedIdx within a range from the buffer instead of from start *)
|
||||||
fun helpFromRange
|
fun helpFromRange
|
||||||
(origIdx, curIdx, finishIdx, buffer, searchString, searchList) =
|
(origIdx, curIdx, finishIdx, buffer, searchString, searchList) =
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToIdx (curIdx, buffer)
|
val buffer = LineGap.goToIdx (curIdx, buffer)
|
||||||
val {idx = bufferIdx, rightStrings, ...} = buffer
|
val {idx = bufferIdx, rightStrings, ...} = buffer
|
||||||
in
|
in
|
||||||
case nextMatch (bufferIdx, curIdx, rightStrings, searchString) of
|
case nextMatch (bufferIdx, curIdx, rightStrings, searchString) of
|
||||||
SOME matchedIdx =>
|
SOME matchedIdx =>
|
||||||
if matchedIdx > finishIdx then
|
if matchedIdx > finishIdx then
|
||||||
let
|
|
||||||
val buffer = LineGap.goToIdx (origIdx, buffer)
|
|
||||||
val searchList = SearchList.goToNum (origIdx, searchList)
|
|
||||||
in
|
|
||||||
(buffer, searchList)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val searchList = SearchList.insert (matchedIdx, searchList)
|
|
||||||
in
|
|
||||||
helpFromRange
|
|
||||||
( origIdx, matchedIdx + 1, finishIdx
|
|
||||||
, buffer, searchString, searchList
|
|
||||||
)
|
|
||||||
end
|
|
||||||
| NONE =>
|
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToIdx (origIdx, buffer)
|
val buffer = LineGap.goToIdx (origIdx, buffer)
|
||||||
val searchList = SearchList.goToNum (origIdx, searchList)
|
val searchList = SearchList.goToNum (origIdx, searchList)
|
||||||
in
|
in
|
||||||
(buffer, searchList)
|
(buffer, searchList)
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
let
|
||||||
|
val searchList =
|
||||||
|
if SearchList.exists (matchedIdx, searchList) then
|
||||||
|
searchList
|
||||||
|
else
|
||||||
|
SearchList.insert (matchedIdx, searchList)
|
||||||
|
in
|
||||||
|
helpFromRange
|
||||||
|
( origIdx
|
||||||
|
, curIdx + 1
|
||||||
|
, finishIdx
|
||||||
|
, buffer
|
||||||
|
, searchString
|
||||||
|
, searchList
|
||||||
|
)
|
||||||
|
end
|
||||||
|
| NONE =>
|
||||||
|
let
|
||||||
|
val buffer = LineGap.goToIdx (origIdx, buffer)
|
||||||
|
val searchList = SearchList.goToNum (origIdx, searchList)
|
||||||
|
in
|
||||||
|
(buffer, searchList)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
fun fromRange (startIdx, length, buffer, searchString, searchList) =
|
fun fromRange (startIdx, length, buffer, searchString, searchList) =
|
||||||
let
|
let
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ sig
|
|||||||
type t = {left: int vector list, right: int vector list}
|
type t = {left: int vector list, right: int vector list}
|
||||||
val empty: t
|
val empty: t
|
||||||
|
|
||||||
|
val exists: int * t -> bool
|
||||||
val insert: int * t -> t
|
val insert: int * t -> t
|
||||||
val append: int * t -> t
|
val append: int * t -> t
|
||||||
val delete: int * int * string * t -> t
|
val delete: int * int * string * t -> t
|
||||||
@@ -587,4 +588,38 @@ struct
|
|||||||
in
|
in
|
||||||
moveRightAndMap (num, mapBy, left, right)
|
moveRightAndMap (num, mapBy, left, right)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
fun helpExistsRight (num, right) =
|
||||||
|
case right of
|
||||||
|
hd :: tl =>
|
||||||
|
let
|
||||||
|
val rlast = Vector.sub (hd, Vector.length hd - 1)
|
||||||
|
in
|
||||||
|
if num > rlast then helpExistsRight (num, tl)
|
||||||
|
else BinSearch.exists (num, hd)
|
||||||
|
end
|
||||||
|
| [] => false
|
||||||
|
|
||||||
|
fun helpExistsLeft (num, left) =
|
||||||
|
case left of
|
||||||
|
hd :: tl =>
|
||||||
|
let
|
||||||
|
val lfirst = Vector.sub (hd, 0)
|
||||||
|
in
|
||||||
|
if num < lfirst then helpExistsLeft (num, tl)
|
||||||
|
else BinSearch.exists (num, hd)
|
||||||
|
end
|
||||||
|
| [] => false
|
||||||
|
|
||||||
|
fun exists (num, {left, right}) =
|
||||||
|
case right of
|
||||||
|
rhd :: rtl =>
|
||||||
|
let
|
||||||
|
val rfirst = Vector.sub (rhd, 0)
|
||||||
|
in
|
||||||
|
if num = rfirst then true
|
||||||
|
else if num > rfirst then helpExistsRight (num, right)
|
||||||
|
else helpExistsLeft (num, left)
|
||||||
|
end
|
||||||
|
| [] => helpExistsLeft (num, left)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user