from sys import stdout from noether.cli.style import * from noether.cli.prompt import * from noether.lib.structs import Result from noether.lib.util import digits from noether.lib.groups import cyclic_subgrp from noether.lib.primes import totient, is_prime class cycsub(Prompt): DEFAULT_PROMPT = style('[n]: ', Color.BLUE) def __init__(self, ignore_zero: bool = True) -> None: super().__init__() self.ignore_zero = ignore_zero def _parse(self, command: str) -> int: try: return Result.succeed(int(command)) except ValueError: return Result.fail('Not an integer.') def _exec(self, n: int) -> None: phi = totient(n) lpadding = digits(n) rpadding = digits(phi) if is_prime(n, phi=n): Cursor.save() Cursor.move_y(-1, reset=False) Cursor.set_x(len(self.DEFAULT_PROMPT) + lpadding + 1) stdout.write(style('[PRIME]', Color.MAGENTA, Effect.BOLD)) Cursor.restore() stdout.flush() # keeps track of all primitive roots # (note that there will be exactly totient(phi) of them) proots = [] for g in range(n): G, order, periodic = cyclic_subgrp(g, n, ignore_zero=self.ignore_zero) primitive = (order == phi) # primitive root lpad = ' ' * (lpadding - digits(a)) rpad = ' ' * (rpadding - digits(order)) color_g = Color.RED style_G = [] style_order = [] if primitive: color_g = Color.GREEN style_G = [Color.GREEN, Effect.BOLD] style_order = [Color.YELLOW, Effect.BOLD] proots.append(g) elif gcd(g, n) == 1: color_g = Color.Yellow line = style(f'{lpad}{g}', color_g, Effect.BOLD) + \ '-> ' + \ style(f'{order}{rpad} ', *style_order) + \ '| ' + \ style(str(G), *style_G) print(line, flush=True)