fixed 'helpExists' function; error was in the FOUND case which checked 'keyPos = String.size searchKey' instead of 'keyPos = String.size searchKey - 1'. The latter is correct, because it checks that the keyPos ended at the last character, which is the intended meaning

This commit is contained in:
2024-09-04 16:38:27 +01:00
parent 86f171cd08
commit 20de15b349

View File

@@ -79,58 +79,64 @@ struct
fun helpExists (searchKey, keyPos, trie) =
case trie of
CHILDREN {keys, children} =>
let
val findChr = String.sub (searchKey, keyPos)
in
(case findBinSearch (findChr, keyPos, keys) of
SOME idx =>
let
val trieKey = Vector.sub (keys, idx)
in
(case searchKeyMatch (searchKey, trieKey, keyPos + 1) of
NO_SEARCH_MATCH => false
| FULL_SEARCH_MATCH =>
let val trieChild = Vector.sub (children, idx)
in isFoundNode trieChild
end
| SEARCH_KEY_CONTAINS_TRIE_KEY =>
let
val trieChild = Vector.sub (children, idx)
in
helpExists
(searchKey, keyPos + String.size trieKey, trieChild)
end
| TRIE_KEY_CONTAINS_SEARCH_KEY => false)
end
| NONE => false)
end
if keyPos = String.size searchKey then
false
else
let
val findChr = String.sub (searchKey, keyPos)
in
(case findBinSearch (findChr, keyPos, keys) of
SOME idx =>
let
val trieKey = Vector.sub (keys, idx)
in
(case searchKeyMatch (searchKey, trieKey, keyPos + 1) of
NO_SEARCH_MATCH => false
| FULL_SEARCH_MATCH =>
let val trieChild = Vector.sub (children, idx)
in isFoundNode trieChild
end
| SEARCH_KEY_CONTAINS_TRIE_KEY =>
let
val trieChild = Vector.sub (children, idx)
in
helpExists
(searchKey, keyPos + String.size trieKey, trieChild)
end
| TRIE_KEY_CONTAINS_SEARCH_KEY => false)
end
| NONE => false)
end
| FOUND_WITH_CHILDREN {keys, children} =>
let
val findChr = String.sub (searchKey, keyPos)
in
(case findBinSearch (findChr, keyPos, keys) of
SOME idx =>
let
val trieKey = Vector.sub (keys, idx)
in
(case searchKeyMatch (searchKey, trieKey, keyPos + 1) of
NO_SEARCH_MATCH => false
| FULL_SEARCH_MATCH =>
let val trieChild = Vector.sub (children, idx)
in isFoundNode trieChild
end
| SEARCH_KEY_CONTAINS_TRIE_KEY =>
let
val trieChild = Vector.sub (children, idx)
in
helpExists
(searchKey, keyPos + String.size trieKey, trieChild)
end
| TRIE_KEY_CONTAINS_SEARCH_KEY => false)
end
| NONE => false)
end
| FOUND => keyPos = String.size searchKey
if keyPos = String.size searchKey then
true
else
let
val findChr = String.sub (searchKey, keyPos)
in
(case findBinSearch (findChr, keyPos, keys) of
SOME idx =>
let
val trieKey = Vector.sub (keys, idx)
in
(case searchKeyMatch (searchKey, trieKey, keyPos + 1) of
NO_SEARCH_MATCH => false
| FULL_SEARCH_MATCH =>
let val trieChild = Vector.sub (children, idx)
in isFoundNode trieChild
end
| SEARCH_KEY_CONTAINS_TRIE_KEY =>
let
val trieChild = Vector.sub (children, idx)
in
helpExists
(searchKey, keyPos + String.size trieKey, trieChild)
end
| TRIE_KEY_CONTAINS_SEARCH_KEY => false)
end
| NONE => false)
end
| FOUND => keyPos = String.size searchKey - 1
fun exists (searchKey, trie) = helpExists (searchKey, 0, trie)
@@ -402,8 +408,16 @@ struct
FOUND_WITH_CHILDREN {keys = keys, children = children}
(* if insert key contains trie key, need to recurse down node *)
| INSERT_KEY_CONTAINS_TRIE_KEY =>
let val trieChild = Vector.sub (children, insIdx)
in helpInsert (insKey, keyPos + String.size trieKey, trieChild)
let
val trieChild = Vector.sub (children, insIdx)
val newTrieChild = helpInsert
(insKey, keyPos + String.size trieKey, trieChild)
val newChildren =
Vector.mapi
(fn (idx, elt) => if idx <> insIdx then elt else newTrieChild)
children
in
constructor {keys = keys, children = newChildren}
end
(* if trie key contains insert key, need to split node *)
| TRIE_KEY_CONTAINS_INSERT_KEY =>
@@ -411,7 +425,7 @@ struct
val trieChild = Vector.sub (children, insIdx)
val newKeys =
Vector.mapi
(fn (idx, key) => if idx <> insIdx then insKey else key) keys
(fn (idx, key) => if idx <> insIdx then key else insKey) keys
(* newTrieChild should always be FOUND_WITH_CHILDREN,
* because previous part matches insert key,
@@ -492,13 +506,16 @@ struct
(*
* todo:
* - Fix insert function.
* - Once insert is fixed, test prefix searching,
* which turns found strings to list.
* - Fix exists function
* - Test prefix searching, which turns found strings to list.
*
* Problem with insert function:
* The "trie" value below does not contain "hello". It somehow disappeared.
* Should probably attempt to create a test suite, to catch regressions as well.
* Problem with exists function:
* exists ("hello", trie) returns true as expected
* but exists ("hellop", trie) also returns true
* even though "hellop" was never added.
*
* "helloz" also returns true, although "hellopo" returns false.
* Problem occurs when trieKey length > searchKey length + 1 apparently.
*)
val trie = fromList ["hello", "hit", "hi"]