From 78e60530667067e90f1220cc7c10607e6c3bb998 Mon Sep 17 00:00:00 2001 From: Sourcery AI <> Date: Fri, 29 Jul 2022 02:19:21 +0000 Subject: [PATCH] 'Refactored by Sourcery' --- epi_judge_python/absent_value_array.py | 2 +- epi_judge_python/adding_credits.py | 2 - epi_judge_python/alternating_array.py | 33 +++++------ epi_judge_python/circular_queue.py | 8 +-- epi_judge_python/copy_posting_list.py | 13 ++--- epi_judge_python/do_lists_overlap.py | 2 +- epi_judge_python/dutch_national_flag.py | 2 +- epi_judge_python/enumerate_trees.py | 2 +- epi_judge_python/graph_clone.py | 3 +- epi_judge_python/gray_code.py | 7 ++- epi_judge_python/hanoi.py | 6 +- epi_judge_python/lru_cache.py | 8 +-- epi_judge_python/pivot_list.py | 29 +++++----- epi_judge_python/queue_from_stacks.py | 5 +- epi_judge_python/queue_with_max.py | 8 +-- epi_judge_python/refueling_schedule.py | 2 +- epi_judge_python/remove_duplicates.py | 4 +- .../search_entry_equal_to_index.py | 8 +-- epi_judge_python/search_maze.py | 22 ++++--- .../smallest_subarray_covering_all_values.py | 2 - epi_judge_python/stack_with_max.py | 11 ++-- epi_judge_python/sudoku_solve.py | 2 +- .../test_framework/binary_tree_utils.py | 7 +-- .../test_framework/console_color.py | 7 ++- .../test_framework/generic_test.py | 5 +- .../test_framework/generic_test_handler.py | 5 +- .../test_framework/random_sequence_checker.py | 30 ++++++---- .../test_framework/serialization_traits.py | 36 ++++++------ .../test_framework/test_config.py | 5 +- epi_judge_python/test_framework/test_timer.py | 6 +- epi_judge_python/test_framework/test_utils.py | 5 +- .../test_framework/test_utils_console.py | 33 +++++------ .../test_framework/timed_executor.py | 15 +++-- .../absent_value_array.py | 2 +- epi_judge_python_solutions/adding_credits.py | 4 +- .../advance_by_offsets.py | 2 +- .../alternating_array.py | 33 +++++------ epi_judge_python_solutions/circular_queue.py | 8 +-- epi_judge_python_solutions/collatz_checker.py | 2 +- .../copy_posting_list.py | 13 ++--- .../directory_path_normalization.py | 4 +- .../do_lists_overlap.py | 4 +- .../dutch_national_flag.py | 2 +- .../enumerate_balanced_parentheses.py | 58 ++++++++++++------- epi_judge_python_solutions/enumerate_trees.py | 2 +- epi_judge_python_solutions/fibonacci.py | 4 +- epi_judge_python_solutions/gcd.py | 4 +- epi_judge_python_solutions/graph_clone.py | 3 +- epi_judge_python_solutions/gray_code.py | 9 ++- epi_judge_python_solutions/h_index.py | 5 +- epi_judge_python_solutions/hanoi.py | 6 +- .../is_number_palindromic.py | 2 +- .../is_string_in_matrix.py | 7 ++- .../k_largest_in_heap.py | 4 +- ...th_largest_element_in_two_sorted_arrays.py | 2 +- .../largest_rectangle_under_skyline.py | 2 +- epi_judge_python_solutions/lru_cache.py | 8 +-- .../minimum_waiting_time.py | 9 ++- .../number_of_traversals_matrix.py | 2 +- epi_judge_python_solutions/path_sum.py | 9 +-- .../picking_up_coins.py | 16 +++-- epi_judge_python_solutions/pivot_list.py | 29 +++++----- epi_judge_python_solutions/pretty_printing.py | 2 +- .../queue_from_stacks.py | 5 +- epi_judge_python_solutions/queue_with_max.py | 8 +-- .../queue_with_max_using_deque.py | 8 +-- .../rectangle_intersection.py | 15 +++-- .../refueling_schedule.py | 2 +- .../remove_duplicates.py | 6 +- epi_judge_python_solutions/reverse_bits.py | 4 +- .../search_entry_equal_to_index.py | 8 +-- epi_judge_python_solutions/search_maze.py | 22 ++++--- .../smallest_subarray_covering_all_values.py | 2 - epi_judge_python_solutions/snake_string.py | 11 +--- epi_judge_python_solutions/stack_with_max.py | 11 ++-- .../string_transformability.py | 12 ++-- epi_judge_python_solutions/substring_match.py | 4 +- epi_judge_python_solutions/sudoku_solve.py | 12 ++-- .../test_framework/binary_tree_utils.py | 7 +-- .../test_framework/console_color.py | 7 ++- .../test_framework/generic_test.py | 5 +- .../test_framework/generic_test_handler.py | 5 +- .../test_framework/random_sequence_checker.py | 30 ++++++---- .../test_framework/serialization_traits.py | 36 ++++++------ .../test_framework/test_config.py | 5 +- .../test_framework/test_timer.py | 6 +- .../test_framework/test_utils.py | 5 +- .../test_framework/test_utils_console.py | 33 +++++------ .../test_framework/timed_executor.py | 15 +++-- .../tree_connect_leaves.py | 7 ++- .../tree_with_parent_inorder.py | 18 ++---- 91 files changed, 447 insertions(+), 454 deletions(-) diff --git a/epi_judge_python/absent_value_array.py b/epi_judge_python/absent_value_array.py index 462f9c9ad..94e18e97c 100644 --- a/epi_judge_python/absent_value_array.py +++ b/epi_judge_python/absent_value_array.py @@ -13,7 +13,7 @@ def find_missing_element_wrapper(stream): try: res = find_missing_element(iter(stream)) if res in stream: - raise TestFailure('{} appears in stream'.format(res)) + raise TestFailure(f'{res} appears in stream') except ValueError: raise TestFailure('Unexpected no missing element exception') diff --git a/epi_judge_python/adding_credits.py b/epi_judge_python/adding_credits.py index 5aeae4762..9f31a8c95 100644 --- a/epi_judge_python/adding_credits.py +++ b/epi_judge_python/adding_credits.py @@ -31,8 +31,6 @@ def client_credits_info_tester(ops): op = x[0] s_arg = x[1] i_arg = x[2] - if op == 'ClientsCreditsInfo': - pass if op == 'max': result = cr.max() if result != s_arg: diff --git a/epi_judge_python/alternating_array.py b/epi_judge_python/alternating_array.py index ba55ad39f..8e133079f 100644 --- a/epi_judge_python/alternating_array.py +++ b/epi_judge_python/alternating_array.py @@ -21,25 +21,22 @@ def check_answer(A): PropertyName.RESULT, A).with_mismatch_info( i, 'A[{}] <= A[{}]'.format(i - 1, i), '{} > {}'.format(A[i - 1], A[i])) - if i + 1 < len(A): - if A[i] < A[i + 1]: - raise TestFailure().with_property( - PropertyName.RESULT, A).with_mismatch_info( - i, 'A[{}] >= A[{}]'.format(i, i + 1), - '{} < {}'.format(A[i], A[i + 1])) + if i + 1 < len(A) and A[i] < A[i + 1]: + raise TestFailure().with_property( + PropertyName.RESULT, A).with_mismatch_info( + i, 'A[{}] >= A[{}]'.format(i, i + 1), + '{} < {}'.format(A[i], A[i + 1])) else: - if i > 0: - if A[i - 1] < A[i]: - raise TestFailure().with_property( - PropertyName.RESULT, A).with_mismatch_info( - i, 'A[{}] >= A[{}]'.format(i - 1, i), - '{} < {}'.format(A[i - 1], A[i])) - if i + 1 < len(A): - if A[i + 1] < A[i]: - raise TestFailure().with_property( - PropertyName.RESULT, A).with_mismatch_info( - i, 'A[{}] <= A[{}]'.format(i, i + 1), - '{} > {}'.format(A[i], A[i + 1])) + if i > 0 and A[i - 1] < A[i]: + raise TestFailure().with_property( + PropertyName.RESULT, A).with_mismatch_info( + i, 'A[{}] >= A[{}]'.format(i - 1, i), + '{} < {}'.format(A[i - 1], A[i])) + if i + 1 < len(A) and A[i + 1] < A[i]: + raise TestFailure().with_property( + PropertyName.RESULT, A).with_mismatch_info( + i, 'A[{}] <= A[{}]'.format(i, i + 1), + '{} > {}'.format(A[i], A[i + 1])) executor.run(functools.partial(rearrange, A)) check_answer(A) diff --git a/epi_judge_python/circular_queue.py b/epi_judge_python/circular_queue.py index ffcbb4fdf..25cc94c10 100644 --- a/epi_judge_python/circular_queue.py +++ b/epi_judge_python/circular_queue.py @@ -31,15 +31,13 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}, got ' + str(result))) elif op == 'size': result = q.size() if result != arg: - raise TestFailure('Size: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Size: expected {str(arg)}, got ' + str(result))) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') if __name__ == '__main__': diff --git a/epi_judge_python/copy_posting_list.py b/epi_judge_python/copy_posting_list.py index 924e299e8..12d62af1d 100644 --- a/epi_judge_python/copy_posting_list.py +++ b/epi_judge_python/copy_posting_list.py @@ -13,7 +13,7 @@ def copy_postings_list(L: PostingListNode) -> Optional[PostingListNode]: def assert_lists_equal(orig, copy): - node_mapping = dict() + node_mapping = {} o_it = orig c_it = copy while o_it: @@ -38,10 +38,9 @@ def assert_lists_equal(orig, copy): if c_it.jump is not None: raise TestFailure( 'Jump link points to a different nodes in the copied list') - else: - if not node_mapping[o_it.jump] is c_it.jump: - raise TestFailure( - 'Jump link points to a different nodes in the copied list') + elif node_mapping[o_it.jump] is not c_it.jump: + raise TestFailure( + 'Jump link points to a different nodes in the copied list') o_it = o_it.next c_it = c_it.next @@ -49,7 +48,7 @@ def assert_lists_equal(orig, copy): @enable_executor_hook def copy_postings_list_wrapper(executor, l): def create_posting_list(serialized): - key_mapping = dict() + key_mapping = {} head = None for (order, _) in reversed(serialized): head = PostingListNode(order, head) @@ -58,7 +57,7 @@ def create_posting_list(serialized): list_it = head for (_, jump_index) in serialized: if jump_index != -1: - list_it.jump = key_mapping.get(jump_index, None) + list_it.jump = key_mapping.get(jump_index) if not list_it.jump: raise RuntimeError('Jump index out of range') diff --git a/epi_judge_python/do_lists_overlap.py b/epi_judge_python/do_lists_overlap.py index 4a64c0795..18e2c526d 100644 --- a/epi_judge_python/do_lists_overlap.py +++ b/epi_judge_python/do_lists_overlap.py @@ -61,7 +61,7 @@ def overlapping_lists_wrapper(executor, l0, l1, common, cycle0, cycle1): result = executor.run(functools.partial(overlapping_lists, l0, l1)) - if not (id(result) in common_nodes or (not common_nodes and not result)): + if id(result) not in common_nodes and (common_nodes or result): raise TestFailure('Invalid result') diff --git a/epi_judge_python/dutch_national_flag.py b/epi_judge_python/dutch_national_flag.py index 54ae3ecdd..c73a92415 100644 --- a/epi_judge_python/dutch_national_flag.py +++ b/epi_judge_python/dutch_national_flag.py @@ -34,7 +34,7 @@ def dutch_flag_partition_wrapper(executor, A, pivot_idx): i += 1 if i != len(A): - raise TestFailure('Not partitioned after {}th element'.format(i)) + raise TestFailure(f'Not partitioned after {i}th element') elif any(count): raise TestFailure('Some elements are missing from original array') diff --git a/epi_judge_python/enumerate_trees.py b/epi_judge_python/enumerate_trees.py index 38751b3c9..5351a2a96 100644 --- a/epi_judge_python/enumerate_trees.py +++ b/epi_judge_python/enumerate_trees.py @@ -17,7 +17,7 @@ def serialize_structure(tree): q = [tree] while q: a = q.pop(0) - result.append(0 if not a else 1) + result.append(1 if a else 0) if a: q.append(a.left) q.append(a.right) diff --git a/epi_judge_python/graph_clone.py b/epi_judge_python/graph_clone.py index 420e421d2..05cbfe2ed 100644 --- a/epi_judge_python/graph_clone.py +++ b/epi_judge_python/graph_clone.py @@ -24,10 +24,9 @@ def check_graph(node, graph): if node is None: raise TestFailure('Graph was not copied') - vertex_set = set() q = collections.deque() q.append(node) - vertex_set.add(node) + vertex_set = {node} while q: vertex = q.popleft() if vertex.label >= len(graph): diff --git a/epi_judge_python/gray_code.py b/epi_judge_python/gray_code.py index f06bf3cf3..a21e90862 100644 --- a/epi_judge_python/gray_code.py +++ b/epi_judge_python/gray_code.py @@ -17,8 +17,11 @@ def gray_code_wrapper(executor, num_bits): expected_size = (1 << num_bits) if len(result) != expected_size: - raise TestFailure('Length mismatch: expected ' + str(expected_size) + - ', got ' + str(len(result))) + raise TestFailure( + (f'Length mismatch: expected {str(expected_size)}' + ', got ') + + str(len(result)) + ) + for i in range(1, len(result)): if not differ_by_1_bit(result[i - 1], result[i]): if result[i - 1] == result[i]: diff --git a/epi_judge_python/hanoi.py b/epi_judge_python/hanoi.py index eca2953bc..07993bd7c 100644 --- a/epi_judge_python/hanoi.py +++ b/epi_judge_python/hanoi.py @@ -22,8 +22,10 @@ def compute_tower_hanoi_wrapper(executor, num_rings): for from_peg, to_peg in result: if pegs[to_peg] and pegs[from_peg][-1] >= pegs[to_peg][-1]: - raise TestFailure('Illegal move from {} to {}'.format( - pegs[from_peg][-1], pegs[to_peg][-1])) + raise TestFailure( + f'Illegal move from {pegs[from_peg][-1]} to {pegs[to_peg][-1]}' + ) + pegs[to_peg].append(pegs[from_peg].pop()) expected_pegs1 = [[], [], list(reversed(range(1, num_rings + 1)))] expected_pegs2 = [[], list(reversed(range(1, num_rings + 1))), []] diff --git a/epi_judge_python/lru_cache.py b/epi_judge_python/lru_cache.py index 3b26353c6..a9908510d 100644 --- a/epi_judge_python/lru_cache.py +++ b/epi_judge_python/lru_cache.py @@ -30,17 +30,15 @@ def lru_cache_tester(commands): if cmd[0] == 'lookup': result = cache.lookup(cmd[1]) if result != cmd[2]: - raise TestFailure('Lookup: expected ' + str(cmd[2]) + - ', got ' + str(result)) + raise TestFailure((f'Lookup: expected {str(cmd[2])}' + ', got ') + str(result)) elif cmd[0] == 'insert': cache.insert(cmd[1], cmd[2]) elif cmd[0] == 'erase': result = 1 if cache.erase(cmd[1]) else 0 if result != cmd[2]: - raise TestFailure('Erase: expected ' + str(cmd[2]) + ', got ' + - str(result)) + raise TestFailure((f'Erase: expected {str(cmd[2])}, got ' + str(result))) else: - raise RuntimeError('Unexpected command ' + cmd[0]) + raise RuntimeError(f'Unexpected command {cmd[0]}') if __name__ == '__main__': diff --git a/epi_judge_python/pivot_list.py b/epi_judge_python/pivot_list.py index 3bfa71496..83cb9ebe3 100644 --- a/epi_judge_python/pivot_list.py +++ b/epi_judge_python/pivot_list.py @@ -13,7 +13,7 @@ def list_pivoting(l: ListNode, x: int) -> Optional[ListNode]: def linked_to_list(l): - v = list() + v = [] while l is not None: v.append(l.data) l = l.next @@ -29,20 +29,19 @@ def list_pivoting_wrapper(executor, l, x): pivoted = linked_to_list(l) mode = -1 for i in pivoted: - if mode == -1: - if i == x: - mode = 0 - elif i > x: - mode = 1 - elif mode == 0: - if i < x: - raise TestFailure('List is not pivoted') - elif i > x: - mode = 1 - else: - if i <= x: - raise TestFailure('List is not pivoted') - + if mode == -1 and i == x: + mode = 0 + elif ( + mode == -1 + and i > x + or mode != -1 + and mode == 0 + and i >= x + and i > x + ): + mode = 1 + elif mode != -1 and (mode != 0 or i < x) and (mode == 0 or i <= x): + raise TestFailure('List is not pivoted') if sorted(original) != sorted(pivoted): raise TestFailure('Result list contains different values') diff --git a/epi_judge_python/queue_from_stacks.py b/epi_judge_python/queue_from_stacks.py index 81ea76dcc..169170c1c 100644 --- a/epi_judge_python/queue_from_stacks.py +++ b/epi_judge_python/queue_from_stacks.py @@ -24,10 +24,9 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}' + ', got ') + str(result)) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python/queue_with_max.py b/epi_judge_python/queue_with_max.py index 6c498a735..d370d062f 100644 --- a/epi_judge_python/queue_with_max.py +++ b/epi_judge_python/queue_with_max.py @@ -29,15 +29,13 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}' + ', got ') + str(result)) elif op == 'max': result = q.max() if result != arg: - raise TestFailure('Max: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Max: expected {str(arg)}, got ' + str(result))) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python/refueling_schedule.py b/epi_judge_python/refueling_schedule.py index 56d2ee0a5..8791efbe4 100644 --- a/epi_judge_python/refueling_schedule.py +++ b/epi_judge_python/refueling_schedule.py @@ -25,7 +25,7 @@ def find_ample_city_wrapper(executor, gallons, distances): city = (result + i) % num_cities tank += gallons[city] * MPG - distances[city] if tank < 0: - raise TestFailure('Out of gas on city {}'.format(i)) + raise TestFailure(f'Out of gas on city {i}') if __name__ == '__main__': diff --git a/epi_judge_python/remove_duplicates.py b/epi_judge_python/remove_duplicates.py index fe78ebea7..7098a4b73 100644 --- a/epi_judge_python/remove_duplicates.py +++ b/epi_judge_python/remove_duplicates.py @@ -30,9 +30,9 @@ def eliminate_duplicate_wrapper(executor, names): def comp(expected, result): - return all([ + return all( e == r.first_name for (e, r) in zip(sorted(expected), sorted(result)) - ]) + ) if __name__ == '__main__': diff --git a/epi_judge_python/search_entry_equal_to_index.py b/epi_judge_python/search_entry_equal_to_index.py index f913d7e36..a4139d885 100644 --- a/epi_judge_python/search_entry_equal_to_index.py +++ b/epi_judge_python/search_entry_equal_to_index.py @@ -15,13 +15,13 @@ def search_entry_equal_to_its_index(A: List[int]) -> int: def search_entry_equal_to_its_index_wrapper(executor, A): result = executor.run(functools.partial(search_entry_equal_to_its_index, A)) - if result != -1: - if A[result] != result: - raise TestFailure('Entry does not equal to its index') - else: + if result == -1: if any(i == a for i, a in enumerate(A)): raise TestFailure('There are entries which equal to its index') + elif A[result] != result: + raise TestFailure('Entry does not equal to its index') + if __name__ == '__main__': exit( diff --git a/epi_judge_python/search_maze.py b/epi_judge_python/search_maze.py index 06782c7a4..adb1c2e62 100644 --- a/epi_judge_python/search_maze.py +++ b/epi_judge_python/search_maze.py @@ -19,13 +19,21 @@ def search_maze(maze: List[List[int]], s: Coordinate, def path_element_is_feasible(maze, prev, cur): - if not ((0 <= cur.x < len(maze)) and - (0 <= cur.y < len(maze[cur.x])) and maze[cur.x][cur.y] == WHITE): - return False - return cur == (prev.x + 1, prev.y) or \ - cur == (prev.x - 1, prev.y) or \ - cur == (prev.x, prev.y + 1) or \ - cur == (prev.x, prev.y - 1) + return ( + cur + in [ + (prev.x + 1, prev.y), + (prev.x - 1, prev.y), + (prev.x, prev.y + 1), + (prev.x, prev.y - 1), + ] + if ( + (0 <= cur.x < len(maze)) + and (0 <= cur.y < len(maze[cur.x])) + and maze[cur.x][cur.y] == WHITE + ) + else False + ) @enable_executor_hook diff --git a/epi_judge_python/smallest_subarray_covering_all_values.py b/epi_judge_python/smallest_subarray_covering_all_values.py index b7dc2a595..eb29da89f 100644 --- a/epi_judge_python/smallest_subarray_covering_all_values.py +++ b/epi_judge_python/smallest_subarray_covering_all_values.py @@ -30,8 +30,6 @@ def find_smallest_sequentially_covering_subset_wrapper(executor, paragraph, while kw_idx < len(keywords): if para_idx >= len(paragraph): raise TestFailure('Not all keywords are in the generated subarray') - if para_idx >= len(paragraph): - raise TestFailure('Subarray end index exceeds array size') if paragraph[para_idx] == keywords[kw_idx]: kw_idx += 1 para_idx += 1 diff --git a/epi_judge_python/stack_with_max.py b/epi_judge_python/stack_with_max.py index eedd2e3f2..5be7daa2b 100644 --- a/epi_judge_python/stack_with_max.py +++ b/epi_judge_python/stack_with_max.py @@ -32,20 +32,17 @@ def stack_tester(ops): elif op == 'pop': result = s.pop() if result != arg: - raise TestFailure('Pop: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Pop: expected {str(arg)}, got ' + str(result))) elif op == 'max': result = s.max() if result != arg: - raise TestFailure('Max: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Max: expected {str(arg)}, got ' + str(result))) elif op == 'empty': result = int(s.empty()) if result != arg: - raise TestFailure('Empty: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Empty: expected {str(arg)}' + ', got ') + str(result)) else: - raise RuntimeError('Unsupported stack operation: ' + op) + raise RuntimeError(f'Unsupported stack operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python/sudoku_solve.py b/epi_judge_python/sudoku_solve.py index 09024a312..2ff21ea4d 100644 --- a/epi_judge_python/sudoku_solve.py +++ b/epi_judge_python/sudoku_solve.py @@ -48,7 +48,7 @@ def solve_sudoku_wrapper(executor, partial_assignment): if len(br) != len(sr): raise TestFailure('Initial cell assignment has been changed') for (bcell, scell) in zip(br, sr): - if bcell != 0 and bcell != scell: + if bcell not in [0, scell]: raise TestFailure('Initial cell assignment has been changed') block_size = int(math.sqrt(len(solved))) diff --git a/epi_judge_python/test_framework/binary_tree_utils.py b/epi_judge_python/test_framework/binary_tree_utils.py index 265b3752c..6d27314e7 100644 --- a/epi_judge_python/test_framework/binary_tree_utils.py +++ b/epi_judge_python/test_framework/binary_tree_utils.py @@ -107,7 +107,7 @@ def find_node(tree, val): def must_find_node(tree, val): result = find_node(tree, val) if result is None: - raise RuntimeError('{} was not found in the tree'.format(val)) + raise RuntimeError(f'{val} was not found in the tree') return result @@ -150,13 +150,12 @@ def assert_equal_binary_trees(expected, result): def binary_tree_to_string(tree): - result = '' nodes = collections.deque() visited = set() first = True null_nodes_pending = 0 - result += '[' + result = '' + '[' nodes.append(tree) while nodes: @@ -173,7 +172,7 @@ def binary_tree_to_string(tree): result += 'null, ' null_nodes_pending -= 1 - result += '"{}"'.format(node.data) + result += f'"{node.data}"' visited.add(id(node)) nodes.append(node.left) diff --git a/epi_judge_python/test_framework/console_color.py b/epi_judge_python/test_framework/console_color.py index e2d7e662e..26ef74aa1 100644 --- a/epi_judge_python/test_framework/console_color.py +++ b/epi_judge_python/test_framework/console_color.py @@ -54,6 +54,7 @@ def print_std_out_colored(color, value): sys.stdout.flush() platform.set_console_text_attribute(old_text_attr) else: - print('{}{}{}'.format(get_color_code_unix(color), value, - get_color_code_unix(ConsoleColor.FG_DEFAULT)), - end='') + print( + f'{get_color_code_unix(color)}{value}{get_color_code_unix(ConsoleColor.FG_DEFAULT)}', + end='', + ) diff --git a/epi_judge_python/test_framework/generic_test.py b/epi_judge_python/test_framework/generic_test.py index b7b9ffb4b..bf0eedbd1 100644 --- a/epi_judge_python/test_framework/generic_test.py +++ b/epi_judge_python/test_framework/generic_test.py @@ -52,8 +52,7 @@ def generic_test_main(test_file, test_handler = GenericTestHandler(test_func, comparator) return run_tests(test_handler, config, res_printer) except RuntimeError as e: - print('\nCritical error({}): {}'.format(e.__class__.__name__, e), - file=sys.stderr) + print(f'\nCritical error({e.__class__.__name__}): {e}', file=sys.stderr) return TestResult.RUNTIME_ERROR @@ -141,7 +140,7 @@ def update_test_passed(test_file, tests_passed): problem_mapping_file.read().replace(js_begin_pattern, '').replace( js_end_pattern, '')) - test_file = 'Python: ' + test_file + test_file = f'Python: {test_file}' for chapter in chapter_to_problem_to_language_solution_mapping.values(): for _, language_solution_mapping in chapter.items(): if test_file in language_solution_mapping: diff --git a/epi_judge_python/test_framework/generic_test_handler.py b/epi_judge_python/test_framework/generic_test_handler.py index c3c0ff61f..251eee44c 100644 --- a/epi_judge_python/test_framework/generic_test_handler.py +++ b/epi_judge_python/test_framework/generic_test_handler.py @@ -78,8 +78,9 @@ def run_test(self, timeout_seconds, metrics_override, test_args): self._param_traits) + (0 if self.expected_is_void() else 1) if len(test_args) != expected_param_count: raise RuntimeError( - 'Invalid argument count: expected {}, actual {}'.format( - expected_param_count, len(test_args))) + f'Invalid argument count: expected {expected_param_count}, actual {len(test_args)}' + ) + parsed = [ param_trait.parse(json.loads(test_arg)) diff --git a/epi_judge_python/test_framework/random_sequence_checker.py b/epi_judge_python/test_framework/random_sequence_checker.py index 85d546b20..c66bcda91 100644 --- a/epi_judge_python/test_framework/random_sequence_checker.py +++ b/epi_judge_python/test_framework/random_sequence_checker.py @@ -15,11 +15,14 @@ def compute_deviation_multiplier(allowed_false_negative, num_rvs=1): 1 - 0.999999999997440 ] - for i, bound in enumerate(ERROR_BOUNDS): - if bound <= individual_rv_error: - return i + 1 - - return len(ERROR_BOUNDS) + 1 + return next( + ( + i + 1 + for i, bound in enumerate(ERROR_BOUNDS) + if bound <= individual_rv_error + ), + len(ERROR_BOUNDS) + 1, + ) def check_frequencies(seq, n, false_negative_tolerance): @@ -41,13 +44,12 @@ def check_frequencies(seq, n, false_negative_tolerance): def check_pairs_frequencies(seq, n, false_negative_tolerance): - seq_pairs = [(x, next_x) for x, next_x in zip(seq, seq[1:])] + seq_pairs = list(zip(seq, seq[1:])) return check_frequencies(seq_pairs, n * n, false_negative_tolerance) def check_triples_frequencies(seq, n, false_negative_tolerance): - seq_triples = [(x, next_x, next_next_x) - for x, next_x, next_next_x in zip(seq, seq[1:], seq[2:])] + seq_triples = list(zip(seq, seq[1:], seq[2:])) return check_frequencies(seq_triples, n * n * n, false_negative_tolerance) @@ -106,12 +108,16 @@ def run_func_with_retries(func): if __name__ == '__main__': assert check_sequence_is_uniformly_random( - [random.randint(1, 10) for i in range(1000000)], + [random.randint(1, 10) for _ in range(1000000)], 10, - false_negative_tolerance=0.01) + false_negative_tolerance=0.01, + ) + assert not check_sequence_is_uniformly_random( - [random.randint(1, 11) for i in range(1000000)], + [random.randint(1, 11) for _ in range(1000000)], 10, - false_negative_tolerance=0.01) + false_negative_tolerance=0.01, + ) + assert not check_sequence_is_uniformly_random( [i % 10 for i in range(1000000)], 10, false_negative_tolerance=0.01) diff --git a/epi_judge_python/test_framework/serialization_traits.py b/epi_judge_python/test_framework/serialization_traits.py index efb1cc2f9..f12f18d8e 100644 --- a/epi_judge_python/test_framework/serialization_traits.py +++ b/epi_judge_python/test_framework/serialization_traits.py @@ -48,7 +48,7 @@ def parse(self, json_object): return str(json_object) def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): return [len(x)] @@ -102,13 +102,13 @@ def __init__(self, inner_type_trait): self._inner_type_trait = inner_type_trait def name(self): - return 'array({})'.format(self._inner_type_trait.name()) + return f'array({self._inner_type_trait.name()})' def parse(self, json_object): return [self._inner_type_trait.parse(inner) for inner in json_object] def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): if isinstance(x, list): @@ -126,7 +126,7 @@ def __init__(self, node_type, inner_type_trait): self._inner_type_trait = inner_type_trait def name(self): - return 'binary_tree({})'.format(self._inner_type_trait.name()) + return f'binary_tree({self._inner_type_trait.name()})' def parse(self, json_object): def build_binary_tree(data): @@ -157,7 +157,7 @@ def build_binary_tree(data): return build_binary_tree(json_object) def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name), 'height({})'.format(arg_name)] + return [f'size({arg_name})', f'height({arg_name})'] def get_metrics(self, x): return [binary_tree_size(x), binary_tree_height(x)] @@ -169,8 +169,7 @@ def __init__(self, inner_type_trait): self._list_trait = ListTrait(inner_type_trait) def name(self): - return 'linked_list({})'.format( - self._list_trait.get_inner_trait().name()) + return f'linked_list({self._list_trait.get_inner_trait().name()})' def parse(self, json_object): parsed = self._list_trait.parse(json_object) @@ -180,7 +179,7 @@ def parse(self, json_object): return head def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): if x is None: @@ -196,13 +195,13 @@ def __init__(self, inner_type_trait): self._list_trait = ListTrait(inner_type_trait) def name(self): - return 'set({})'.format(self._list_trait.get_inner_trait().name()) + return f'set({self._list_trait.get_inner_trait().name()})' def parse(self, json_object): return set(self._list_trait.parse(json_object)) def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): if isinstance(x, set): @@ -227,8 +226,9 @@ def name(self): def parse(self, json_object): if len(json_object) != len(self._inner_type_traits): raise RuntimeError( - 'Tuple parser: expected {} values, provide {}'.format( - len(self._inner_type_traits), len(json_object))) + f'Tuple parser: expected {len(self._inner_type_traits)} values, provide {len(json_object)}' + ) + return tuple( inner_type_trait.parse(p) for inner_type_trait, p in zip( self._inner_type_traits, json_object)) @@ -258,26 +258,26 @@ def get_trait(typename): list_regex = re.compile(r'^array\((.*)\)$') m = list_regex.match(typename) if m and len(m.groups()) == 1: - return ListTrait(get_trait(m.group(1))) + return ListTrait(get_trait(m[1])) binary_tree_regex = re.compile(r'^binary_tree\((.*)\)$') m = binary_tree_regex.match(typename) if m and len(m.groups()) == 1: - return BinaryTreeTrait(BinaryTreeNode, get_trait(m.group(1))) + return BinaryTreeTrait(BinaryTreeNode, get_trait(m[1])) linked_list_regex = re.compile(r'^linked_list\((.*)\)$') m = linked_list_regex.match(typename) if m and len(m.groups()) == 1: - return LinkedListTrait(get_trait(m.group(1))) + return LinkedListTrait(get_trait(m[1])) set_regex = re.compile(r'^set\((.*)\)$') m = set_regex.match(typename) if m and len(m.groups()) == 1: - return SetTrait(get_trait(m.group(1))) + return SetTrait(get_trait(m[1])) tuple_regex = re.compile(r'^tuple\((.*)\)$') m = tuple_regex.match(typename) if m and len(m.groups()) == 1: - return TupleTrait([get_trait(x) for x in m.group(1).split(',')]) + return TupleTrait([get_trait(x) for x in m[1].split(',')]) - raise NotImplementedError("Unsupported type " + typename) + raise NotImplementedError(f"Unsupported type {typename}") diff --git a/epi_judge_python/test_framework/test_config.py b/epi_judge_python/test_framework/test_config.py index e839089ca..6160fe0a4 100644 --- a/epi_judge_python/test_framework/test_config.py +++ b/epi_judge_python/test_framework/test_config.py @@ -125,8 +125,9 @@ def from_command_line(test_file, test_data_file, timeout_seconds, if config.test_data_dir: if not os.path.isdir(config.test_data_dir): raise RuntimeError( - 'CL: --test-data-dir argument ({}) is not a directory'. - format(config.test_data_dir)) + f'CL: --test-data-dir argument ({config.test_data_dir}) is not a directory' + ) + else: config.test_data_dir = get_default_test_data_dir_path() diff --git a/epi_judge_python/test_framework/test_timer.py b/epi_judge_python/test_framework/test_timer.py index 2d2ac956e..d75d71c41 100644 --- a/epi_judge_python/test_framework/test_timer.py +++ b/epi_judge_python/test_framework/test_timer.py @@ -29,10 +29,10 @@ def duration_to_string(dur): if dur == 0: return ' <1 us' elif dur < milli_to_micro: - return str(duration_format + ' us').format(dur) + return str(f'{duration_format} us').format(dur) elif dur < second_to_micro: - return str(duration_format + ' ms').format(dur // milli_to_micro) - return str(duration_format + ' s').format(dur // second_to_micro) + return str(f'{duration_format} ms').format(dur // milli_to_micro) + return str(f'{duration_format} s').format(dur // second_to_micro) def avg_and_median_from_durations(durations): diff --git a/epi_judge_python/test_framework/test_utils.py b/epi_judge_python/test_framework/test_utils.py index 7c99ed406..7c1239d45 100644 --- a/epi_judge_python/test_framework/test_utils.py +++ b/epi_judge_python/test_framework/test_utils.py @@ -79,10 +79,7 @@ def completely_sorted(x): then the argument is lexicographically sorted on all levels, starting from the bottom. """ - if isinstance(x, list): - return sorted(completely_sorted(e) for e in x) - else: - return x + return sorted(completely_sorted(e) for e in x) if isinstance(x, list) else x def unordered_compare(a, b): diff --git a/epi_judge_python/test_framework/test_utils_console.py b/epi_judge_python/test_framework/test_utils_console.py index 303870476..c8d4710bc 100644 --- a/epi_judge_python/test_framework/test_utils_console.py +++ b/epi_judge_python/test_framework/test_utils_console.py @@ -50,14 +50,12 @@ def print_test_info(test_result, test_nr, total_tests, diagnostic, timer): flush=True) if timer is not None: - print(' [{}]'.format(duration_to_string(timer.get_microseconds())), - end='', - flush=True) + print(f' [{duration_to_string(timer.get_microseconds())}]', end='', flush=True) print_test_info.caret_at_line_start = False if test_result != TestResult.PASSED: - print(' {}'.format(diagnostic), flush=True) + print(f' {diagnostic}', flush=True) print_test_info.caret_at_line_start = True @@ -75,15 +73,12 @@ def print_failed_test(param_names, arguments, test_failure, res_printer): print_std_out_colored(ConsoleColor.FG_YELLOW, 'Arguments') print() - for (name, value) in zip(param_names, arguments): + for name, value in zip(param_names, arguments): print('\t', end='') print_std_out_colored(ConsoleColor.FG_YELLOW, name) - print(': {}{}'.format(gen_spaces(max_col_size - len(name)), - escape_newline(str(value)))) + print(f': {gen_spaces(max_col_size - len(name))}{escape_newline(str(value))}') - properties = test_failure.get_properties() - - if properties: + if properties := test_failure.get_properties(): print_std_out_colored(ConsoleColor.FG_YELLOW, '\nFailure info\n') for prop in properties: @@ -93,8 +88,7 @@ def print_failed_test(param_names, arguments, test_failure, res_printer): value = prop.value() print('\t', end='') print_std_out_colored(ConsoleColor.FG_YELLOW, prop.name()) - print(': {}{}'.format(gen_spaces(max_col_size - len(prop.name())), - value)) + print(f': {gen_spaces(max_col_size - len(prop.name()))}{value}') def show_complexity_notification(): @@ -105,16 +99,15 @@ def show_complexity_notification(): def print_post_run_stats(tests_passed, total_tests, complexity, durations): if durations: if complexity: - print('Time complexity: {}'.format(complexity)) + print(f'Time complexity: {complexity}') avg_median = avg_and_median_from_durations(durations) - print('Average running time: {}\n' - 'Median running time: {}\n'.format( - duration_to_string(avg_median[0]), - duration_to_string(avg_median[1])), - end='') + print( + f'Average running time: {duration_to_string(avg_median[0])}\nMedian running time: {duration_to_string(avg_median[1])}\n', + end='', + ) + if tests_passed < total_tests: - print('*** You\'ve passed {}/{} tests. ***'.format( - tests_passed, total_tests)) + print(f"*** You\'ve passed {tests_passed}/{total_tests} tests. ***") else: print('*** You\'ve passed ALL tests. Congratulations! ***') diff --git a/epi_judge_python/test_framework/timed_executor.py b/epi_judge_python/test_framework/timed_executor.py index a1fa4a945..0b9cd44b7 100644 --- a/epi_judge_python/test_framework/timed_executor.py +++ b/epi_judge_python/test_framework/timed_executor.py @@ -22,14 +22,13 @@ def run(self, func): if self._timeout_seconds == 0: # Timeout is disabled. return self._timed_call(func) - else: - try: - with futures.ThreadPoolExecutor() as executor: - return next( - executor.map(self._timed_call, (func, ), - timeout=self._timeout_seconds)) - except futures.TimeoutError: - raise TimeoutException(self._timeout_seconds) + try: + with futures.ThreadPoolExecutor() as executor: + return next( + executor.map(self._timed_call, (func, ), + timeout=self._timeout_seconds)) + except futures.TimeoutError: + raise TimeoutException(self._timeout_seconds) def get_timer(self): return self._timer diff --git a/epi_judge_python_solutions/absent_value_array.py b/epi_judge_python_solutions/absent_value_array.py index 65e4284fa..c163b37b6 100644 --- a/epi_judge_python_solutions/absent_value_array.py +++ b/epi_judge_python_solutions/absent_value_array.py @@ -41,7 +41,7 @@ def find_missing_element_wrapper(stream): try: res = find_missing_element(iter(stream)) if res in stream: - raise TestFailure('{} appears in stream'.format(res)) + raise TestFailure(f'{res} appears in stream') except ValueError: raise TestFailure('Unexpected no missing element exception') diff --git a/epi_judge_python_solutions/adding_credits.py b/epi_judge_python_solutions/adding_credits.py index 447174011..7eba6d286 100644 --- a/epi_judge_python_solutions/adding_credits.py +++ b/epi_judge_python_solutions/adding_credits.py @@ -42,7 +42,7 @@ def max(self) -> str: if not self._credit_to_clients: return '' clients = self._credit_to_clients.max_item()[1] - return '' if not clients else next(iter(clients)) + return next(iter(clients)) if clients else '' def client_credits_info_tester(ops): @@ -52,8 +52,6 @@ def client_credits_info_tester(ops): op = x[0] s_arg = x[1] i_arg = x[2] - if op == 'ClientsCreditsInfo': - pass if op == 'max': result = cr.max() if result != s_arg: diff --git a/epi_judge_python_solutions/advance_by_offsets.py b/epi_judge_python_solutions/advance_by_offsets.py index 3532a5fab..e0e7c4719 100644 --- a/epi_judge_python_solutions/advance_by_offsets.py +++ b/epi_judge_python_solutions/advance_by_offsets.py @@ -7,7 +7,7 @@ def can_reach_end(A: List[int]) -> bool: furthest_reach_so_far, last_index = 0, len(A) - 1 i = 0 - while i <= furthest_reach_so_far and furthest_reach_so_far < last_index: + while i <= furthest_reach_so_far < last_index: furthest_reach_so_far = max(furthest_reach_so_far, A[i] + i) i += 1 return furthest_reach_so_far >= last_index diff --git a/epi_judge_python_solutions/alternating_array.py b/epi_judge_python_solutions/alternating_array.py index 100d43270..2c7217345 100644 --- a/epi_judge_python_solutions/alternating_array.py +++ b/epi_judge_python_solutions/alternating_array.py @@ -22,25 +22,22 @@ def check_answer(A): PropertyName.RESULT, A).with_mismatch_info( i, 'A[{}] <= A[{}]'.format(i - 1, i), '{} > {}'.format(A[i - 1], A[i])) - if i + 1 < len(A): - if A[i] < A[i + 1]: - raise TestFailure().with_property( - PropertyName.RESULT, A).with_mismatch_info( - i, 'A[{}] >= A[{}]'.format(i, i + 1), - '{} < {}'.format(A[i], A[i + 1])) + if i + 1 < len(A) and A[i] < A[i + 1]: + raise TestFailure().with_property( + PropertyName.RESULT, A).with_mismatch_info( + i, 'A[{}] >= A[{}]'.format(i, i + 1), + '{} < {}'.format(A[i], A[i + 1])) else: - if i > 0: - if A[i - 1] < A[i]: - raise TestFailure().with_property( - PropertyName.RESULT, A).with_mismatch_info( - i, 'A[{}] >= A[{}]'.format(i - 1, i), - '{} < {}'.format(A[i - 1], A[i])) - if i + 1 < len(A): - if A[i + 1] < A[i]: - raise TestFailure().with_property( - PropertyName.RESULT, A).with_mismatch_info( - i, 'A[{}] <= A[{}]'.format(i, i + 1), - '{} > {}'.format(A[i], A[i + 1])) + if i > 0 and A[i - 1] < A[i]: + raise TestFailure().with_property( + PropertyName.RESULT, A).with_mismatch_info( + i, 'A[{}] >= A[{}]'.format(i - 1, i), + '{} < {}'.format(A[i - 1], A[i])) + if i + 1 < len(A) and A[i + 1] < A[i]: + raise TestFailure().with_property( + PropertyName.RESULT, A).with_mismatch_info( + i, 'A[{}] <= A[{}]'.format(i, i + 1), + '{} > {}'.format(A[i], A[i + 1])) executor.run(functools.partial(rearrange, A)) check_answer(A) diff --git a/epi_judge_python_solutions/circular_queue.py b/epi_judge_python_solutions/circular_queue.py index ae35d6510..16ae001e5 100644 --- a/epi_judge_python_solutions/circular_queue.py +++ b/epi_judge_python_solutions/circular_queue.py @@ -49,15 +49,13 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}, got ' + str(result))) elif op == 'size': result = q.size() if result != arg: - raise TestFailure('Size: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Size: expected {str(arg)}, got ' + str(result))) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') if __name__ == '__main__': diff --git a/epi_judge_python_solutions/collatz_checker.py b/epi_judge_python_solutions/collatz_checker.py index ab01aaebf..23a4d9e80 100644 --- a/epi_judge_python_solutions/collatz_checker.py +++ b/epi_judge_python_solutions/collatz_checker.py @@ -12,7 +12,7 @@ def test_collatz_conjecture(n: int) -> bool: for i in range(3, n + 1): sequence: Set[int] = set() test_i = i - while test_i >= i: + while test_i >= test_i: if test_i in sequence: # We previously encountered test_i, so the Collatz sequence has # fallen into a loop. This disproves the hypothesis, so we diff --git a/epi_judge_python_solutions/copy_posting_list.py b/epi_judge_python_solutions/copy_posting_list.py index 52d987c7d..55071726c 100644 --- a/epi_judge_python_solutions/copy_posting_list.py +++ b/epi_judge_python_solutions/copy_posting_list.py @@ -38,7 +38,7 @@ def copy_postings_list(L: PostingListNode) -> Optional[PostingListNode]: def assert_lists_equal(orig, copy): - node_mapping = dict() + node_mapping = {} o_it = orig c_it = copy while o_it: @@ -63,10 +63,9 @@ def assert_lists_equal(orig, copy): if c_it.jump is not None: raise TestFailure( 'Jump link points to a different nodes in the copied list') - else: - if not node_mapping[o_it.jump] is c_it.jump: - raise TestFailure( - 'Jump link points to a different nodes in the copied list') + elif node_mapping[o_it.jump] is not c_it.jump: + raise TestFailure( + 'Jump link points to a different nodes in the copied list') o_it = o_it.next c_it = c_it.next @@ -74,7 +73,7 @@ def assert_lists_equal(orig, copy): @enable_executor_hook def copy_postings_list_wrapper(executor, l): def create_posting_list(serialized): - key_mapping = dict() + key_mapping = {} head = None for (order, _) in reversed(serialized): head = PostingListNode(order, head) @@ -83,7 +82,7 @@ def create_posting_list(serialized): list_it = head for (_, jump_index) in serialized: if jump_index != -1: - list_it.jump = key_mapping.get(jump_index, None) + list_it.jump = key_mapping.get(jump_index) if not list_it.jump: raise RuntimeError('Jump index out of range') diff --git a/epi_judge_python_solutions/directory_path_normalization.py b/epi_judge_python_solutions/directory_path_normalization.py index c38a2a21e..c1b86613a 100644 --- a/epi_judge_python_solutions/directory_path_normalization.py +++ b/epi_judge_python_solutions/directory_path_normalization.py @@ -16,9 +16,9 @@ def shortest_equivalent_path(path: str) -> str: if token == '..': if not path_names or path_names[-1] == '..': path_names.append(token) + elif path_names[-1] == '/': + raise ValueError('Path error') else: - if path_names[-1] == '/': - raise ValueError('Path error') path_names.pop() else: # Must be a name. path_names.append(token) diff --git a/epi_judge_python_solutions/do_lists_overlap.py b/epi_judge_python_solutions/do_lists_overlap.py index 4e3010f9e..7625b0bea 100644 --- a/epi_judge_python_solutions/do_lists_overlap.py +++ b/epi_judge_python_solutions/do_lists_overlap.py @@ -17,7 +17,7 @@ def overlapping_lists(l0: ListNode, l1: ListNode) -> Optional[ListNode]: if not root0 and not root1: # Both lists don't have cycles. return overlapping_no_cycle_lists(l0, l1) - elif (root0 and not root1) or (not root0 and root1): + elif root0 and not root1 or not root0: # One list has cycle, one list has no cycle. return None # Both lists have cycles. @@ -79,7 +79,7 @@ def overlapping_lists_wrapper(executor, l0, l1, common, cycle0, cycle1): result = executor.run(functools.partial(overlapping_lists, l0, l1)) - if not (id(result) in common_nodes or (not common_nodes and not result)): + if id(result) not in common_nodes and (common_nodes or result): raise TestFailure('Invalid result') diff --git a/epi_judge_python_solutions/dutch_national_flag.py b/epi_judge_python_solutions/dutch_national_flag.py index 3f3dcb141..44f66e7e9 100644 --- a/epi_judge_python_solutions/dutch_national_flag.py +++ b/epi_judge_python_solutions/dutch_national_flag.py @@ -51,7 +51,7 @@ def dutch_flag_partition_wrapper(executor, A, pivot_idx): i += 1 if i != len(A): - raise TestFailure('Not partitioned after {}th element'.format(i)) + raise TestFailure(f'Not partitioned after {i}th element') elif any(count): raise TestFailure('Some elements are missing from original array') diff --git a/epi_judge_python_solutions/enumerate_balanced_parentheses.py b/epi_judge_python_solutions/enumerate_balanced_parentheses.py index e070e7c5a..74a26351b 100644 --- a/epi_judge_python_solutions/enumerate_balanced_parentheses.py +++ b/epi_judge_python_solutions/enumerate_balanced_parentheses.py @@ -5,18 +5,24 @@ def generate_balanced_parentheses(num_pairs: int) -> List[str]: def directed_generate_balanced_parentheses(num_left_parens_needed, - num_right_parens_needed, - valid_prefix, - result=[]): - if num_left_parens_needed > 0: # Able to insert '('. - directed_generate_balanced_parentheses(num_left_parens_needed - 1, num_right_parens_needed, - valid_prefix + '(') + valid_prefix, + result=[]): + if num_left_parens_needed > 0: # Able to insert '('. + directed_generate_balanced_parentheses( + num_left_parens_needed - 1, + num_right_parens_needed, + f'{valid_prefix}(', + ) + if num_left_parens_needed < num_right_parens_needed: # Able to insert ')'. - directed_generate_balanced_parentheses(num_left_parens_needed, - num_right_parens_needed - 1, - valid_prefix + ')') + directed_generate_balanced_parentheses( + num_left_parens_needed, + num_right_parens_needed - 1, + f'{valid_prefix})', + ) + if not num_right_parens_needed: result.append(valid_prefix) return result @@ -29,19 +35,29 @@ def directed_generate_balanced_parentheses(num_left_parens_needed, def generate_balanced_parentheses_pythonic(num_pairs, num_left_open=0): if not num_pairs: return [')' * num_left_open] - if not num_left_open: - return [ - '(' + p for p in generate_balanced_parentheses_pythonic( - num_pairs - 1, num_left_open + 1) + return ( + ( + [ + f'({p}' + for p in generate_balanced_parentheses_pythonic( + num_pairs - 1, num_left_open + 1 + ) + ] + + [ + f'){p}' + for p in generate_balanced_parentheses_pythonic( + num_pairs - 1, num_left_open - 1 + ) + ] + ) + if num_left_open + else [ + f'({p}' + for p in generate_balanced_parentheses_pythonic( + num_pairs - 1, num_left_open + 1 + ) ] - else: - return ([ - '(' + p for p in generate_balanced_parentheses_pythonic( - num_pairs - 1, num_left_open + 1) - ] + [ - ')' + p for p in generate_balanced_parentheses_pythonic( - num_pairs - 1, num_left_open - 1) - ]) + ) if __name__ == '__main__': diff --git a/epi_judge_python_solutions/enumerate_trees.py b/epi_judge_python_solutions/enumerate_trees.py index cb86be307..b4dc194a3 100644 --- a/epi_judge_python_solutions/enumerate_trees.py +++ b/epi_judge_python_solutions/enumerate_trees.py @@ -40,7 +40,7 @@ def serialize_structure(tree): q = [tree] while q: a = q.pop(0) - result.append(0 if not a else 1) + result.append(1 if a else 0) if a: q.append(a.left) q.append(a.right) diff --git a/epi_judge_python_solutions/fibonacci.py b/epi_judge_python_solutions/fibonacci.py index e713400ca..9478097f0 100644 --- a/epi_judge_python_solutions/fibonacci.py +++ b/epi_judge_python_solutions/fibonacci.py @@ -6,9 +6,7 @@ @functools.lru_cache(None) def fibonacci(n: int) -> int: - if n <= 1: - return n - return fibonacci(n - 1) + fibonacci(n - 2) + return n if n <= 1 else fibonacci(n - 1) + fibonacci(n - 2) if __name__ == '__main__': diff --git a/epi_judge_python_solutions/gcd.py b/epi_judge_python_solutions/gcd.py index 3d9eef636..a73dbf8d1 100644 --- a/epi_judge_python_solutions/gcd.py +++ b/epi_judge_python_solutions/gcd.py @@ -9,9 +9,9 @@ def gcd(x: int, y: int) -> int: return y elif not x & 1 and not y & 1: # x and y are even. return gcd(x >> 1, y >> 1) << 1 - elif not x & 1 and y & 1: # x is even, y is odd. + elif not x & 1: # x is even, y is odd. return gcd(x >> 1, y) - elif x & 1 and not y & 1: # x is odd, y is even. + elif not y & 1: # x is odd, y is even. return gcd(x, y >> 1) return gcd(x, y - x) # Both x and y are odd. diff --git a/epi_judge_python_solutions/graph_clone.py b/epi_judge_python_solutions/graph_clone.py index dfbd9e3e3..b3eea0bf2 100644 --- a/epi_judge_python_solutions/graph_clone.py +++ b/epi_judge_python_solutions/graph_clone.py @@ -38,10 +38,9 @@ def check_graph(node, graph): if node is None: raise TestFailure('Graph was not copied') - vertex_set = set() q = collections.deque() q.append(node) - vertex_set.add(node) + vertex_set = {node} while q: vertex = q.popleft() if vertex.label >= len(graph): diff --git a/epi_judge_python_solutions/gray_code.py b/epi_judge_python_solutions/gray_code.py index e4a750fb9..f51c85a39 100644 --- a/epi_judge_python_solutions/gray_code.py +++ b/epi_judge_python_solutions/gray_code.py @@ -30,7 +30,7 @@ def differs_by_one_bit(x, y): return False result = [0] - directed_gray_code(set([0])) + directed_gray_code({0}) return result @@ -49,8 +49,11 @@ def gray_code_wrapper(executor, num_bits): expected_size = (1 << num_bits) if len(result) != expected_size: - raise TestFailure('Length mismatch: expected ' + str(expected_size) + - ', got ' + str(len(result))) + raise TestFailure( + (f'Length mismatch: expected {str(expected_size)}' + ', got ') + + str(len(result)) + ) + for i in range(1, len(result)): if not differ_by_1_bit(result[i - 1], result[i]): if result[i - 1] == result[i]: diff --git a/epi_judge_python_solutions/h_index.py b/epi_judge_python_solutions/h_index.py index 9ad24b01d..1ae95dd23 100644 --- a/epi_judge_python_solutions/h_index.py +++ b/epi_judge_python_solutions/h_index.py @@ -7,10 +7,7 @@ def h_index(citations: List[int]) -> int: citations.sort() n = len(citations) - for i, c in enumerate(citations): - if c >= n - i: - return n - i - return 0 + return next((n - i for i, c in enumerate(citations) if c >= n - i), 0) if __name__ == '__main__': diff --git a/epi_judge_python_solutions/hanoi.py b/epi_judge_python_solutions/hanoi.py index 0165cb8f5..b99b78e9c 100644 --- a/epi_judge_python_solutions/hanoi.py +++ b/epi_judge_python_solutions/hanoi.py @@ -36,8 +36,10 @@ def compute_tower_hanoi_wrapper(executor, num_rings): for from_peg, to_peg in result: if pegs[to_peg] and pegs[from_peg][-1] >= pegs[to_peg][-1]: - raise TestFailure('Illegal move from {} to {}'.format( - pegs[from_peg][-1], pegs[to_peg][-1])) + raise TestFailure( + f'Illegal move from {pegs[from_peg][-1]} to {pegs[to_peg][-1]}' + ) + pegs[to_peg].append(pegs[from_peg].pop()) expected_pegs1 = [[], [], list(reversed(range(1, num_rings + 1)))] expected_pegs2 = [[], list(reversed(range(1, num_rings + 1))), []] diff --git a/epi_judge_python_solutions/is_number_palindromic.py b/epi_judge_python_solutions/is_number_palindromic.py index 82aacb3d6..2abae41ed 100644 --- a/epi_judge_python_solutions/is_number_palindromic.py +++ b/epi_judge_python_solutions/is_number_palindromic.py @@ -10,7 +10,7 @@ def is_palindrome_number(x: int) -> bool: num_digits = math.floor(math.log10(x)) + 1 msd_mask = 10**(num_digits - 1) - for i in range(num_digits // 2): + for _ in range(num_digits // 2): if x // msd_mask != x % 10: return False x %= msd_mask # Remove the most significant digit of x. diff --git a/epi_judge_python_solutions/is_string_in_matrix.py b/epi_judge_python_solutions/is_string_in_matrix.py index a05292c8f..41ca49ada 100644 --- a/epi_judge_python_solutions/is_string_in_matrix.py +++ b/epi_judge_python_solutions/is_string_in_matrix.py @@ -14,8 +14,11 @@ def is_pattern_suffix_contained_starting_at_xy(x, y, offset): # Early return if (x, y) lies outside the grid or the character # does not match or we have already tried this combination. - if (not (0 <= x < len(grid) and 0 <= y < len(grid[x])) - or grid[x][y] != pattern[offset]): + if ( + not 0 <= x < len(grid) + or not 0 <= y < len(grid[x]) + or grid[x][y] != pattern[offset] + ): return False return any( diff --git a/epi_judge_python_solutions/k_largest_in_heap.py b/epi_judge_python_solutions/k_largest_in_heap.py index a341b7f87..dc62b9805 100644 --- a/epi_judge_python_solutions/k_largest_in_heap.py +++ b/epi_judge_python_solutions/k_largest_in_heap.py @@ -12,9 +12,7 @@ def k_largest_in_binary_heap(A: List[int], k: int) -> List[int]: # Stores the (-value, index)-pair in candidate_max_heap. This heap is # ordered by value field. Uses the negative of value to get the effect of # a max heap. - candidate_max_heap = [] - # The largest element in A is at index 0. - candidate_max_heap.append((-A[0], 0)) + candidate_max_heap = [(-A[0], 0)] result = [] for _ in range(k): candidate_idx = candidate_max_heap[0][1] diff --git a/epi_judge_python_solutions/kth_largest_element_in_two_sorted_arrays.py b/epi_judge_python_solutions/kth_largest_element_in_two_sorted_arrays.py index ce5f09569..7fe050145 100644 --- a/epi_judge_python_solutions/kth_largest_element_in_two_sorted_arrays.py +++ b/epi_judge_python_solutions/kth_largest_element_in_two_sorted_arrays.py @@ -27,7 +27,7 @@ def find_kth_in_two_sorted_arrays(A: List[int], B: List[int], k: int) -> int: return typing.cast(int, max(A_x_1, B_k_x_1)) A_b_1 = float('-inf') if b <= 0 else A[b - 1] - B_k_b_1 = float('-inf') if k - b - 1 < 0 else B[k - b - 1] + B_k_b_1 = float('-inf') if k - b < 1 else B[k - b - 1] return typing.cast(int, max(A_b_1, B_k_b_1)) diff --git a/epi_judge_python_solutions/largest_rectangle_under_skyline.py b/epi_judge_python_solutions/largest_rectangle_under_skyline.py index 3eb382a09..955d9786f 100644 --- a/epi_judge_python_solutions/largest_rectangle_under_skyline.py +++ b/epi_judge_python_solutions/largest_rectangle_under_skyline.py @@ -12,7 +12,7 @@ def calculate_largest_rectangle(heights: List[int]) -> int: for i, h in enumerate(heights + [0]): while pillar_indices and heights[pillar_indices[-1]] >= h: height = heights[pillar_indices.pop()] - width = i if not pillar_indices else i - pillar_indices[-1] - 1 + width = i - pillar_indices[-1] - 1 if pillar_indices else i max_rectangle_area = max(max_rectangle_area, height * width) pillar_indices.append(i) return max_rectangle_area diff --git a/epi_judge_python_solutions/lru_cache.py b/epi_judge_python_solutions/lru_cache.py index 64e149451..0d652a04f 100644 --- a/epi_judge_python_solutions/lru_cache.py +++ b/epi_judge_python_solutions/lru_cache.py @@ -44,17 +44,15 @@ def lru_cache_tester(commands): if cmd[0] == 'lookup': result = cache.lookup(cmd[1]) if result != cmd[2]: - raise TestFailure('Lookup: expected ' + str(cmd[2]) + - ', got ' + str(result)) + raise TestFailure((f'Lookup: expected {str(cmd[2])}' + ', got ') + str(result)) elif cmd[0] == 'insert': cache.insert(cmd[1], cmd[2]) elif cmd[0] == 'erase': result = 1 if cache.erase(cmd[1]) else 0 if result != cmd[2]: - raise TestFailure('Erase: expected ' + str(cmd[2]) + ', got ' + - str(result)) + raise TestFailure((f'Erase: expected {str(cmd[2])}, got ' + str(result))) else: - raise RuntimeError('Unexpected command ' + cmd[0]) + raise RuntimeError(f'Unexpected command {cmd[0]}') if __name__ == '__main__': diff --git a/epi_judge_python_solutions/minimum_waiting_time.py b/epi_judge_python_solutions/minimum_waiting_time.py index b0da6102b..2e59786b7 100644 --- a/epi_judge_python_solutions/minimum_waiting_time.py +++ b/epi_judge_python_solutions/minimum_waiting_time.py @@ -7,11 +7,10 @@ def minimum_total_waiting_time(service_times: List[int]) -> int: # Sort the service times in increasing order. service_times.sort() - total_waiting_time = 0 - for i, service_time in enumerate(service_times): - num_remaining_queries = len(service_times) - (i + 1) - total_waiting_time += service_time * num_remaining_queries - return total_waiting_time + return sum( + service_time * (len(service_times) - (i + 1)) + for i, service_time in enumerate(service_times) + ) def minimum_total_waiting_time_pythonic(service_times): diff --git a/epi_judge_python_solutions/number_of_traversals_matrix.py b/epi_judge_python_solutions/number_of_traversals_matrix.py index 0d8c2713a..2f823ca97 100644 --- a/epi_judge_python_solutions/number_of_traversals_matrix.py +++ b/epi_judge_python_solutions/number_of_traversals_matrix.py @@ -22,7 +22,7 @@ def number_of_ways_space_efficient(n, m): n, m = m, n table = [1] * m - for i in range(1, n): + for _ in range(1, n): prev_res = 0 for j in range(m): table[j] += prev_res diff --git a/epi_judge_python_solutions/path_sum.py b/epi_judge_python_solutions/path_sum.py index e2f586409..59edac8ab 100644 --- a/epi_judge_python_solutions/path_sum.py +++ b/epi_judge_python_solutions/path_sum.py @@ -6,11 +6,12 @@ def has_path_sum(tree: BinaryTreeNode, remaining_weight: int) -> bool: if not tree: return False - if not tree.left and not tree.right: # Leaf. + if tree.left or tree.right: + # Non-leaf. + return (has_path_sum(tree.left, remaining_weight - tree.data) + or has_path_sum(tree.right, remaining_weight - tree.data)) + else: # Leaf. return remaining_weight == tree.data - # Non-leaf. - return (has_path_sum(tree.left, remaining_weight - tree.data) - or has_path_sum(tree.right, remaining_weight - tree.data)) if __name__ == '__main__': diff --git a/epi_judge_python_solutions/picking_up_coins.py b/epi_judge_python_solutions/picking_up_coins.py index 59ea6cdf1..4b1bbafc7 100644 --- a/epi_judge_python_solutions/picking_up_coins.py +++ b/epi_judge_python_solutions/picking_up_coins.py @@ -32,10 +32,18 @@ def compute_maximum_revenue_for_range(a, b): return coins[a] return max( - coins[a] + prefix_sum[b] - (prefix_sum[a] if a + 1 > 0 else 0) - - compute_maximum_revenue_for_range(a + 1, b), coins[b] + - prefix_sum[b - 1] - (prefix_sum[a - 1] if a > 0 else 0) - - compute_maximum_revenue_for_range(a, b - 1)) + ( + coins[a] + + prefix_sum[b] + - (prefix_sum[a] if a > -1 else 0) + - compute_maximum_revenue_for_range(a + 1, b) + ), + coins[b] + + prefix_sum[b - 1] + - (prefix_sum[a - 1] if a > 0 else 0) + - compute_maximum_revenue_for_range(a, b - 1), + ) + prefix_sum = list(itertools.accumulate(coins)) return compute_maximum_revenue_for_range(0, len(coins) - 1) diff --git a/epi_judge_python_solutions/pivot_list.py b/epi_judge_python_solutions/pivot_list.py index a8895daab..8e503376d 100644 --- a/epi_judge_python_solutions/pivot_list.py +++ b/epi_judge_python_solutions/pivot_list.py @@ -32,7 +32,7 @@ def list_pivoting(l: ListNode, x: int) -> Optional[ListNode]: def linked_to_list(l): - v = list() + v = [] while l is not None: v.append(l.data) l = l.next @@ -48,20 +48,19 @@ def list_pivoting_wrapper(executor, l, x): pivoted = linked_to_list(l) mode = -1 for i in pivoted: - if mode == -1: - if i == x: - mode = 0 - elif i > x: - mode = 1 - elif mode == 0: - if i < x: - raise TestFailure('List is not pivoted') - elif i > x: - mode = 1 - else: - if i <= x: - raise TestFailure('List is not pivoted') - + if mode == -1 and i == x: + mode = 0 + elif ( + mode == -1 + and i > x + or mode != -1 + and mode == 0 + and i >= x + and i > x + ): + mode = 1 + elif mode != -1 and (mode != 0 or i < x) and (mode == 0 or i <= x): + raise TestFailure('List is not pivoted') if sorted(original) != sorted(pivoted): raise TestFailure('Result list contains different values') diff --git a/epi_judge_python_solutions/pretty_printing.py b/epi_judge_python_solutions/pretty_printing.py index 96d01d6c8..f3ae42031 100644 --- a/epi_judge_python_solutions/pretty_printing.py +++ b/epi_judge_python_solutions/pretty_printing.py @@ -19,7 +19,7 @@ def minimum_messiness(words: List[str], line_length: int) -> int: if num_remaining_blanks < 0: # Not enough space to add more words. break - first_j_messiness = 0 if j - 1 < 0 else min_messiness[j - 1] + first_j_messiness = 0 if j < 1 else min_messiness[j - 1] current_line_messiness = num_remaining_blanks**2 min_messiness[i] = min(min_messiness[i], first_j_messiness + current_line_messiness) diff --git a/epi_judge_python_solutions/queue_from_stacks.py b/epi_judge_python_solutions/queue_from_stacks.py index a760be24a..fad99021c 100644 --- a/epi_judge_python_solutions/queue_from_stacks.py +++ b/epi_judge_python_solutions/queue_from_stacks.py @@ -34,10 +34,9 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}' + ', got ') + str(result)) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python_solutions/queue_with_max.py b/epi_judge_python_solutions/queue_with_max.py index 451cabdcb..4d3d3a5ed 100644 --- a/epi_judge_python_solutions/queue_with_max.py +++ b/epi_judge_python_solutions/queue_with_max.py @@ -39,15 +39,13 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}' + ', got ') + str(result)) elif op == 'max': result = q.max() if result != arg: - raise TestFailure('Max: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Max: expected {str(arg)}, got ' + str(result))) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python_solutions/queue_with_max_using_deque.py b/epi_judge_python_solutions/queue_with_max_using_deque.py index 131cc3cbb..3ea510525 100644 --- a/epi_judge_python_solutions/queue_with_max_using_deque.py +++ b/epi_judge_python_solutions/queue_with_max_using_deque.py @@ -41,15 +41,13 @@ def queue_tester(ops): elif op == 'dequeue': result = q.dequeue() if result != arg: - raise TestFailure('Dequeue: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Dequeue: expected {str(arg)}' + ', got ') + str(result)) elif op == 'max': result = q.max() if result != arg: - raise TestFailure('Max: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Max: expected {str(arg)}, got ' + str(result))) else: - raise RuntimeError('Unsupported queue operation: ' + op) + raise RuntimeError(f'Unsupported queue operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python_solutions/rectangle_intersection.py b/epi_judge_python_solutions/rectangle_intersection.py index 1dca78de4..ee3bd9382 100644 --- a/epi_judge_python_solutions/rectangle_intersection.py +++ b/epi_judge_python_solutions/rectangle_intersection.py @@ -11,11 +11,16 @@ def is_intersect(r1, r2): return (r1.x <= r2.x + r2.width and r1.x + r1.width >= r2.x and r1.y <= r2.y + r2.height and r1.y + r1.height >= r2.y) - if not is_intersect(r1, r2): - return Rect(0, 0, -1, -1) # No intersection. - return Rect(max(r1.x, r2.x), max(r1.y, r2.y), - min(r1.x + r1.width, r2.x + r2.width) - max(r1.x, r2.x), - min(r1.y + r1.height, r2.y + r2.height) - max(r1.y, r2.y)) + return ( + Rect( + max(r1.x, r2.x), + max(r1.y, r2.y), + min(r1.x + r1.width, r2.x + r2.width) - max(r1.x, r2.x), + min(r1.y + r1.height, r2.y + r2.height) - max(r1.y, r2.y), + ) + if is_intersect(r1, r2) + else Rect(0, 0, -1, -1) + ) def intersect_rectangle_wrapper(r1, r2): diff --git a/epi_judge_python_solutions/refueling_schedule.py b/epi_judge_python_solutions/refueling_schedule.py index aeabe727d..7809146f4 100644 --- a/epi_judge_python_solutions/refueling_schedule.py +++ b/epi_judge_python_solutions/refueling_schedule.py @@ -36,7 +36,7 @@ def find_ample_city_wrapper(executor, gallons, distances): city = (result + i) % num_cities tank += gallons[city] * MPG - distances[city] if tank < 0: - raise TestFailure('Out of gas on city {}'.format(i)) + raise TestFailure(f'Out of gas on city {i}') if __name__ == '__main__': diff --git a/epi_judge_python_solutions/remove_duplicates.py b/epi_judge_python_solutions/remove_duplicates.py index fa2543ded..ca78583fe 100644 --- a/epi_judge_python_solutions/remove_duplicates.py +++ b/epi_judge_python_solutions/remove_duplicates.py @@ -19,7 +19,7 @@ def __lt__(self, other) -> bool: self.last_name < other.last_name) def __repr__(self): - return '%s %s' % (self.first_name, self.last_name) + return f'{self.first_name} {self.last_name}' def eliminate_duplicate(A: List[Name]) -> None: @@ -52,9 +52,9 @@ def eliminate_duplicate_wrapper(executor, names): def comp(expected, result): - return all([ + return all( e == r.first_name for (e, r) in zip(sorted(expected), sorted(result)) - ]) + ) if __name__ == '__main__': diff --git a/epi_judge_python_solutions/reverse_bits.py b/epi_judge_python_solutions/reverse_bits.py index 8a98038a7..29aef7d7b 100644 --- a/epi_judge_python_solutions/reverse_bits.py +++ b/epi_judge_python_solutions/reverse_bits.py @@ -5964,8 +5964,8 @@ def reverse_bits(x: int) -> int: - - + + mask_size = 16 bit_mask = 0xFFFF return (PRECOMPUTED_REVERSE[x & bit_mask] << (3 * mask_size) diff --git a/epi_judge_python_solutions/search_entry_equal_to_index.py b/epi_judge_python_solutions/search_entry_equal_to_index.py index 4562894aa..ab8d6d402 100644 --- a/epi_judge_python_solutions/search_entry_equal_to_index.py +++ b/epi_judge_python_solutions/search_entry_equal_to_index.py @@ -26,13 +26,13 @@ def search_entry_equal_to_its_index(A: List[int]) -> int: def search_entry_equal_to_its_index_wrapper(executor, A): result = executor.run(functools.partial(search_entry_equal_to_its_index, A)) - if result != -1: - if A[result] != result: - raise TestFailure('Entry does not equal to its index') - else: + if result == -1: if any(i == a for i, a in enumerate(A)): raise TestFailure('There are entries which equal to its index') + elif A[result] != result: + raise TestFailure('Entry does not equal to its index') + if __name__ == '__main__': exit( diff --git a/epi_judge_python_solutions/search_maze.py b/epi_judge_python_solutions/search_maze.py index 721a14c92..4bbae54d9 100644 --- a/epi_judge_python_solutions/search_maze.py +++ b/epi_judge_python_solutions/search_maze.py @@ -42,13 +42,21 @@ def search_maze_helper(cur): def path_element_is_feasible(maze, prev, cur): - if not ((0 <= cur.x < len(maze)) and - (0 <= cur.y < len(maze[cur.x])) and maze[cur.x][cur.y] == WHITE): - return False - return cur == (prev.x + 1, prev.y) or \ - cur == (prev.x - 1, prev.y) or \ - cur == (prev.x, prev.y + 1) or \ - cur == (prev.x, prev.y - 1) + return ( + cur + in [ + (prev.x + 1, prev.y), + (prev.x - 1, prev.y), + (prev.x, prev.y + 1), + (prev.x, prev.y - 1), + ] + if ( + (0 <= cur.x < len(maze)) + and (0 <= cur.y < len(maze[cur.x])) + and maze[cur.x][cur.y] == WHITE + ) + else False + ) @enable_executor_hook diff --git a/epi_judge_python_solutions/smallest_subarray_covering_all_values.py b/epi_judge_python_solutions/smallest_subarray_covering_all_values.py index 35434ff0a..bb0329ee1 100644 --- a/epi_judge_python_solutions/smallest_subarray_covering_all_values.py +++ b/epi_judge_python_solutions/smallest_subarray_covering_all_values.py @@ -62,8 +62,6 @@ def find_smallest_sequentially_covering_subset_wrapper(executor, paragraph, while kw_idx < len(keywords): if para_idx >= len(paragraph): raise TestFailure('Not all keywords are in the generated subarray') - if para_idx >= len(paragraph): - raise TestFailure('Subarray end index exceeds array size') if paragraph[para_idx] == keywords[kw_idx]: kw_idx += 1 para_idx += 1 diff --git a/epi_judge_python_solutions/snake_string.py b/epi_judge_python_solutions/snake_string.py index 37fa7877d..abe4b7c86 100644 --- a/epi_judge_python_solutions/snake_string.py +++ b/epi_judge_python_solutions/snake_string.py @@ -3,16 +3,11 @@ def snake_string(s: str) -> str: - result = [] - # Outputs the first row, i.e., s[1], s[5], s[9], ... - for i in range(1, len(s), 4): - result.append(s[i]) + result = [s[i] for i in range(1, len(s), 4)] # Outputs the second row, i.e., s[0], s[2], s[4], ... - for i in range(0, len(s), 2): - result.append(s[i]) + result.extend(s[i] for i in range(0, len(s), 2)) # Outputs the third row, i.e., s[3], s[7], s[11], ... - for i in range(3, len(s), 4): - result.append(s[i]) + result.extend(s[i] for i in range(3, len(s), 4)) return ''.join(result) diff --git a/epi_judge_python_solutions/stack_with_max.py b/epi_judge_python_solutions/stack_with_max.py index 304d63529..5891a6411 100644 --- a/epi_judge_python_solutions/stack_with_max.py +++ b/epi_judge_python_solutions/stack_with_max.py @@ -44,20 +44,17 @@ def stack_tester(ops): elif op == 'pop': result = s.pop() if result != arg: - raise TestFailure('Pop: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Pop: expected {str(arg)}, got ' + str(result))) elif op == 'max': result = s.max() if result != arg: - raise TestFailure('Max: expected ' + str(arg) + ', got ' + - str(result)) + raise TestFailure((f'Max: expected {str(arg)}, got ' + str(result))) elif op == 'empty': result = int(s.empty()) if result != arg: - raise TestFailure('Empty: expected ' + str(arg) + - ', got ' + str(result)) + raise TestFailure((f'Empty: expected {str(arg)}' + ', got ') + str(result)) else: - raise RuntimeError('Unsupported stack operation: ' + op) + raise RuntimeError(f'Unsupported stack operation: {op}') except IndexError: raise TestFailure('Unexpected IndexError exception') diff --git a/epi_judge_python_solutions/string_transformability.py b/epi_judge_python_solutions/string_transformability.py index 5ee1f47ba..408f45027 100644 --- a/epi_judge_python_solutions/string_transformability.py +++ b/epi_judge_python_solutions/string_transformability.py @@ -34,11 +34,15 @@ def transform_string_pythonic(D, s, t): if s == t: return 0 length = 1 - running = set([s]) + running = {s} while running: - running = D & set(cand[:i] + c + cand[i + 1:] for cand in running - for i in range(len(cand)) - for c in string.ascii_lowercase) + running = D & { + cand[:i] + c + cand[i + 1 :] + for cand in running + for i in range(len(cand)) + for c in string.ascii_lowercase + } + if t in running: return length length += 1 diff --git a/epi_judge_python_solutions/substring_match.py b/epi_judge_python_solutions/substring_match.py index c43e016d5..45c0cf3c6 100644 --- a/epi_judge_python_solutions/substring_match.py +++ b/epi_judge_python_solutions/substring_match.py @@ -25,9 +25,7 @@ def rabin_karp(t: str, s: str) -> int: t_hash = t_hash * base + ord(t[i]) # Tries to match s and t[-len(s):]. - if t_hash == s_hash and t[-len(s):] == s: - return len(t) - len(s) - return -1 # s is not a substring of t. + return len(t) - len(s) if t_hash == s_hash and t[-len(s):] == s else -1 if __name__ == '__main__': diff --git a/epi_judge_python_solutions/sudoku_solve.py b/epi_judge_python_solutions/sudoku_solve.py index 6f0ae0c2e..74f724d85 100644 --- a/epi_judge_python_solutions/sudoku_solve.py +++ b/epi_judge_python_solutions/sudoku_solve.py @@ -35,10 +35,12 @@ def valid_to_add(i, j, val): region_size = int(math.sqrt(len(partial_assignment))) I = i // region_size J = j // region_size - return not any( - val == partial_assignment[region_size * I + - a][region_size * J + b] - for a, b in itertools.product(range(region_size), repeat=2)) + return all( + val + != partial_assignment[region_size * I + a][region_size * J + b] + for a, b in itertools.product(range(region_size), repeat=2) + ) + for val in range(1, len(partial_assignment) + 1): # It's substantially quicker to check if entry val with any of the @@ -92,7 +94,7 @@ def solve_sudoku_wrapper(executor, partial_assignment): if len(br) != len(sr): raise TestFailure('Initial cell assignment has been changed') for (bcell, scell) in zip(br, sr): - if bcell != 0 and bcell != scell: + if bcell not in [0, scell]: raise TestFailure('Initial cell assignment has been changed') block_size = int(math.sqrt(len(solved))) diff --git a/epi_judge_python_solutions/test_framework/binary_tree_utils.py b/epi_judge_python_solutions/test_framework/binary_tree_utils.py index 265b3752c..6d27314e7 100644 --- a/epi_judge_python_solutions/test_framework/binary_tree_utils.py +++ b/epi_judge_python_solutions/test_framework/binary_tree_utils.py @@ -107,7 +107,7 @@ def find_node(tree, val): def must_find_node(tree, val): result = find_node(tree, val) if result is None: - raise RuntimeError('{} was not found in the tree'.format(val)) + raise RuntimeError(f'{val} was not found in the tree') return result @@ -150,13 +150,12 @@ def assert_equal_binary_trees(expected, result): def binary_tree_to_string(tree): - result = '' nodes = collections.deque() visited = set() first = True null_nodes_pending = 0 - result += '[' + result = '' + '[' nodes.append(tree) while nodes: @@ -173,7 +172,7 @@ def binary_tree_to_string(tree): result += 'null, ' null_nodes_pending -= 1 - result += '"{}"'.format(node.data) + result += f'"{node.data}"' visited.add(id(node)) nodes.append(node.left) diff --git a/epi_judge_python_solutions/test_framework/console_color.py b/epi_judge_python_solutions/test_framework/console_color.py index e2d7e662e..26ef74aa1 100644 --- a/epi_judge_python_solutions/test_framework/console_color.py +++ b/epi_judge_python_solutions/test_framework/console_color.py @@ -54,6 +54,7 @@ def print_std_out_colored(color, value): sys.stdout.flush() platform.set_console_text_attribute(old_text_attr) else: - print('{}{}{}'.format(get_color_code_unix(color), value, - get_color_code_unix(ConsoleColor.FG_DEFAULT)), - end='') + print( + f'{get_color_code_unix(color)}{value}{get_color_code_unix(ConsoleColor.FG_DEFAULT)}', + end='', + ) diff --git a/epi_judge_python_solutions/test_framework/generic_test.py b/epi_judge_python_solutions/test_framework/generic_test.py index b7b9ffb4b..bf0eedbd1 100644 --- a/epi_judge_python_solutions/test_framework/generic_test.py +++ b/epi_judge_python_solutions/test_framework/generic_test.py @@ -52,8 +52,7 @@ def generic_test_main(test_file, test_handler = GenericTestHandler(test_func, comparator) return run_tests(test_handler, config, res_printer) except RuntimeError as e: - print('\nCritical error({}): {}'.format(e.__class__.__name__, e), - file=sys.stderr) + print(f'\nCritical error({e.__class__.__name__}): {e}', file=sys.stderr) return TestResult.RUNTIME_ERROR @@ -141,7 +140,7 @@ def update_test_passed(test_file, tests_passed): problem_mapping_file.read().replace(js_begin_pattern, '').replace( js_end_pattern, '')) - test_file = 'Python: ' + test_file + test_file = f'Python: {test_file}' for chapter in chapter_to_problem_to_language_solution_mapping.values(): for _, language_solution_mapping in chapter.items(): if test_file in language_solution_mapping: diff --git a/epi_judge_python_solutions/test_framework/generic_test_handler.py b/epi_judge_python_solutions/test_framework/generic_test_handler.py index c3c0ff61f..251eee44c 100644 --- a/epi_judge_python_solutions/test_framework/generic_test_handler.py +++ b/epi_judge_python_solutions/test_framework/generic_test_handler.py @@ -78,8 +78,9 @@ def run_test(self, timeout_seconds, metrics_override, test_args): self._param_traits) + (0 if self.expected_is_void() else 1) if len(test_args) != expected_param_count: raise RuntimeError( - 'Invalid argument count: expected {}, actual {}'.format( - expected_param_count, len(test_args))) + f'Invalid argument count: expected {expected_param_count}, actual {len(test_args)}' + ) + parsed = [ param_trait.parse(json.loads(test_arg)) diff --git a/epi_judge_python_solutions/test_framework/random_sequence_checker.py b/epi_judge_python_solutions/test_framework/random_sequence_checker.py index 85d546b20..c66bcda91 100644 --- a/epi_judge_python_solutions/test_framework/random_sequence_checker.py +++ b/epi_judge_python_solutions/test_framework/random_sequence_checker.py @@ -15,11 +15,14 @@ def compute_deviation_multiplier(allowed_false_negative, num_rvs=1): 1 - 0.999999999997440 ] - for i, bound in enumerate(ERROR_BOUNDS): - if bound <= individual_rv_error: - return i + 1 - - return len(ERROR_BOUNDS) + 1 + return next( + ( + i + 1 + for i, bound in enumerate(ERROR_BOUNDS) + if bound <= individual_rv_error + ), + len(ERROR_BOUNDS) + 1, + ) def check_frequencies(seq, n, false_negative_tolerance): @@ -41,13 +44,12 @@ def check_frequencies(seq, n, false_negative_tolerance): def check_pairs_frequencies(seq, n, false_negative_tolerance): - seq_pairs = [(x, next_x) for x, next_x in zip(seq, seq[1:])] + seq_pairs = list(zip(seq, seq[1:])) return check_frequencies(seq_pairs, n * n, false_negative_tolerance) def check_triples_frequencies(seq, n, false_negative_tolerance): - seq_triples = [(x, next_x, next_next_x) - for x, next_x, next_next_x in zip(seq, seq[1:], seq[2:])] + seq_triples = list(zip(seq, seq[1:], seq[2:])) return check_frequencies(seq_triples, n * n * n, false_negative_tolerance) @@ -106,12 +108,16 @@ def run_func_with_retries(func): if __name__ == '__main__': assert check_sequence_is_uniformly_random( - [random.randint(1, 10) for i in range(1000000)], + [random.randint(1, 10) for _ in range(1000000)], 10, - false_negative_tolerance=0.01) + false_negative_tolerance=0.01, + ) + assert not check_sequence_is_uniformly_random( - [random.randint(1, 11) for i in range(1000000)], + [random.randint(1, 11) for _ in range(1000000)], 10, - false_negative_tolerance=0.01) + false_negative_tolerance=0.01, + ) + assert not check_sequence_is_uniformly_random( [i % 10 for i in range(1000000)], 10, false_negative_tolerance=0.01) diff --git a/epi_judge_python_solutions/test_framework/serialization_traits.py b/epi_judge_python_solutions/test_framework/serialization_traits.py index efb1cc2f9..f12f18d8e 100644 --- a/epi_judge_python_solutions/test_framework/serialization_traits.py +++ b/epi_judge_python_solutions/test_framework/serialization_traits.py @@ -48,7 +48,7 @@ def parse(self, json_object): return str(json_object) def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): return [len(x)] @@ -102,13 +102,13 @@ def __init__(self, inner_type_trait): self._inner_type_trait = inner_type_trait def name(self): - return 'array({})'.format(self._inner_type_trait.name()) + return f'array({self._inner_type_trait.name()})' def parse(self, json_object): return [self._inner_type_trait.parse(inner) for inner in json_object] def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): if isinstance(x, list): @@ -126,7 +126,7 @@ def __init__(self, node_type, inner_type_trait): self._inner_type_trait = inner_type_trait def name(self): - return 'binary_tree({})'.format(self._inner_type_trait.name()) + return f'binary_tree({self._inner_type_trait.name()})' def parse(self, json_object): def build_binary_tree(data): @@ -157,7 +157,7 @@ def build_binary_tree(data): return build_binary_tree(json_object) def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name), 'height({})'.format(arg_name)] + return [f'size({arg_name})', f'height({arg_name})'] def get_metrics(self, x): return [binary_tree_size(x), binary_tree_height(x)] @@ -169,8 +169,7 @@ def __init__(self, inner_type_trait): self._list_trait = ListTrait(inner_type_trait) def name(self): - return 'linked_list({})'.format( - self._list_trait.get_inner_trait().name()) + return f'linked_list({self._list_trait.get_inner_trait().name()})' def parse(self, json_object): parsed = self._list_trait.parse(json_object) @@ -180,7 +179,7 @@ def parse(self, json_object): return head def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): if x is None: @@ -196,13 +195,13 @@ def __init__(self, inner_type_trait): self._list_trait = ListTrait(inner_type_trait) def name(self): - return 'set({})'.format(self._list_trait.get_inner_trait().name()) + return f'set({self._list_trait.get_inner_trait().name()})' def parse(self, json_object): return set(self._list_trait.parse(json_object)) def get_metric_names(self, arg_name): - return ['size({})'.format(arg_name)] + return [f'size({arg_name})'] def get_metrics(self, x): if isinstance(x, set): @@ -227,8 +226,9 @@ def name(self): def parse(self, json_object): if len(json_object) != len(self._inner_type_traits): raise RuntimeError( - 'Tuple parser: expected {} values, provide {}'.format( - len(self._inner_type_traits), len(json_object))) + f'Tuple parser: expected {len(self._inner_type_traits)} values, provide {len(json_object)}' + ) + return tuple( inner_type_trait.parse(p) for inner_type_trait, p in zip( self._inner_type_traits, json_object)) @@ -258,26 +258,26 @@ def get_trait(typename): list_regex = re.compile(r'^array\((.*)\)$') m = list_regex.match(typename) if m and len(m.groups()) == 1: - return ListTrait(get_trait(m.group(1))) + return ListTrait(get_trait(m[1])) binary_tree_regex = re.compile(r'^binary_tree\((.*)\)$') m = binary_tree_regex.match(typename) if m and len(m.groups()) == 1: - return BinaryTreeTrait(BinaryTreeNode, get_trait(m.group(1))) + return BinaryTreeTrait(BinaryTreeNode, get_trait(m[1])) linked_list_regex = re.compile(r'^linked_list\((.*)\)$') m = linked_list_regex.match(typename) if m and len(m.groups()) == 1: - return LinkedListTrait(get_trait(m.group(1))) + return LinkedListTrait(get_trait(m[1])) set_regex = re.compile(r'^set\((.*)\)$') m = set_regex.match(typename) if m and len(m.groups()) == 1: - return SetTrait(get_trait(m.group(1))) + return SetTrait(get_trait(m[1])) tuple_regex = re.compile(r'^tuple\((.*)\)$') m = tuple_regex.match(typename) if m and len(m.groups()) == 1: - return TupleTrait([get_trait(x) for x in m.group(1).split(',')]) + return TupleTrait([get_trait(x) for x in m[1].split(',')]) - raise NotImplementedError("Unsupported type " + typename) + raise NotImplementedError(f"Unsupported type {typename}") diff --git a/epi_judge_python_solutions/test_framework/test_config.py b/epi_judge_python_solutions/test_framework/test_config.py index e839089ca..6160fe0a4 100644 --- a/epi_judge_python_solutions/test_framework/test_config.py +++ b/epi_judge_python_solutions/test_framework/test_config.py @@ -125,8 +125,9 @@ def from_command_line(test_file, test_data_file, timeout_seconds, if config.test_data_dir: if not os.path.isdir(config.test_data_dir): raise RuntimeError( - 'CL: --test-data-dir argument ({}) is not a directory'. - format(config.test_data_dir)) + f'CL: --test-data-dir argument ({config.test_data_dir}) is not a directory' + ) + else: config.test_data_dir = get_default_test_data_dir_path() diff --git a/epi_judge_python_solutions/test_framework/test_timer.py b/epi_judge_python_solutions/test_framework/test_timer.py index 2d2ac956e..d75d71c41 100644 --- a/epi_judge_python_solutions/test_framework/test_timer.py +++ b/epi_judge_python_solutions/test_framework/test_timer.py @@ -29,10 +29,10 @@ def duration_to_string(dur): if dur == 0: return ' <1 us' elif dur < milli_to_micro: - return str(duration_format + ' us').format(dur) + return str(f'{duration_format} us').format(dur) elif dur < second_to_micro: - return str(duration_format + ' ms').format(dur // milli_to_micro) - return str(duration_format + ' s').format(dur // second_to_micro) + return str(f'{duration_format} ms').format(dur // milli_to_micro) + return str(f'{duration_format} s').format(dur // second_to_micro) def avg_and_median_from_durations(durations): diff --git a/epi_judge_python_solutions/test_framework/test_utils.py b/epi_judge_python_solutions/test_framework/test_utils.py index 7c99ed406..7c1239d45 100644 --- a/epi_judge_python_solutions/test_framework/test_utils.py +++ b/epi_judge_python_solutions/test_framework/test_utils.py @@ -79,10 +79,7 @@ def completely_sorted(x): then the argument is lexicographically sorted on all levels, starting from the bottom. """ - if isinstance(x, list): - return sorted(completely_sorted(e) for e in x) - else: - return x + return sorted(completely_sorted(e) for e in x) if isinstance(x, list) else x def unordered_compare(a, b): diff --git a/epi_judge_python_solutions/test_framework/test_utils_console.py b/epi_judge_python_solutions/test_framework/test_utils_console.py index 303870476..c8d4710bc 100644 --- a/epi_judge_python_solutions/test_framework/test_utils_console.py +++ b/epi_judge_python_solutions/test_framework/test_utils_console.py @@ -50,14 +50,12 @@ def print_test_info(test_result, test_nr, total_tests, diagnostic, timer): flush=True) if timer is not None: - print(' [{}]'.format(duration_to_string(timer.get_microseconds())), - end='', - flush=True) + print(f' [{duration_to_string(timer.get_microseconds())}]', end='', flush=True) print_test_info.caret_at_line_start = False if test_result != TestResult.PASSED: - print(' {}'.format(diagnostic), flush=True) + print(f' {diagnostic}', flush=True) print_test_info.caret_at_line_start = True @@ -75,15 +73,12 @@ def print_failed_test(param_names, arguments, test_failure, res_printer): print_std_out_colored(ConsoleColor.FG_YELLOW, 'Arguments') print() - for (name, value) in zip(param_names, arguments): + for name, value in zip(param_names, arguments): print('\t', end='') print_std_out_colored(ConsoleColor.FG_YELLOW, name) - print(': {}{}'.format(gen_spaces(max_col_size - len(name)), - escape_newline(str(value)))) + print(f': {gen_spaces(max_col_size - len(name))}{escape_newline(str(value))}') - properties = test_failure.get_properties() - - if properties: + if properties := test_failure.get_properties(): print_std_out_colored(ConsoleColor.FG_YELLOW, '\nFailure info\n') for prop in properties: @@ -93,8 +88,7 @@ def print_failed_test(param_names, arguments, test_failure, res_printer): value = prop.value() print('\t', end='') print_std_out_colored(ConsoleColor.FG_YELLOW, prop.name()) - print(': {}{}'.format(gen_spaces(max_col_size - len(prop.name())), - value)) + print(f': {gen_spaces(max_col_size - len(prop.name()))}{value}') def show_complexity_notification(): @@ -105,16 +99,15 @@ def show_complexity_notification(): def print_post_run_stats(tests_passed, total_tests, complexity, durations): if durations: if complexity: - print('Time complexity: {}'.format(complexity)) + print(f'Time complexity: {complexity}') avg_median = avg_and_median_from_durations(durations) - print('Average running time: {}\n' - 'Median running time: {}\n'.format( - duration_to_string(avg_median[0]), - duration_to_string(avg_median[1])), - end='') + print( + f'Average running time: {duration_to_string(avg_median[0])}\nMedian running time: {duration_to_string(avg_median[1])}\n', + end='', + ) + if tests_passed < total_tests: - print('*** You\'ve passed {}/{} tests. ***'.format( - tests_passed, total_tests)) + print(f"*** You\'ve passed {tests_passed}/{total_tests} tests. ***") else: print('*** You\'ve passed ALL tests. Congratulations! ***') diff --git a/epi_judge_python_solutions/test_framework/timed_executor.py b/epi_judge_python_solutions/test_framework/timed_executor.py index a1fa4a945..0b9cd44b7 100644 --- a/epi_judge_python_solutions/test_framework/timed_executor.py +++ b/epi_judge_python_solutions/test_framework/timed_executor.py @@ -22,14 +22,13 @@ def run(self, func): if self._timeout_seconds == 0: # Timeout is disabled. return self._timed_call(func) - else: - try: - with futures.ThreadPoolExecutor() as executor: - return next( - executor.map(self._timed_call, (func, ), - timeout=self._timeout_seconds)) - except futures.TimeoutError: - raise TimeoutException(self._timeout_seconds) + try: + with futures.ThreadPoolExecutor() as executor: + return next( + executor.map(self._timed_call, (func, ), + timeout=self._timeout_seconds)) + except futures.TimeoutError: + raise TimeoutException(self._timeout_seconds) def get_timer(self): return self._timer diff --git a/epi_judge_python_solutions/tree_connect_leaves.py b/epi_judge_python_solutions/tree_connect_leaves.py index 67b881c3c..abb19fe5a 100644 --- a/epi_judge_python_solutions/tree_connect_leaves.py +++ b/epi_judge_python_solutions/tree_connect_leaves.py @@ -11,10 +11,11 @@ def create_list_of_leaves(tree: BinaryTreeNode) -> List[BinaryTreeNode]: if not tree: return [] - if not tree.left and not tree.right: + if tree.left or tree.right: + # First do the left subtree, and then do the right subtree. + return create_list_of_leaves(tree.left) + create_list_of_leaves(tree.right) + else: return [tree] - # First do the left subtree, and then do the right subtree. - return create_list_of_leaves(tree.left) + create_list_of_leaves(tree.right) @enable_executor_hook diff --git a/epi_judge_python_solutions/tree_with_parent_inorder.py b/epi_judge_python_solutions/tree_with_parent_inorder.py index 45e37a013..39c87d3ff 100644 --- a/epi_judge_python_solutions/tree_with_parent_inorder.py +++ b/epi_judge_python_solutions/tree_with_parent_inorder.py @@ -8,20 +8,12 @@ def inorder_traversal(tree: BinaryTreeNode) -> List[int]: prev, result = None, [] while tree: - if prev is tree.parent: - # We came down to tree from prev. - if tree.left: # Keep going left. - next = tree.left - else: - result.append(tree.data) - # Done with left, so go right if right is not empty. Otherwise, - # go up. - next = tree.right or tree.parent - elif tree.left is prev: - # We came up to tree from its left child. + if prev is tree.parent and tree.left: # Keep going left. + next = tree.left + elif prev is tree.parent or tree.left is prev: result.append(tree.data) - # Done with left, so go right if right is not empty. Otherwise, go - # up. + # Done with left, so go right if right is not empty. Otherwise, + # go up. next = tree.right or tree.parent else: # Done with both children, so move up. next = tree.parent