| t | class UnknownError(Exception): | t | class UnknownError(Exception): |
| pass | | pass |
| | | |
| class CycleError(Exception): | | class CycleError(Exception): |
| pass | | pass |
| | | |
| class IneffectiveError(Exception): | | class IneffectiveError(Exception): |
| pass | | pass |
| | | |
| def main(): | | def main(): |
| plans = {} | | plans = {} |
| participants = [] | | participants = [] |
| while True: | | while True: |
| line = input().strip() | | line = input().strip() |
| if line == '': | | if line == '': |
| break | | break |
| parts = line.split(':', 1) | | parts = line.split(':', 1) |
| name = parts[0].strip() | | name = parts[0].strip() |
| participants.append(name) | | participants.append(name) |
| if len(parts) == 1 or parts[1].strip() == '': | | if len(parts) == 1 or parts[1].strip() == '': |
| plans[name] = [] | | plans[name] = [] |
| else: | | else: |
| plans[name] = [x.strip() for x in parts[1].split(',')] | | plans[name] = [x.strip() for x in parts[1].split(',')] |
| all_names = set(plans.keys()) | | all_names = set(plans.keys()) |
| for name, base_list in plans.items(): | | for name, base_list in plans.items(): |
| for base in base_list: | | for base in base_list: |
| if base not in all_names: | | if base not in all_names: |
| print('UNKNOWN') | | print('UNKNOWN') |
| return | | return |
| mros = {} | | mros = {} |
| in_progress = set() | | in_progress = set() |
| | | |
| def merge(sequences): | | def merge(sequences): |
| sequences = [seq[:] for seq in sequences if seq] | | sequences = [seq[:] for seq in sequences if seq] |
| result = [] | | result = [] |
| while any(sequences): | | while any(sequences): |
| found = None | | found = None |
| for seq in sequences: | | for seq in sequences: |
| if not seq: | | if not seq: |
| continue | | continue |
| candidate = seq[0] | | candidate = seq[0] |
| for other in sequences: | | for other in sequences: |
| if candidate in other[1:]: | | if candidate in other[1:]: |
| candidate = None | | candidate = None |
| break | | break |
| if candidate is not None: | | if candidate is not None: |
| found = candidate | | found = candidate |
| break | | break |
| if found is None: | | if found is None: |
| return None | | return None |
| result.append(found) | | result.append(found) |
| for seq in sequences: | | for seq in sequences: |
| if seq and seq[0] == found: | | if seq and seq[0] == found: |
| del seq[0] | | del seq[0] |
| return result | | return result |
| | | |
| def compute_mro(name): | | def compute_mro(name): |
| if name in mros: | | if name in mros: |
| return mros[name] | | return mros[name] |
| if name not in plans: | | if name not in plans: |
| raise UnknownError() | | raise UnknownError() |
| if name in in_progress: | | if name in in_progress: |
| raise CycleError() | | raise CycleError() |
| in_progress.add(name) | | in_progress.add(name) |
| bases = plans[name] | | bases = plans[name] |
| mros_bases = [] | | mros_bases = [] |
| for base in bases: | | for base in bases: |
| mro_base = compute_mro(base) | | mro_base = compute_mro(base) |
| mros_bases.append(mro_base) | | mros_bases.append(mro_base) |
| sequences = mros_bases + [bases] | | sequences = mros_bases + [bases] |
| merged = merge(sequences) | | merged = merge(sequences) |
| if merged is None: | | if merged is None: |
| raise IneffectiveError() | | raise IneffectiveError() |
| mro = [name] + merged | | mro = [name] + merged |
| mros[name] = mro | | mros[name] = mro |
| in_progress.remove(name) | | in_progress.remove(name) |
| return mro | | return mro |
| try: | | try: |
| for name in participants: | | for name in participants: |
| compute_mro(name) | | compute_mro(name) |
| except UnknownError: | | except UnknownError: |
| print('UNKNOWN') | | print('UNKNOWN') |
| return | | return |
| except CycleError: | | except CycleError: |
| print('CYCLE') | | print('CYCLE') |
| return | | return |
| except IneffectiveError: | | except IneffectiveError: |
| print('INEFFECTIVE') | | print('INEFFECTIVE') |
| return | | return |
| for name in participants: | | for name in participants: |
| mro = mros[name][1:] | | mro = mros[name][1:] |
| print(f"{name}: {', '.join(mro)}") | | print(f"{name}: {', '.join(mro)}") |
| if __name__ == '__main__': | | if __name__ == '__main__': |
| main() | | main() |