61 lines
2 KiB
Python
61 lines
2 KiB
Python
|
|
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)
|