Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 46:b9a40c633c93 | 51:68fa88ac73fe |
|---|---|
| 1 import { InputEvent, useCallback, useEffect, useRef, useState } from "react"; | |
| 2 import ReactDOM from "react-dom/client"; | |
| 3 | |
| 4 // 1. input and listen to its key stroke fire findSuggestions | |
| 5 // 2. debounce findSuggestions | |
| 6 // 3. create structure for its to search | |
| 7 | |
| 8 const DEBOUNCER_WAIT_TIME = 500; | |
| 9 | |
| 10 const WORDS = [ | |
| 11 "cat", | |
| 12 "call", | |
| 13 "cell", | |
| 14 "car", | |
| 15 "carpet", | |
| 16 "celcius" | |
| 17 ] | |
| 18 | |
| 19 interface Tries { | |
| 20 children: Record<string, Tries>; | |
| 21 words: Set<string>; | |
| 22 } | |
| 23 | |
| 24 function TypeAhead() { | |
| 25 const inputRef = useRef<HTMLInputElement | null>(null); | |
| 26 const debounceTimerId = useRef<NodeJS.Timeout>(null); | |
| 27 const tries = useRef<Tries>({ children: {}, words: new Set(WORDS) }) | |
| 28 const [suggestions, setSuggestions] = useState<string[]>([]); | |
| 29 | |
| 30 const performSearch = useCallback((value: string) => { | |
| 31 let curr = tries.current | |
| 32 const res: string[] = [] | |
| 33 function dfs(node: Tries, pos: number, off: number = 0, matching: number = 0) { | |
| 34 if (off > 2) { | |
| 35 if (matching > Math.ceil(value.length/2)) { | |
| 36 node.words.forEach(word => res.push(word)); | |
| 37 } | |
| 38 return; | |
| 39 } | |
| 40 | |
| 41 if (pos == value.length) { | |
| 42 node.words.forEach(word => res.push(word)); | |
| 43 return; | |
| 44 } | |
| 45 | |
| 46 const letter = value[pos]; | |
| 47 if (!node.children[letter]) { | |
| 48 Object.keys(node.children).forEach((key) => { | |
| 49 dfs(node.children[key], pos+1, off+1, matching) | |
| 50 }); | |
| 51 } else { | |
| 52 dfs(node.children[letter], pos+1, off, matching + 1) | |
| 53 } | |
| 54 | |
| 55 } | |
| 56 dfs(curr, 0); | |
| 57 setSuggestions([...res]); | |
| 58 }, []) | |
| 59 | |
| 60 const findSuggestions = useCallback(() => { | |
| 61 if (debounceTimerId.current) { | |
| 62 clearTimeout(debounceTimerId.current); | |
| 63 } | |
| 64 debounceTimerId.current = setTimeout(() => performSearch(inputRef.current?.value || ""), DEBOUNCER_WAIT_TIME) | |
| 65 }, []) | |
| 66 | |
| 67 useEffect(() => { | |
| 68 WORDS.forEach(word => { | |
| 69 let curr = tries.current; | |
| 70 for (let letter of word) { | |
| 71 letter = letter.toLowerCase(); | |
| 72 if (!curr.children[letter]) { | |
| 73 curr.children[letter] = { children: {}, words: new Set([word]) }; | |
| 74 } else { | |
| 75 curr.children[letter].words.add(word) ; | |
| 76 } | |
| 77 curr = curr.children[letter]; | |
| 78 } | |
| 79 }) | |
| 80 return () => { | |
| 81 if (debounceTimerId.current) | |
| 82 clearTimeout(debounceTimerId.current) | |
| 83 } | |
| 84 }, []) | |
| 85 | |
| 86 return ( | |
| 87 <> | |
| 88 <h1> Type ahead </h1> | |
| 89 <input ref={inputRef} onChange={findSuggestions}/> | |
| 90 {suggestions && ( | |
| 91 <div style={{display: "flex", flexDirection: "column", gap: 8, border: "1px black solid"}}> | |
| 92 {suggestions.map(suggestion => { | |
| 93 return ( | |
| 94 <div>{suggestion}</div> | |
| 95 ) | |
| 96 })} | |
| 97 </div> | |
| 98 )} | |
| 99 </> | |
| 100 ); | |
| 101 } | |
| 102 | |
| 103 // Render | |
| 104 const root = ReactDOM.createRoot(document.getElementById("root")!); | |
| 105 root.render(<TypeAhead />); |