Advertisement
kosievdmerwe

Untitled

Nov 8th, 2021
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.21 KB | None | 0 0
  1. PUZZLE_LEN = 7
  2.  
  3.  
  4. class PuzzleTrie:
  5.     def __init__(self):
  6.         self.cnt = 0
  7.         self.idxes = None
  8.         self.children = {}
  9.    
  10.     def add_norm_puzzle(self, puzzle_idx: int, norm_puzzle: str) -> None:
  11.         cur = self
  12.         depth = 0
  13.         for i in range(26):
  14.             if (1 << i) & norm_puzzle == 0:
  15.                 continue
  16.             depth += 1
  17.             if i not in cur.children:
  18.                 cur.children[i] = PuzzleTrie()
  19.             cur = cur.children[i]
  20.         assert depth == PUZZLE_LEN, f"{depth}, {bin(norm_puzzle)}"
  21.        
  22.         if cur.idxes is None:
  23.             cur.idxes = []
  24.         cur.idxes.append(puzzle_idx)
  25.    
  26.     def add_norm_word(self, norm_word: int) -> None:
  27.         cur = self
  28.         for i in range(26):
  29.             if (1 << i) & norm_word == 0:
  30.                 continue
  31.             if i not in cur.children:
  32.                 return
  33.             cur = cur.children[i]
  34.         cur.cnt += 1
  35.    
  36.     def flatten_counts(self, parent: "Optional[PuzzleTrie]" = None) -> None:
  37.         self.cnt += 0 if not parent else parent.cnt
  38.         for child in self.children.values():
  39.             child.flatten_counts(self)
  40.    
  41.     def update_puzzle_counts(self, puzzle_counts: List[int]):
  42.         if self.idxes is None:
  43.             for child in self.children.values():
  44.                 child.update_puzzle_counts(puzzle_counts)
  45.         else:
  46.             for idx in self.idxes:
  47.                 puzzle_counts[idx] += self.cnt
  48.            
  49.     def to_tuple(self) -> Tuple[int, Optional[List[int]], Dict[int, Any]]:
  50.         children = {}
  51.         for k, v in self.children.items():
  52.             children[k] = v.to_tuple()
  53.         return (self.cnt, self.idxes, children)
  54.            
  55.     def debug_print(self):
  56.         from pprint import pprint
  57.         pprint(self.to_tuple())
  58.        
  59.  
  60.                
  61. class Solution:
  62.     def findNumOfValidWords(self, words: List[str], puzzles: List[str]) -> List[int]:
  63.         first_letter_tries = [PuzzleTrie() for _ in range(26)]
  64.        
  65.         for idx, puzzle in enumerate(puzzles):
  66.             first_letter_idx = ord(puzzle[0]) - ord('a')
  67.             norm_puzzle = self.calc_norm_word(puzzle)
  68.             first_letter_tries[first_letter_idx].add_norm_puzzle(idx, norm_puzzle)
  69.            
  70.         for word in words:
  71.             norm_word = self.calc_norm_word(word)
  72.             if bin(norm_word).count("1") > PUZZLE_LEN:
  73.                 continue
  74.            
  75.             for first_letter_idx in range(26):
  76.                 if (1 << first_letter_idx) & norm_word == 0:
  77.                     continue
  78.                 first_letter_tries[first_letter_idx].add_norm_word(norm_word)
  79.                
  80.                 if first_letter_idx == 0:
  81.                     print()
  82.                     first_letter_tries[first_letter_idx].debug_print()
  83.                     print()
  84.  
  85.         ans = [0] * len(puzzles)
  86.         for first_letter_idx, pt in enumerate(first_letter_tries):
  87.             pt.flatten_counts()
  88.             pt.update_puzzle_counts(ans)
  89.         return ans
  90.  
  91.     def calc_norm_word(self, word: str) -> int:
  92.         normed = 0
  93.         for c in word:
  94.             normed |= 1 << (ord(c) - ord('a'))
  95.         return normed
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement