# %% from typing import NamedTuple class Rule(NamedTuple): child: str parent: str def is_rule_satisfied(in_list: list, rule: Rule) -> bool: child_index = in_list.index(rule.child) parent_index = in_list.index(rule.parent) return parent_index < child_index def sort_by_rules(in_list: list, rules: list[Rule]) -> bool: def move_item_down(in_list: list, index: int): """moves item""" # assert index > in_list[index], in_list[index - 1] = in_list[index - 1], in_list[index] for _ in range(10000): rule_satisfied: list[bool] = [] for rule in rules: if not is_rule_satisfied(in_list, rule): rule_satisfied.append(False) parent_index = in_list.index(rule.parent) move_item_down(in_list, parent_index) else: rule_satisfied.append(True) if all(rule_satisfied): print("success") return True print("failed") return False in_list = ["a", "b", "c", "d", "e", "f", "g"] rules = [ # X depends on Y Rule("a", "e"), Rule("b", "e"), Rule("b", "f"), Rule("c", "e"), Rule("d", "e"), Rule("f", "e"), ] print("before", in_list) sort_by_rules(in_list, rules) print("before", in_list) def test_uniqueness(in_list: list): assert len(set(in_list)) == len(in_list) def test_rules(in_list, rules): rule_satisfied: list[bool] = [] for rule in rules: if is_rule_satisfied(in_list, rule): rule_satisfied.append(True) else: rule_satisfied.append(False) assert all(rule_satisfied) test_uniqueness(in_list) test_rules(in_list, rules)