def generate(self, quantity=1, operators=7, enable_power=False): count = 0 for loop in range(quantity * 2): if count >= quantity: break nums = [ BiTree(0, random.randint(0, self.UPPERCAP)) for _ in range(1, operators + 2) ] ops = [ BiTree( 1, random.randint(0, len(BiTree.operators) - 2 + enable_power)) for _ in range(operators) ] unfilled = ops[:] filled = nums[:] ev = Evaluator() # 链接成树 while len(unfilled): i = random.randint(0, len(filled) - 1) unfilled[0].set_lchild(filled[i]) filled.pop(i) # 除法 乘方 特殊处理 i = random.randint(0, len(filled) - 1) if unfilled[0].node_type == 1 and unfilled[0].val == 3: # 除数为0 if ev.evaluate(filled[i]) == 0: unfilled[0].set_rchild( BiTree(0, random.randint(1, self.UPPERCAP))) else: unfilled[0].set_rchild(filled[i]) elif unfilled[0].node_type == 1 and unfilled[0].val == 4: # 指数过大 或 为分数 if abs(ev.evaluate(filled[i])) > 2 or ev.evaluate( filled[i]).denominator != 1: unfilled[0].set_rchild(BiTree(0, random.randint(1, 2))) else: unfilled[0].set_rchild(filled[i]) else: unfilled[0].set_rchild(filled[i]) filled.pop(i) filled.append(unfilled[0]) unfilled.pop(0) # 去重 if not self.deduplicate(filled[-1]): continue # 检查除数为0 try: ev.evaluate(filled[-1]) except ZeroDivisionError: continue self.output_list.append(filled[-1]) count += 1
def test_format_L2(self): # 6 + 3 -> 3 + 6 root = BiTree(1, 0) root.set_lchild(BiTree(0, 6)) root.set_rchild(BiTree(0, 3)) self.g.format_expression(root) self.assertEqual('3 + 6', root.to_string())
def format_expression(node: BiTree): if not node.lchild: return QuestGenerator.format_expression(node.lchild) QuestGenerator.format_expression(node.rchild) # 仅有+×可交换 if node.val in ( 0, 2) and node.lchild.to_string() > node.rchild.to_string(): tmp = node.lchild node.lchild = node.rchild node.rchild = tmp
def test_div(self): root = BiTree(1, 3) # (-14) ÷ 6 root.set_lchild(BiTree(0, -14)) root.set_rchild(BiTree(0, 6)) self.assertEqual(Fraction(-7, 3), self.ev.evaluate(root))
def test_mul(self): root = BiTree(1, 2) # (-7) × 6 root.set_lchild(BiTree(0, -7)) root.set_rchild(BiTree(0, 6)) self.assertEqual(-42, self.ev.evaluate(root))
def test_sub(self): root = BiTree(1, 1) # (-7) - 6 root.set_lchild(BiTree(0, -7)) root.set_rchild(BiTree(0, 6)) self.assertEqual(-13, self.ev.evaluate(root))
def test_add(self): root = BiTree(1, 0) # (-7) + 6 root.set_lchild(BiTree(0, -7)) root.set_rchild(BiTree(0, 6)) self.assertEqual(-1, self.ev.evaluate(root))
def test_number(self): root = BiTree(0, 5) self.assertEqual(5, self.ev.evaluate(root))
def test_deduplicate(self): tree1 = BiTree(0, 4) tree2 = BiTree(1, 0) tree2.set_lchild(BiTree(0, 6)) tree2.set_rchild(BiTree(0, 3)) tree3 = BiTree(1, 2) lft = BiTree(1, 0) lft.set_lchild(BiTree(0, 6)) lft.set_rchild(BiTree(0, 5)) r = BiTree(1, 1) r.set_lchild(BiTree(0, 4)) r.set_rchild(BiTree(0, 2)) tree3.set_lchild(lft) tree3.set_rchild(r) self.assertEqual(True, self.g.deduplicate(tree1)) self.assertEqual(False, self.g.deduplicate(tree1)) self.assertEqual(True, self.g.deduplicate(tree2)) self.assertEqual(False, self.g.deduplicate(tree2)) self.assertEqual(True, self.g.deduplicate(tree3)) self.assertEqual(False, self.g.deduplicate(tree3))
def test_op_priority(self): self.assertEqual(0, BiTree(1, 0).this_level) self.assertEqual(0, BiTree(1, 1).this_level) self.assertEqual(2, BiTree(1, 2).this_level) self.assertEqual(2, BiTree(1, 3).this_level) self.assertEqual(4, BiTree(1, 4).this_level)
def test_set_power(self): BiTree.set_power_operator(True) self.assertEqual(' ^ ', BiTree.operators[4])
def test_format_L1(self): node = BiTree(0, 4) self.g.format_expression(node) self.assertEqual('4', node.to_string())
def test_to_string_L3(self): # (5 + 6) ^ (4 - 2) root = BiTree(1, 4) lft = BiTree(1, 0) lft.set_lchild(BiTree(0, 5)) lft.set_rchild(BiTree(0, 6)) r = BiTree(1, 1) r.set_lchild(BiTree(0, 4)) r.set_rchild(BiTree(0, 2)) root.set_lchild(lft) root.set_rchild(r) self.assertEqual('(5 + 6) ** (4 - 2)', root.to_string()) BiTree.set_power_operator(True) self.assertEqual('(5 + 6) ^ (4 - 2)', root.to_string())
def test_to_string_L2(self): # 4 × 8 root = BiTree(1, 2) root.set_lchild(BiTree(0, 4)) root.set_rchild(BiTree(0, 8)) self.assertEqual('4 × 8', root.to_string())
def test_to_string_L1(self): self.assertEqual('3', BiTree(0, 3).to_string())
def test_pow(self): root = BiTree(1, 4) # (-2) ^ 3 root.set_lchild(BiTree(0, -2)) root.set_rchild(BiTree(0, 3)) self.assertEqual(-8, self.ev.evaluate(root))
def test_format_L3(self): # (6 + 5) × (4 - 2) -> (4 - 2) × (5 + 6) root = BiTree(1, 2) lft = BiTree(1, 0) lft.set_lchild(BiTree(0, 6)) lft.set_rchild(BiTree(0, 5)) r = BiTree(1, 1) r.set_lchild(BiTree(0, 4)) r.set_rchild(BiTree(0, 2)) root.set_lchild(lft) root.set_rchild(r) self.g.format_expression(root) self.assertEqual('(4 - 2) × (5 + 6)', root.to_string())
except getopt.GetoptError as e: print('\n ' + e.msg + '\n') exit(21) else: for op, value in opts: if op == '-h': print(USAGE) exit(0) elif op == '-n': num = int(value) elif op == '-l': operators = int(value) elif op == '-e': exp = True elif op == '-p': BiTree.set_power_operator(True) elif op == '-v': verbose = True elif op == '-i': interact = True g = Qg.QuestGenerator() g.generate(quantity=num, operators=operators, enable_power=exp) ev = Evaluator.Evaluator() # 显示结果 if verbose: for out in g.output_list: print(out.to_string()) for out in g.output_list: print(str(ev.evaluate(out)))
def test_set_power_2(self): BiTree.set_power_operator(False) self.assertEqual(' ** ', BiTree.operators[4])