Mercurial
diff react_games/src/random.tsx @ 51:68fa88ac73fe
Interview prep for xAI
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Mon, 15 Dec 2025 19:55:17 -0800 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/react_games/src/random.tsx Mon Dec 15 19:55:17 2025 -0800 @@ -0,0 +1,105 @@ +import { InputEvent, useCallback, useEffect, useRef, useState } from "react"; +import ReactDOM from "react-dom/client"; + +// 1. input and listen to its key stroke fire findSuggestions +// 2. debounce findSuggestions +// 3. create structure for its to search + +const DEBOUNCER_WAIT_TIME = 500; + +const WORDS = [ + "cat", + "call", + "cell", + "car", + "carpet", + "celcius" +] + +interface Tries { + children: Record<string, Tries>; + words: Set<string>; +} + +function TypeAhead() { + const inputRef = useRef<HTMLInputElement | null>(null); + const debounceTimerId = useRef<NodeJS.Timeout>(null); + const tries = useRef<Tries>({ children: {}, words: new Set(WORDS) }) + const [suggestions, setSuggestions] = useState<string[]>([]); + + const performSearch = useCallback((value: string) => { + let curr = tries.current + const res: string[] = [] + function dfs(node: Tries, pos: number, off: number = 0, matching: number = 0) { + if (off > 2) { + if (matching > Math.ceil(value.length/2)) { + node.words.forEach(word => res.push(word)); + } + return; + } + + if (pos == value.length) { + node.words.forEach(word => res.push(word)); + return; + } + + const letter = value[pos]; + if (!node.children[letter]) { + Object.keys(node.children).forEach((key) => { + dfs(node.children[key], pos+1, off+1, matching) + }); + } else { + dfs(node.children[letter], pos+1, off, matching + 1) + } + + } + dfs(curr, 0); + setSuggestions([...res]); + }, []) + + const findSuggestions = useCallback(() => { + if (debounceTimerId.current) { + clearTimeout(debounceTimerId.current); + } + debounceTimerId.current = setTimeout(() => performSearch(inputRef.current?.value || ""), DEBOUNCER_WAIT_TIME) + }, []) + + useEffect(() => { + WORDS.forEach(word => { + let curr = tries.current; + for (let letter of word) { + letter = letter.toLowerCase(); + if (!curr.children[letter]) { + curr.children[letter] = { children: {}, words: new Set([word]) }; + } else { + curr.children[letter].words.add(word) ; + } + curr = curr.children[letter]; + } + }) + return () => { + if (debounceTimerId.current) + clearTimeout(debounceTimerId.current) + } + }, []) + + return ( + <> + <h1> Type ahead </h1> + <input ref={inputRef} onChange={findSuggestions}/> + {suggestions && ( + <div style={{display: "flex", flexDirection: "column", gap: 8, border: "1px black solid"}}> + {suggestions.map(suggestion => { + return ( + <div>{suggestion}</div> + ) + })} + </div> + )} + </> + ); +} + +// Render +const root = ReactDOM.createRoot(document.getElementById("root")!); +root.render(<TypeAhead />);