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