seem to have fixed error with 'exists' function previously mentioned in todo, without introducing regressions

This commit is contained in:
2024-09-04 18:57:39 +01:00
parent b2b0837524
commit dd41c971e3

View File

@@ -79,64 +79,62 @@ struct
fun helpExists (searchKey, keyPos, trie) = fun helpExists (searchKey, keyPos, trie) =
case trie of case trie of
CHILDREN {keys, children} => CHILDREN {keys, children} =>
if keyPos = String.size searchKey then let
false val findChr = String.sub (searchKey, keyPos)
else in
let (case findBinSearch (findChr, keyPos, keys) of
val findChr = String.sub (searchKey, keyPos) SOME idx =>
in let
(case findBinSearch (findChr, keyPos, keys) of val trieKey = Vector.sub (keys, idx)
SOME idx => in
let (case searchKeyMatch (searchKey, trieKey, keyPos + 1) of
val trieKey = Vector.sub (keys, idx) NO_SEARCH_MATCH => false
in | FULL_SEARCH_MATCH =>
(case searchKeyMatch (searchKey, trieKey, keyPos + 1) of let val trieChild = Vector.sub (children, idx)
NO_SEARCH_MATCH => false in isFoundNode trieChild
| FULL_SEARCH_MATCH => end
let val trieChild = Vector.sub (children, idx) | SEARCH_KEY_CONTAINS_TRIE_KEY =>
in isFoundNode trieChild let val trieChild = Vector.sub (children, idx)
end in helpExists (searchKey, String.size trieKey, trieChild)
| SEARCH_KEY_CONTAINS_TRIE_KEY => end
let | TRIE_KEY_CONTAINS_SEARCH_KEY => false)
val trieChild = Vector.sub (children, idx) end
in | NONE => false)
helpExists end
(searchKey, keyPos + String.size trieKey, trieChild)
end
| TRIE_KEY_CONTAINS_SEARCH_KEY => false)
end
| NONE => false)
end
| FOUND_WITH_CHILDREN {keys, children} => | FOUND_WITH_CHILDREN {keys, children} =>
if keyPos = String.size searchKey then let
true val findChr = String.sub (searchKey, keyPos)
else in
let (case findBinSearch (findChr, keyPos, keys) of
val findChr = String.sub (searchKey, keyPos) SOME idx =>
in let
(case findBinSearch (findChr, keyPos, keys) of val trieKey = Vector.sub (keys, idx)
SOME idx => in
let (case searchKeyMatch (searchKey, trieKey, keyPos + 1) of
val trieKey = Vector.sub (keys, idx) NO_SEARCH_MATCH => false
in | FULL_SEARCH_MATCH =>
(case searchKeyMatch (searchKey, trieKey, keyPos + 1) of let val trieChild = Vector.sub (children, idx)
NO_SEARCH_MATCH => false in isFoundNode trieChild
| FULL_SEARCH_MATCH => end
let val trieChild = Vector.sub (children, idx) | SEARCH_KEY_CONTAINS_TRIE_KEY =>
in isFoundNode trieChild let val trieChild = Vector.sub (children, idx)
end in helpExists (searchKey, String.size trieKey, trieChild)
| SEARCH_KEY_CONTAINS_TRIE_KEY => end
let | TRIE_KEY_CONTAINS_SEARCH_KEY => false)
val trieChild = Vector.sub (children, idx) end
in | NONE => false)
helpExists end
(searchKey, keyPos + String.size trieKey, trieChild) | FOUND =>
end (*
| TRIE_KEY_CONTAINS_SEARCH_KEY => false) * This case should only occur if we recurse in a node
end * when there is a partial, but not full, string match.
| NONE => false) * This is because of the isFoundNode helper function
end * which is called by the parent.
| FOUND => keyPos = String.size searchKey - 1 * In other words, only the parent node returns true,
* by checking if the child is a found node and has
* a full string match.
*)
false
fun exists (searchKey, trie) = helpExists (searchKey, 0, trie) fun exists (searchKey, trie) = helpExists (searchKey, 0, trie)
@@ -155,8 +153,7 @@ struct
let let
val trieChild = Vector.sub (children, idx) val trieChild = Vector.sub (children, idx)
in in
helpGetPrefixSubtrie helpGetPrefixSubtrie (prefix, String.size trieKey, trieChild)
(prefix, keyPos + String.size trieKey, trieChild)
end end
| FULL_SEARCH_MATCH => | FULL_SEARCH_MATCH =>
let val node = Vector.sub (children, idx) let val node = Vector.sub (children, idx)
@@ -177,7 +174,7 @@ struct
| FOUND_WITH_CHILDREN {keys, children} => | FOUND_WITH_CHILDREN {keys, children} =>
helpGetPrefixSubtrieChildren (prefix, keyPos, keys, children, trie) helpGetPrefixSubtrieChildren (prefix, keyPos, keys, children, trie)
| FOUND => | FOUND =>
if keyPos = String.size prefix then if keyPos = String.size prefix - 1 then
let val node = fromString prefix let val node = fromString prefix
in SOME node in SOME node
end end
@@ -209,7 +206,7 @@ struct
fun getPrefixList (prefix, trie) = fun getPrefixList (prefix, trie) =
case getPrefixSubtrie (prefix, trie) of case getPrefixSubtrie (prefix, trie) of
SOME subtrie => helpGetPrefixList (trie, []) SOME subtrie => helpGetPrefixList (subtrie, [])
| NONE => [] | NONE => []
datatype insert_string_match = datatype insert_string_match =
@@ -351,9 +348,8 @@ struct
fun foundInsertPos (keys, children, keyPos, insKey, insIdx, trie, constructor) = fun foundInsertPos (keys, children, keyPos, insKey, insIdx, trie, constructor) =
let let
val trieKey = Vector.sub (keys, insIdx) val trieKey = Vector.sub (keys, insIdx)
val nextKeyPos = keyPos + 1
in in
(case insertKeyMatch (insKey, trieKey, nextKeyPos) of (case insertKeyMatch (insKey, trieKey, keyPos + 1) of
(* may need to split string if difference found but prefix matched *) (* may need to split string if difference found but prefix matched *)
DIFFERENCE_FOUND_AT diffIdx => DIFFERENCE_FOUND_AT diffIdx =>
let let
@@ -410,8 +406,8 @@ struct
| INSERT_KEY_CONTAINS_TRIE_KEY => | INSERT_KEY_CONTAINS_TRIE_KEY =>
let let
val trieChild = Vector.sub (children, insIdx) val trieChild = Vector.sub (children, insIdx)
val newTrieChild = helpInsert val newTrieChild =
(insKey, keyPos + String.size trieKey, trieChild) helpInsert (insKey, String.size trieKey, trieChild)
val newChildren = val newChildren =
Vector.mapi Vector.mapi
(fn (idx, elt) => if idx <> insIdx then elt else newTrieChild) (fn (idx, elt) => if idx <> insIdx then elt else newTrieChild)
@@ -508,4 +504,10 @@ struct
* todo: * todo:
* - Test prefix searching, which turns found strings to list. * - Test prefix searching, which turns found strings to list.
*) *)
val trie = fromList ["hello", "hit", "hi", "henlo", "help"]
val lst = getPrefixList ("hi", trie)
val helloExists = exists ("hello", trie)
val hitExists = exists ("hit", trie)
val hiExists = exists ("hi", trie)
end end