SHARE
TWEET

recprimefac.py

a guest Feb 23rd, 2017 82 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python3
  2. import sys, itertools
  3. import urllib.parse
  4. from collections import defaultdict, Counter
  5.  
  6. try:
  7.     import primesieve
  8. except ImportError as e:
  9.     sys.exit("primesieve is required. See https://pypi.python.org/pypi/primesieve")
  10.  
  11. class RecursiveFactor:
  12.     Top = itertools.repeat(0)
  13.     def __init__(self, n):
  14.         if isinstance(n, RecursiveFactor):
  15.             if n.factors == RecursiveFactor.Top:
  16.                 self.factors = RecursiveFactor.Top
  17.             else:
  18.                 self.factors = [RecursiveFactor(factor) for factor in n.factors]
  19.         elif isinstance(n, int):
  20.             if n == 0:
  21.                 self.factors = RecursiveFactor.Top
  22.             else:
  23.                 factors = []
  24.                 i = 2
  25.                 print("factoring {0}".format(n))
  26.                 while i * i <= n:
  27.                     while n % i == 0:
  28.                         n = n // i
  29.                         factors.append(i)
  30.                     i = i + 1
  31.                 if n != 1: factors.append(n)
  32.                 self.factors = [RecursiveFactor(primesieve.count_primes(factor)) for factor in factors]
  33.         else:
  34.             self.factors = [RecursiveFactor(factor) for factor in n]
  35.         if self.factors != RecursiveFactor.Top:
  36.             self.factors.sort()
  37.  
  38.     def reduce(self, binary, unary, one, zero = None, horiz_combo = False, vert_combo = False):
  39.         ''' binary expected to take sum and nextFactor
  40.            unary expected to take factor (or (nextFactor, times) if horiz_combo)
  41.                                or factor and depth if vert_combo)
  42.            if binary = RF(a*b), you can expect sum < nextFactor
  43.                 using ordinal (epsilon naught) ordering:
  44.                                  (1,2,4,8,...,3,6,12...,9,...,27,...
  45.                                   7,14,28,...,21,42,...,63,...
  46.                                   19, ...
  47.                                   ...
  48.                                   5, ... 13, ... 37, ..., ..., 23, ...
  49.                                   17, ..., 67, ...
  50.                                   11, ......., 0)
  51.            DOES NOT RECURSE - ADD RECURSION IN UNARY
  52.        '''
  53.         if self.factors == RecursiveFactor.Top:
  54.             if zero is None:
  55.                 uninput = (0,...) if horiz_combo else 0
  56.                 return unary(uninput,...) if vert_combo else unary(uninput)
  57.             else: return zero
  58.         it = iter(sorted(Counter(self.factors).items() if horiz_combo else self.factors))
  59.         out = one
  60.         for factor in it:
  61.             if vert_combo:
  62.                 depth = 0
  63.                 while(factor.is_prime()):
  64.                     depth += 1
  65.                     factor = factor.factors[0]
  66.                 out = binary(out, unary(factor, depth))
  67.             else: out = binary(out, unary(factor))
  68.         return out
  69.            
  70.     def stringify(self, left = '<', right = '>', middle = '', one = '', depth = None, zero = 'T'):
  71.         ''' this.stringify([left],[right],[middle], [one], [depth])
  72.            blearugh '''
  73.         if depth is None:
  74.             return self.reduce(lambda a, b: a+middle+b if a!=one else b,
  75.                                lambda a: left
  76.                                + a.stringify(left, right, middle, one = one, depth = depth, zero = zero)
  77.                                + right,
  78.                                one,
  79.                                zero = zero)
  80.         else:
  81.             return self.reduce(lambda a, b: a+middle+b if a!= one else b,
  82.                                lambda a, de:
  83.                                    depth(de) if int(a)==1 else
  84.                                    left(de)
  85.                                    + a.stringify(left, right, middle, one = one, depth = depth, zero = zero)
  86.                                    + right(de),
  87.                                one,
  88.                                zero = zero,
  89.                                vert_combo = True)
  90.  
  91.     def factor_list(self):
  92.         if self.factors == RecursiveFactor.Top:
  93.             return [(RecursiveFactor(0), ...)]
  94.         print(str(self.factors))
  95.         print(sorted(Counter(self.factors).items()))
  96.         return [(RecursiveFactor(1),...)] + sorted(Counter(self.factors).items())
  97.  
  98.     def __eq__(self,other):
  99.         return self.factors == RecursiveFactor(other).factors
  100.    
  101.     def __hash__(self):
  102.         return hash(self.stringify())
  103.    
  104.     def __ne__(self,other):
  105.         other = RecursiveFactor(other)
  106.         return self.factors != other.factors
  107.    
  108.     def __lt__(self,other):
  109.         other = RecursiveFactor(other)
  110.         if self.factors == RecursiveFactor.Top:
  111.             return False
  112.         if other.factors == RecursiveFactor.Top:
  113.             return True
  114.         if other.factors == []:
  115.             return False
  116.         if self.factors == []:
  117.             return True
  118.         max = min(len(self.factors), len(other.factors))
  119.         for i in range(max):
  120.             if self.factors[-i] != other.factors[-i]:
  121.                 return self.factors[-i]<other.factors[-i]
  122.         return False
  123.    
  124.     def __ge__(self,other):
  125.         other = RecursiveFactor(other)
  126.         return not self < other
  127.    
  128.     def __repr__(self):
  129.         return 'RecursiveFactor: [' + self.stringify(left = '[', right = ']', middle = ', ') + ']'
  130.    
  131.     def is_symmetrical(self):
  132.         if self.factors == RecursiveFactor.Top:
  133.             return self
  134.         elif len(self.factors)==1:
  135.             return self.factors[0].is_symmetrical()
  136.         else:
  137.             found_odd = False
  138.             for factor, times in Counter(self.factors).items():
  139.                 if times % 2 == 1:
  140.                     if found_odd:
  141.                         return False
  142.                     if not factor.is_symmetrical():
  143.                         return False
  144.                     found_odd = True
  145.             return True
  146.  
  147.     def is_prime(self):
  148.         if self.factors == RecursiveFactor.Top:
  149.             return False
  150.         else:
  151.             return len(self.factors)==1
  152.    
  153.     def __int__(self):
  154.         if self.factors == RecursiveFactor.Top: return 0
  155.         return self.reduce(lambda x,y: x * y, lambda x: primesieve.nth_prime(x), 1)
  156.  
  157. def get_ordinal(n, latex=True):
  158.     n = RecursiveFactor(n)
  159.     def unary(factory):
  160.         factor = factory[0]
  161.         if int(factor) == 1:
  162.             return str(factory[1])
  163.         times = factory[1]
  164.         if times == 1: times = ''
  165.         omega = r'\omega' if latex else 'ω'
  166.         if int(factor) == 2:
  167.             return omega + str(times)
  168.         else:
  169.             ordinal = get_ordinal(factor, latex=latex)
  170.             if latex:
  171.                 return omega + '^{' + ordinal + '}' + str(times)
  172.             else:
  173.                 if '+' in ordinal or times != '':
  174.                     return omega + '^(' + ordinal + ')' + str(times)
  175.                 else:
  176.                     return omega + '^' + ordinal
  177.     return n.reduce(lambda x,y:
  178.                     y if x == '0' else y + '+' + x, unary, '0', zero = r'\epsilon_0' if latex else 'ε₀', horiz_combo = True)
  179.  
  180. def full_ordinal(n):
  181.     return r'\mathfrak{p}(' + get_ordinal(n) + ')'
  182.  
  183. def get_info(n):
  184.     info = {}
  185.     n = RecursiveFactor(n)
  186.     brackets = n.stringify()
  187.     info["bracket_notation"] = brackets
  188.     abc = brackets.replace('<>', 'a')
  189.     letter = 'a'
  190.     while letter in abc:
  191.         abc = abc.replace('<'+letter+'>', chr(ord(letter)+1))
  192.         letter = chr(ord(letter)+1)
  193.     info["abc_notation"] = abc
  194.     info["p_notation"] = n.stringify(lambda x: 'pdfghijklmnopqtuvwxyz'[x] + '<',
  195.                                      lambda x: '>',
  196.                                      one = 's',
  197.                                      depth= lambda x: 'pdfghijklmnopqtuvwxyz'[x])
  198.  
  199.     digits_list = []
  200.     last_bracket = ''
  201.     for char in brackets:
  202.         if char == last_bracket:
  203.             digits_list[-1] += 1
  204.         else:
  205.             digits_list.append(1)
  206.         last_bracket = char
  207.     digits = ''.join(map(str,digits_list))
  208.     info["digit_notation"] = digits
  209.  
  210.     depth = []
  211.     current_depth = 0
  212.     max_depth = 0
  213.     add = True
  214.     for digit in digits_list[:-1]:
  215.         if add:
  216.             current_depth += digit
  217.         else:
  218.             current_depth -= digit
  219.         depth.append('*' * current_depth)
  220.         add = not add
  221.         if current_depth > max_depth:
  222.             max_depth = current_depth
  223.     info["depth_notation"] = '\n'.join(''.join(row) for row in itertools.zip_longest(*depth, fillvalue=' '))
  224.     ordinal_escaped = urllib.parse.quote(full_ordinal(n))
  225.     info["ordinal"] = '[img]http://latex.codecogs.com/gif.latex?' + ordinal_escaped + '[/img]'
  226.  
  227.     info["is_prime"] = len(n.factor_list()) == 2 and n.factor_list()[1] == 1
  228.     info["is_prime_power"] = len(n.factor_list()) <= 2
  229.     info["is_symmetrical"] = n.is_symmetrical()
  230.     info["is_alphabetical"] = not ('<' in abc)
  231.  
  232.     factors = n.factor_list()
  233.     factors = [int(factor) for factor in factors]
  234.     factors.sort()
  235.  
  236.     info["length"] = len(brackets)
  237.     info["reversals"]= len(digits_list) - 1
  238.     info["max_depth"] = max_depth
  239.     info["factors"] = len(factors)-1
  240.     info["smoothness"] = int(factors[-1][0])
  241.     info["necessary_brackets"] = abc.count('<')*2
  242.     return info
  243.  
  244. def info_string(number):
  245.     info = get_info(number)
  246.     return '\n'.join([
  247.         str(int(number)),
  248.         info["bracket_notation"],
  249.         info["abc_notation"],
  250.         info["p_notation"],
  251.         info["digit_notation"],
  252.         '[code]',
  253.         info["depth_notation"],
  254.         '[/code]',
  255.         info["ordinal"],
  256.         '',
  257.         'Prime: {0}'.format('Yes' if info["is_prime"] else 'No'),
  258.         'Prime Power: {0}'.format('Yes' if info["is_prime_power"] else 'No'),
  259.         'Symmetrical: {0}'.format('Yes' if info["is_symmetrical"] else 'No'),
  260.         'Alphabetical: {0}'.format('Yes' if info["is_alphabetical"] else 'No'),
  261.         '',
  262.         'Length: {0}'.format(info["length"]),
  263.         'Reversals: {0}'.format(info["reversals"]),
  264.         'Max Depth: {0}'.format(info["max_depth"]),
  265.         'Factors: {0}'.format(info["factors"]),
  266.         'Smoothness: {0}'.format(info["smoothness"]),
  267.         'Necessary Brackets: {0}'.format(info["necessary_brackets"])
  268.     ])
  269. if __name__ == '__main__':
  270.     n = int(sys.argv[1] if len(sys.argv) > 1 else 1)
  271.     while n != 0:
  272.         print(info_string(n))
  273.         print("-----------------------------------------")
  274.         try: n = int(input())
  275.         except:
  276.             n = 0
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top