def test_lca(self): tree = Tree({'A': 'xabxac', 'B': 'awyawxawxz'}) tree.prepare_lca() self.assertEqual( tree.lca(tree.nodemap['A'][1], tree.nodemap['B'][3]).id, 8) self.assertEqual( tree.lca(tree.nodemap['A'][0], tree.nodemap['B'][8]).id, 2) self.assertEqual( tree.lca(tree.nodemap['B'][1], tree.nodemap['B'][7]).id, 19) self.assertEqual( tree.lca(tree.nodemap['A'][0], tree.nodemap['B'][7]).id, 1)
class LongestPalindromeFinder(tk.Frame): def __init__(self, master=None): super().__init__(master=master) tk.Label(self, text='Sequence').grid(row=0, column=0, sticky='w') self.sequence_text = tk.Text(self) self.sequence_text.grid(row=1, column=0, columnspan=2, sticky='nsew') self.sequence_load_btn = tk.Button( self, text='Choose file', command=self.choose_sequence_file) self.sequence_load_btn.grid(row=2, column=1, sticky='e') buttons_frame = tk.Frame(self) self.run_btn = tk.Button(master=buttons_frame, text='Run', command=self.run) self.run_btn.grid(row=0, column=1) self.export_btn = tk.Button( master=buttons_frame, text='Export Tree', command=self.export_tree) self.export_btn.grid(row=0, column=0) buttons_frame.grid(row=3, column=0, columnspan=2, sticky='e') for i in range(2): self.grid_columnconfigure(i, weight=1) for i in range(4): self.grid_rowconfigure(i, weight=1) self.sequence = None self.tree = None def choose_sequence_file(self): filename = filedialog.askopenfilename(parent=self) try: self.sequence_text.delete(1.0, tk.END) self.sequence_text.insert(tk.END, open(filename, 'r').read()) except FileNotFoundError: messagebox.showwarning( title='Bad file', message='No files selected') def load_sequence(self): self.sequence = self.sequence_text.get(1.0, tk.END).strip("\n ") def construct_tree(self): self.tree = Tree({1: self.sequence, 2: reversed(self.sequence)}) def initialize(self): self.load_sequence() if not self.sequence: messagebox.showerror( title='Bad input', message='Invalid input sequence') return self.construct_tree() def run(self): self.initialize() result = str(self.find_the_longest_palindrome()).replace(' ', '') output(result, 'longest_palindrome_found.txt') def build_neighbor_leaves(self): leaves = {} def f(node): if node.is_leaf(): leaves[(node.str_id, node.path.start)] = node self.tree.root.post_order(f) odd_neighbor_leaves = [(leaves[1, i], leaves[2, len(self.sequence) - 1 - i]) for i in range(len(self.sequence))] even_neighbor_leaves = [(self.sequence[i], leaves[1, i + 1], leaves[2, len(self.sequence) + 1 - i]) for i in range(1, len(self.sequence) - 1) if self.sequence[i - 1] == self.sequence[i]] # neighbor_leaves = [(leaves[i, 0], leaves[2, 0])] return odd_neighbor_leaves, even_neighbor_leaves def find_the_longest_odd_palindrome(self, neighbor_leaves): candidate_node = None for node1, node2 in neighbor_leaves: node = self.tree.lca(node1, node2) if candidate_node is None or len(node) > len(candidate_node): candidate_node = node result = str(candidate_node).replace(' ', '') result = (result[::-1])[:-1] + result return result def find_the_longest_even_palindrome(self, neighbor_leaves): if not neighbor_leaves: return '' candidate_node = None middle = None for mid, node1, node2 in neighbor_leaves: node = self.tree.lca(node1, node2) if candidate_node is None or len(node) > len(candidate_node): candidate_node = node middle = mid if candidate_node == self.tree.root: candidate_node = '' result = str(candidate_node).replace(' ', '') result = result[::-1] + (middle * 2) + result return result def find_the_longest_palindrome(self): odd_neighbor_leaves, even_neighbor_leaves = self.build_neighbor_leaves() self.tree.prepare_lca() odd_palindrome = self.find_the_longest_odd_palindrome(odd_neighbor_leaves) even_palindrome = self.find_the_longest_even_palindrome(even_neighbor_leaves) return max(odd_palindrome, even_palindrome, key=len) def export_tree(self): self.initialize() filename = filedialog.asksaveasfilename(parent=self.master) graphviz.Source(self.tree.to_dot()).render( filename=filename, format='pdf', view=True, cleanup=True)