pyzuki

mycalc.py

Sep 12th, 2011
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 107.88 KB | None | 0 0
  1. # This is mycalc.py for Python 32
  2.  
  3.  
  4. """
  5. often used functions:
  6. time_stamp
  7. numberRounding(n, sigdigits)
  8. round_to_n(x, n),
  9. secsToHMS(seconds),  
  10. factorsOfInteger(n), intSpell(n),
  11. randIntOfRandLength(minLength, maxLength),
  12. int_digits(n),
  13. int_commas(n)
  14. isPrime(n),
  15. findDayOfWeek(1937, 4, 24)
  16. croots(c, n),
  17. decPow(n, power, precision=4)
  18. is_dec_repeating(denominator)
  19. decDiv(num, denom, precision=100)
  20. find_repeat_seq(num, denom, precision=1000)
  21. unique()
  22. """
  23. import gmpy
  24. import gmpy2
  25. import random
  26. import datetime
  27. from math import log10
  28. from time import time, clock
  29.  
  30. def is_hashable(object):
  31.     try:
  32.         hash(object)
  33.     except TypeError:
  34.         return False
  35.     return True
  36.  
  37. def hex2dec(hex_n):
  38.     """
  39.    Given a hex integer in the 0x... form, returns the equivalent base-10 integer
  40.    
  41.    >>> hex2dec(0xf)
  42.    15
  43.    >>> hex2dec(0x10)
  44.    16
  45.    >>> hex2dec(0xA)
  46.    10
  47.    >>> hex2dec(0xff)
  48.    255
  49.    >>>
  50.    """
  51.     return int(hex_n)
  52.  
  53. def dec2hex(dec_n):
  54.     """
  55.    Given a base-10 int, return the equivalent hex integer as a string.
  56.    
  57.    >>> dec2hex(255)
  58.    '0xff'
  59.    >>> dec2hex(256)
  60.    '0x100'
  61.    >>>
  62.    """
  63.     return hex(dec_n)
  64.  
  65. def convertPath(path):
  66.     r"""
  67.    Given a path with backslashes, return that path with forward slashes.
  68.  
  69.    By Steven D'Aprano  07/31/2011 on Tutor list
  70.    >>> path = r'C:\Users\Dick\Desktop\Documents\Notes\College Notes.rtf'
  71.    >>> convertPath(path)
  72.    'C:/Users/Dick/Desktop/Documents/Notes/College Notes.rtf'
  73.    """
  74.     import os.path
  75.     separator = os.path.sep
  76.     if separator != '/':
  77.         path = path.replace(os.path.sep, '/')
  78.     return path
  79.  
  80. def d(x, precision=50):
  81.     """
  82.    Given x is either an int of any length or a float with 16 or fewer digits,
  83.    return decimal.Decimal(str(x)).
  84.    
  85.    This function appears in a simpler form in the 2nd ed. of
  86.    _Python In a Nutshell_, p.373
  87.    #>>> from decimal import Decimal as D
  88.    #>>> decimal.getcontext().prec = 50
  89.    #>>> D('234')**D('.555555555555555')
  90.    #Decimal('20.712428960882622698237158800584555118350558990840')
  91.    >>> d(234)**d(.555555555555555)
  92.    Decimal('20.712428960882622698237158800584555118350558990840')
  93.    >>> d(234, 25)**d(.555555555555555)
  94.    Decimal('20.712428960882622698237158800584555118350558990840')
  95.    >>> d(234)**d(.555555555555555, 25)
  96.    Decimal('20.71242896088262269823716')
  97.    >>> d(234)**d(.55555555555555557)
  98.    float beginning 0.555 has too many digits.
  99.    Maximum to maintain accuracy is 16
  100.    (<http://www.wolframalpha.com/input/?i=234**.555555555555555>
  101.    gives 20.71242896088262269823715880058455511835055899083967...)
  102.    (for WA, us 927)  
  103.    """
  104.     import decimal
  105.     from decimal import getcontext
  106.     getcontext().prec = precision
  107.     import sys
  108.     from decimal import Decimal as D
  109.    
  110.     if isinstance(x, float):
  111.         decimal.getcontext().prec = 16
  112.         if D(str(x)) != +D(str(x)):
  113.             print('float beginning', str(x)[:5], 'has too many digits.')
  114.             print('Maximum to maintain accuracy is 16 digits')
  115.             sys.exit()
  116.         decimal.getcontext().prec = precision
  117.     elif isinstance(x, int):
  118.         decimal.getcontext().prec = precision
  119.     else:
  120.         raise TypeError("WTF you didn't pass me an int or a float")
  121.     return D(str(x))
  122.  
  123. def goldbach_pairs(n):
  124.     """
  125.    Given an even int > 3, returns the list of unique unordered Goldbach pairs, p1 and p2 such that p1 and p2 are prime, p1 + p2 = n, and p1 !> p2.
  126.    
  127.    Thus for n = 14, the list will contain either (3, 11) or (11, 3), but not both (11, 3) and (3, 11), because (3, 11) and (11, 3) are considered to be the same pair.
  128.    >>> goldbach_pairs(50)
  129.    [(3, 47), (7, 43), (13, 37), (19, 31)]
  130.    Error: n must be even and >= 6
  131.    >>> goldbach_pairs(51)
  132.    None
  133.    >>> goldbach_pairs(4)
  134.    [(2, 2)]
  135.    """
  136.     from mycalc import isPrime
  137.     if n == 4:
  138.         return [(2, 2)]
  139.     if n % 2 or n < 6:
  140.         print("Error: n must be even and >= 6")
  141.         return ''
  142.     x = 3
  143.     y = n - x
  144.     pairs_count = 0
  145.     pairs_list = []
  146.    
  147.     while x <= n // 2:
  148.         if isPrime(x) and isPrime(y):
  149.             pairs_list.append((x, y))
  150.             pairs_count += 1
  151.         x += 2
  152.         y -= 2
  153.    
  154.     return pairs_list
  155.  
  156. def no_zero(n):
  157.     """
  158.    Given a float with abcissa of 0, returns an int. Otherwise returns the float.
  159.    
  160.    >>> no_zero(234.0)
  161.    234
  162.    >>> no_zero(-56.12)
  163.    -56.12
  164.    no_zero(3546)
  165.    >>> 3456
  166.    """
  167.     if n == int(n):
  168.         return int(n)
  169.     else:
  170.         return n
  171.    
  172.  
  173. def remove_all_x(x, list_):
  174.     """
  175.    return list_ with all x removed
  176.    
  177.    >>> lst = ['asd', 'f', 'qwerty', 234, 'qwerty']
  178.    >>> remove_all_x('qwerty', lst)
  179.    ['asd', 'f', 234]
  180.    >>>
  181.    """
  182.     return [e for e in list_ if e != x]
  183.  
  184. def is_permutation(a, b):
  185.     """
  186.    Given 2 sequences of same type, or given 2 integers, return True if the 2nd is a permutation of the 1st.
  187.    
  188.  
  189.    >>> is_permutation('Moores', 'Moorse')
  190.    True
  191.    >>> is_permutation(189, 189)
  192.    True
  193.    >>> is_permutation(189, '189')
  194.    the two are of different types
  195.    >>> is_permutation(189, 1899)
  196.    the two have different lengths: 3 and 4
  197.    >>> is_permutation(['p','q',23], ['q',23,'p'])
  198.    True
  199.    >>> is_permutation(['p','q', 23], ['p', 24, 'q'])
  200.    False
  201.    >>> is_permutation(['p','q',23], ('p', 23, 'q'))
  202.    the two are of different types
  203.    >>> is_permutation(5.6, 5.6)
  204.    the two are neither ints nor sequences
  205.    >>> is_permutation('5.6', '6.5')
  206.    True
  207.    >>>
  208.    """
  209.     if type(a) != type(b):
  210.         print('the two are of different types', type(a), 'and', type(b))
  211.         return False
  212.     elif not isinstance(a, (str, list, tuple, int)):
  213.         print("the two are of the same type", type(a), "which is neither int nor sequence")
  214.         return False
  215.     else:
  216.         for element in a:
  217.             if not a.count(element) == b.count(element):
  218.                 return False
  219.     return True
  220.  
  221. def int_digits_num(n):
  222.     """
  223.    Given an integer, (positive, 0, or negative), or an expression that
  224.    evaluates to an integer, returns the number of digits in the integer.
  225.    """
  226.     from math import log10
  227.     if not isinstance(n, int):
  228.         raise TypeError("WTF you didn't pass me an int")
  229.     if n == 0:
  230.         return 1
  231.     n = abs(n)
  232.     return int(log10(n)) + 1
  233.  
  234. def harmonic_mean(Hlist):
  235.     """
  236.    return harmonic mean of positive numbers in Hlist
  237.  
  238.    ref: http://mathworld.wolfram.com/HarmonicMean.html
  239.    test: hm of 1,2,3,4,5,6,7 is 980/363 or 2.6997245179063363
  240.    """
  241.     import math
  242.     if any(x <= 0 for x in Hlist):
  243.         raise ValueError("All items in Hlist must be positive numbers.")
  244.     sum_ = math.fsum([1/x for x in Hlist])
  245.     n = len(Hlist)
  246.     invH = (1/n)*sum_
  247.     H = 1/invH
  248.     return H
  249.  
  250. def geometric_mean(Glist):
  251.     """
  252.    return geometric mean of positive numbers in Glist
  253.  
  254.    ref: http://mathworld.wolfram.com/GeometricMean.html
  255.    test: G of 1,5,10 is (1*5*10)**(1/3), or 3.6840314986403864
  256.    """
  257.     if any(x <= 0 for x in Glist):
  258.         raise ValueError("All items in Glist must be positive numbers.")
  259.     product = 1
  260.     for x in Glist:
  261.         product *= x
  262.     n = len(Glist)
  263.     G = product ** (1/n)
  264.     return G
  265.  
  266. def sound_Exit(n=1):
  267.     import winsound
  268.     for x in range(n):
  269.         winsound.PlaySound("SystemExit", winsound.SND_ALIAS)
  270.  
  271. def is_squarefree(n):
  272.     """
  273.    Return True if integer n is squarefree; False if not
  274.  
  275.    A number is said to be squarefree if its prime decomposition contains no repeated factors.
  276.    """
  277.     factors_of_n = factorsOfInteger(n)
  278.     for x in factors_of_n:
  279.         if factors_of_n.count(x) > 1:
  280.             return False
  281.     return True
  282.  
  283. def is_squareful(n):
  284.     """
  285.    Return True if integer n is squareful; False if not
  286.  
  287.    A number is said to be squareful if its prime decomposition
  288.    contains at least one repeated factor. (12 = 2*2*3)
  289.    """
  290.     factors_of_n = factorsOfInteger(n)
  291.     for x in factors_of_n:
  292.         if factors_of_n.count(x) > 1:
  293.             return True
  294.     return False
  295.  
  296. def proper_divisors(n):
  297.     """
  298.    Return a list of the proper divisors of positive integer n
  299.    """
  300.     limit = int(n/2)
  301.     return [x for x in range(1,limit+1) if n % x == 0]
  302.  
  303. def proper_divisors_sum(n):
  304.     """
  305.    Return the sum of a list of the proper divisors of positive integer n
  306.    """
  307.     sum_ = 0
  308.     limit = int(n/2)
  309.     for x in range(1, limit+1):
  310.         if n % x == 0:
  311.             sum_ += x
  312.     return sum_
  313.  
  314. def nth_substring(string, substring, n):
  315.     """
  316.    Return the index of the first character of the nth instance of substring in string.
  317.  
  318.    If no nth instance, return -1
  319.    """
  320.     max_n = string.count(substring)
  321.     if n > max_n:
  322.         return -1
  323.     idx = 0
  324.     original_string = string
  325.     len_substring = len(substring)
  326.     count = 0
  327.     idx_sum = 0
  328.     while True:
  329.         count += 1
  330.         idx = string[idx_sum:].find(substring)
  331.         idx += len_substring
  332.         idx_sum += idx
  333.         if count >= n:
  334.             idx = idx_sum-len_substring
  335.             return idx
  336.  
  337. def time_stamp():
  338.     return datetime.datetime.now().strftime("%H:%M:%S")
  339.  
  340. def sci_notation_to_non_sci_notation(sci_not):
  341.     """
  342.    Given a number in scientific notation as a string, return the number.
  343.  
  344.    E.g., 1.234e3 -> 1234; 1.234+E6 -> 1234000; 1+e2 -> 100; 1.234e2 -> 123.4
  345.    """
  346.     s = str(sci_not)
  347.     # remove '.'
  348.     s = s.replace('.', '')
  349.     #remove '+'
  350.     s = s.replace('+', '')
  351.     s = s.replace('E', 'e')
  352.     if 'e' not in s:
  353.         print(sci_not, "is not in scientific notation form")
  354.         return
  355.     idx_e = s.find('e')
  356.     s_before_e = s[:idx_e]
  357.     exponent = int(s[idx_e+1:])
  358.     len_s_before_e = len(s_before_e)
  359.     if len_s_before_e <= exponent+1:
  360.         return s_before_e + '0'*(exponent - len_s_before_e + 1)
  361.     elif len_s_before_e > exponent+1:
  362.         return s_before_e[:exponent+1] + '.' + s_before_e[exponent+1:]
  363.  
  364. def int_digits(n):
  365.     """
  366.    return number of digits of an integer
  367.    """
  368.     return int(log10(n) + 1)
  369.  
  370. def find_prime_before_n(n):
  371.     for x in range(n, 2, -1):
  372.         if isPrime(x):
  373.             return x
  374.  
  375. def prime_to_biggest_prime(p):
  376.     """
  377.    Given a prime, return a much bigger one.
  378.  
  379.    For every prime p there there is at least one pair of positive integers a and b such
  380.    that p = a + b, and such that 2**a*3**b is either 1 greater than or 1 less than another
  381.    (much larger) prime. This function returns the pair that produces the greatest value
  382.    of 2**a*3**b, and the greatest prime that p determines.
  383.    """
  384.     for b in range(p-1,0,-1):
  385.         flag = 0
  386.         a = p - b
  387.         one_off_big_p = 2**a*3**b
  388.         for x in [one_off_big_p - 1, one_off_big_p + 1]:
  389.             if isPrime(x):
  390.                 return x, a, b
  391.  
  392. def tech_babble():  #TODO  edit so use random.choice(), delete import statement, and put import random at top.
  393.     """
  394.    Prints a 3 word meaningless phrase; each word a real tech term.
  395.  
  396.    I have a script, tech_babble2.py, that outputs the same phrases. Use AW tb.
  397.    """
  398.     from random import choice
  399.     list1 = ["Integrated", "Pseudo", "Dynamic", "Potential", "Diurnal", "Stratosphere", "Cumulative", "Absolute", "Kinematic", "Conditional"]
  400.  
  401.     list2 = ["Thermal", "Vorticity", "Solenoidal", "Molecular", "Orthographic", "Turbulent", "Solar", "Inertial", "Rotational", "Vapor"]
  402.  
  403.     list3 = ["Equilibrium", "Transfer", "Stratification", "Balance", "Field", "Correlation", "Discontinuity", "Advection", "Trajectory", "Function"]
  404.  
  405.     print("CAUTION:", choice(list1), choice(list2), choice(list3))
  406.  
  407. def sets_intersection(sets_list):
  408.     """
  409.    Given a list of sets, return their intersection.
  410.    """
  411.     sets_list_length = len(sets_list)
  412.     if sets_list[0] == set():
  413.         return set()
  414.     intersection_of_sets = sets_list[0]
  415.     for i in range(1, sets_list_length):
  416.         if sets_list[0] == set():
  417.             return set()
  418.         intersection_of_sets &= sets_list[i]
  419.     return intersection_of_sets  
  420.  
  421. def gcd(*args):
  422.     """http://code.activestate.com/recipes/577512/"""
  423.     if len(args) == 1:
  424.         return args[0]
  425.  
  426.     L = list(args)
  427.  
  428.     while len(L) > 1:
  429.         a = L[len(L) - 2]
  430.         b = L[len(L) - 1]
  431.         L = L[:len(L) - 2]
  432.  
  433.         while a:
  434.             a, b = b%a, a
  435.  
  436.         L.append(b)
  437.  
  438.     return abs(b)
  439.  
  440. def gcd_all2(int_list):
  441.     """
  442.    Return gcd of list of integers
  443.    """
  444.     from fractions import gcd
  445.     int_list = [abs(n) for n in int_list]
  446.     # when int_list contains only zeros
  447.     if max(int_list) == min(int_list) == 0:
  448.         return 0
  449.     divisor = gcd(int_list[0],int_list[1])
  450.     int_list_length = len(int_list)
  451.     for i in range(1, int_list_length-2):
  452.         divisor = gcd(divisor, int_list[i+2])
  453.     return divisor
  454.  
  455. def gcd_of_ints(*args): # wrong (for 30,45,55 returns 15)
  456.     """
  457.    Returns gcd of any number of positive integers
  458.    """
  459.     import fractions
  460.     from mycalc import int_to_ordinal
  461.     flag = False
  462.     args = list(args)
  463.  
  464.     try:
  465.         for i, x in enumerate(args):
  466.             if not x > 0 or not isinstance(x, int):
  467.                 print('argument', x, 'is not a positive integer')
  468.                 flag = True
  469.         if flag:
  470.             return None
  471.  
  472.     except TypeError:
  473.         print('The', int_to_ordinal(i+1), 'argument is not a positive integer')
  474.         return None
  475.  
  476.     if len(args) == 1:
  477.         args.append(args[0])
  478.     gcd_ = fractions.gcd(args[0],args[1])
  479.     for i in range(2, len(args)-1):
  480.         gcd_ = fractions.gcd(gcd_, args[i])
  481.     return gcd_
  482.  
  483. def int_commas(n):
  484.     """
  485.    inserts commas into integers and returns the string
  486.  
  487.    E.g. -12345678 -> -12,345,789
  488.    """
  489.     return format(n, ',d')
  490.  
  491. def next_n_primes(m, n):  # TODO permits negative primes; faster than using my isPrime in nextNPrimes(), etc.?
  492.     """
  493.    Return list of first n primes > m. Even if m is prime, it won't be in the list.
  494.    """
  495.     count = 0
  496.     primes = []
  497.     p = m
  498.     while True:
  499.         p = int(gmpy2.next_prime(p))
  500.         primes.append(p)
  501.         count += 1
  502.         if count >= n:
  503.             return primes
  504.  
  505. def percent_error_from_standard(standard, x):
  506.     return 100*(abs(standard - x))/standard
  507.  
  508. def metric2BMI(kg, cm):
  509.     """
  510.    Given weight in kg and height in cm, return BMI
  511.    """
  512.     BMI = kg/(cm/100)**2
  513.     BMI = round(BMI, 1)
  514.     if BMI < 18.5:
  515.         category = "Underweight"
  516.     elif BMI < 25:
  517.         category = "Normal"
  518.     elif BMI < 30:
  519.         category = "Overweight"
  520.     else:
  521.         category = "Obese"
  522.     print()
  523.     print("Your BMI is", BMI, "which is", category)
  524.     print()
  525.     print("BMI categories:")
  526.     print("Below 18.5 Underweight")
  527.     print("18.5 - 24.9 Normal")
  528.     print("25 - 29.9 Overweight")
  529.     print("30 and above Obese")
  530.     kg_max = 24.9*(cm/100)**2
  531.     kg_min = 18.5*(cm/100)**2
  532.     print()
  533.     print("Your Normal range in kg is from", round(kg_min, 1), "to", round(kg_max, 1))
  534.  
  535. def english2BMI(pounds, inches):
  536.     """
  537.    Given weight in pounds and height in inches, return BMI
  538.    """
  539.     BMI = pounds*703/inches**2
  540.     BMI = round(BMI, 1)
  541.     if BMI < 18.5:
  542.         category = "Underweight"
  543.     elif BMI < 25:
  544.         category = "Normal"
  545.     elif BMI < 30:
  546.         category = "Overweight"
  547.     else:
  548.         category = "Obese"
  549.     print()
  550.     print("Your BMI is", BMI, "which is", category)
  551.     print()
  552.     print("BMI categories:")
  553.     print("Below 18.5 Underweight")
  554.     print("18.5 - 24.9 Normal")
  555.     print("25 - 29.9 Overweight")
  556.     print("30 and above Obese")
  557.     pounds_max = (24.9*inches**2)/703
  558.     pounds_min = (18.5*inches**2)/703
  559.     print()
  560.     print("Your Normal range in pounds is from", round(pounds_min, 1), "to", round(pounds_max, 1))
  561.  
  562. def pi_digits_gmpy(n):
  563.     """
  564.    Returns pi as a str to n digits; n must be >= 10
  565.    
  566.    >>> pi_digits_gmpy(10)
  567.    '3.141592653' (the 10 digits includes the initial '3'
  568.    """
  569.     def special_rounding(f):
  570.         """
  571.        Given a long float as a str, return it rounded off by one digit
  572.        """
  573.         f_last10 = f[-10:]
  574.         f_last10_over_1000000000 = int(f_last10)/10000000000
  575.         x = round(f_last10_over_1000000000,9)
  576.         if len(str(x)) < 11:
  577.             zeros = 11 - len(str(x))
  578.             x = str(x) + zeros*'0'
  579.         else:
  580.             x = str(x)
  581.         rounded_f = f[:-10] + x[2:]
  582.         return rounded_f
  583.     if n < 10:
  584.         print("n must be >= 10")
  585.         return
  586.     multiplier = 4
  587.     bits = 4*n
  588.     gmpy2.context().precision = bits
  589.     rough_pie = gmpy2.const_pi(bits)
  590.     rough_pie = str(rough_pie)
  591.     pie = rough_pie[:n+2]
  592.     rounded_pie = special_rounding(pie)
  593.     return rounded_pie
  594.  
  595. def seconds_elapsed(t, digits=0):
  596.     time_ = clock() - t
  597.     if digits == 0:
  598.         return int(round(time_, digits))
  599.     else:
  600.         return round(time_, digits)
  601.  
  602. def minutes_elapsed(t, digits=0):
  603.     time_ = clock() - t
  604.     minutes = time_/60
  605.     if digits == 0:
  606.         return int(round(minutes, digits))
  607.     else:
  608.         return round(minutes, digits)
  609.  
  610. def tim(t, digits, p=1):
  611.     time_  = clock() - t
  612.     if digits:
  613.         seconds = round(time_, digits)
  614.         minutes = round(time_/60, digits)
  615.         hours = round(time_/3600, digits)
  616.     else:
  617.         seconds = int(round(time_, digits))
  618.         minutes = int(round(time_/60, digits))
  619.         hours = int(round(time_/3600, digits))
  620.     if p and seconds > 3600:
  621.         print("time was", hours, "hours  or ", secsToHMS(time_))
  622.     elif p and seconds > 60:
  623.         print("time was", minutes, "minutes  or ", secsToHMS(time_))
  624.     elif p:
  625.         print("time was", seconds, "seconds  or ", secsToHMS(time_))
  626.     else:
  627.         return secsToHMS(time_)
  628.  
  629.  
  630. def catAge2HumanAge(catAge):
  631.     """
  632.    Given cat age, return equivalent human age
  633.  
  634.    See http://tinyurl.com/ylrjlp4
  635.    """
  636.     return 4 * (catAge - 1) + 16
  637.  
  638. def humanAge2CatAge(humanAge):
  639.     """
  640.    Given human age, return equivalent cat age
  641.    """
  642.     return (humanAge - 16) / 4 + 1      
  643.  
  644. def int2int_length(n, dpi = 10):
  645.     """
  646.    Given integer (large) integer n,
  647.    returns length of n in miles
  648.  
  649.    For my laptop monitor, there are
  650.    about 10 digits per inch (dpi = 10)
  651.    """
  652.     digits = int_digits(n)
  653.     miles = digits/dpi/12/5280
  654.     return miles
  655.  
  656. def num_digits2int_length(num_digits, dpi = 10):
  657.     """
  658.    Given number of digits of (large) integer n,
  659.    returns length of n in miles
  660.  
  661.    For my laptop monitor, there are
  662.    about 10 digits per inch (dpi = 10)
  663.    """
  664.     #digits = int_digits(n)
  665.     miles = num_digits/dpi/12/5280
  666.     return miles
  667.  
  668. def decDiv(num, denom, precision=100):
  669.     from decimal import getcontext, Decimal as D
  670.     getcontext().prec = precision
  671.     return D(str(num))/D(str(denom))
  672.  
  673. #TODO bugs with denoms: 96, 192, 384, 448
  674. # note that 192 and 384 are multiples of 96
  675. #def find_repeat_seq(num, denom, precision=1000):  
  676.     #"""
  677.     #Given num and denom of fraction, returns repeating sequence if there is one.
  678.  
  679.     #Shows at least 2 repetitions of sequence. Also its length.
  680.     #If no such sequence, then fraction's decimals expansion is exact. E.g., 0.375. Returns this.
  681.     #"""
  682.     #num, denom = reduceFraction(num, denom)      
  683.     ## long seqs: 3/911->(455); 37/947->(473); 547/1949->(1948)
  684.     #precision = 2*denom
  685.     #if precision < 50:
  686.         #precision = 50
  687.     #if denom > 50000:
  688.         #print("reduced denom is", denom)
  689.         #print("This is too large: calculation will take too long")
  690.         #return ""
  691.     ## dec, the decimal expansion
  692.     #dec = decDiv(num, denom, precision+3)
  693.     ## index of decimal point
  694.     #dec_pt_idx = str(dec).find('.')
  695.     ## the mantissa of the decimal expansion, as a string
  696.     #str_mantissa = str(dec)[dec_pt_idx+1:-1]
  697.  
  698.     #s = str_mantissa
  699.  
  700.     ## These mantissas are short, and exact. Therefore there is no repeating sequence.
  701.     ## E.g., for 3/8, mantissa is exactly 375. For 79/128, exactly 6171875
  702.     #if not is_dec_repeating(num, denom):
  703.         #return num/denom
  704.     #else:
  705.         #def format_return():
  706.             #if num > denom:
  707.                 #pre = str(num//denom) + '.'
  708.             #else:
  709.                 #pre = '0.'
  710.             #s_length = 2*len(ss)+5
  711.             #if s_length < 50 and len(ss) > 1:
  712.                 #s_length = 50
  713.             #s1 = s[:s_length] + '...'
  714.             #ss1 = '(' + ss + ')'
  715.             #s2 = pre + s1.replace(ss,ss1)
  716.             #return s2
  717.  
  718.         #for b in range(precision):
  719.             ## (re)initializing ss, which will be a sub-string of s
  720.             #ss = ""  
  721.             #for i in range(precision):
  722.                 ## Note that s[b+i] isn't actually appended to ss until last line of this loop.
  723.                 ## ss2 is the sequence of len(ss) that immediately follows ss.
  724.                 #ss2 = s[b+i:b+i+len(ss)]
  725.                 ## If the next digit in s after ss is also in ss, then ss is a candidate for the repeating seq.
  726.                 ## If ss == ss2, then ss is a repeating sequence.
  727.                 ## To test if ss is a single digit, see if all digits of s after ss are equal to ss.
  728.                 ## it is if after it all the digits in mantissa are identical to it.
  729.                 #if (s[b+i] in ss) and ss == ss2 and (s[b:].count(s[b+i]) == len(s[b:])):
  730.                     ##print("The repeating single-digit sequence is", ss)
  731.                     ##print("The repetition begins at index", b, "of the mantissa")
  732.                     ##return ss, b, len(ss)
  733.                     #return format_return(), len(ss)
  734.                 ## to test if repeating sequence has more than one digit
  735.                 #elif (s[b+i] in ss) and ss == ss2 and len(ss) > 1:
  736.                     ###print("The repeating sequence is", ss)
  737.                     ###print("The initial sequence begins at index", b, "of mantissa and has", len(ss), "digits")
  738.                     ## Note that len(ss) == i
  739.                     #return format_return(), len(ss)
  740.                 #else:
  741.                     #ss += s[b+i]
  742.  
  743. def find_repeat_seq(num, denom, precision=1000):  
  744.     """
  745.    Given num and denom of fraction, returns repeating sequence if there is one.
  746.  
  747.    Shows at least 2 repetitions of sequence. Also its length.
  748.    If no such sequence, then fraction's decimal expansion is exact. E.g., 3,8 returns 0.375.  
  749.    """
  750.     num, denom = reduceFraction(num, denom)  
  751.     f = str(num/denom)
  752.     if f[-2:] == ".0":
  753.         num = f[:-2]
  754.         print(num,"/1 = ", num, ".0", sep="", end="")
  755.         return None
  756.     # long seqs: 3/911->(455); 37/947->(473); 547/1949->(1948)
  757.     precision = 2*denom
  758.     if precision < 50:
  759.         precision = 50
  760.     if denom > 50000:
  761.         print("reduced denom is", denom)
  762.         print("This is too large: calculation will take too long")
  763.         return ""
  764.     # dec, the decimal expansion
  765.     dec = decDiv(num, denom, precision+3)
  766.     # index of decimal point
  767.     dec_pt_idx = str(dec).find('.')
  768.     # the mantissa of the decimal expansion, as a string
  769.     str_mantissa = str(dec)[dec_pt_idx+1:-1]
  770.  
  771.     s = str_mantissa
  772.  
  773.     # These mantissas are short, and exact. Therefore there is no repeating sequence.
  774.     # E.g., for 3/8, mantissa is exactly 375. For 79/128, exactly 6171875
  775.     if not is_dec_repeating(num, denom):
  776.         return num/denom
  777.     else:
  778.         def format_return():
  779.             if num > denom:
  780.                 pre = str(num//denom) + '.'
  781.             else:
  782.                 pre = '0.'
  783.             s_length = 2*len(ss)+5
  784.             if s_length < 50 and len(ss) > 1:
  785.                 s_length = 50
  786.             s1 = s[:s_length] + '...'
  787.             ss1 = '(' + ss + ')'
  788.             s2 = pre + s1.replace(ss,ss1)
  789.             return s2
  790.  
  791.         for b in range(precision):
  792.             # (re)initializing ss, which will be a sub-string of s
  793.             ss = ""  
  794.             for i in range(precision):
  795.                 # Note that s[b+i] isn't actually appended to ss until last line of this loop.
  796.                 # ss2 is the sequence of len(ss) that immediately follows ss.
  797.                 ss2 = s[b+i:b+i+len(ss)]
  798.                 # If the next digit in s after ss is also in ss, then ss is a candidate for the repeating seq.
  799.                 # If ss == ss2, then ss is a repeating sequence.
  800.                 # To test if ss is a single digit, see if all digits of s after ss are equal to ss.
  801.                 # it is if after it all the digits in mantissa are identical to it.
  802.                 if (s[b+i] in ss) and ss == ss2 and (s[b:].count(s[b+i]) == len(s[b:])):
  803.                     #print("The repeating single-digit sequence is", ss)
  804.                     #print("The repetition begins at index", b, "of the mantissa")
  805.                     #return ss, b, len(ss)
  806.                     return format_return(), len(ss)
  807.                 # to test if repeating sequence has more than one digit
  808.                 elif (s[b+i] in ss) and ss == ss2 and len(ss) > 1:
  809.                     ##print("The repeating sequence is", ss)
  810.                     ##print("The initial sequence begins at index", b, "of mantissa and has", len(ss), "digits")
  811.                     # Note that len(ss) == i
  812.                     return format_return(), len(ss)
  813.                 else:
  814.                     ss += s[b+i]
  815.  
  816. def find_repeat_seq2(fraction, precision=1000):  
  817.     """
  818.    Given a fraction with denominator <= 50,000, returns repeating sequence if there is one.
  819.  
  820.    Shows at least 2 repetitions of sequence. Also its length.
  821.    If no such sequence, then fraction's decimals expansion is exact. E.g., 0.375. Returns this.
  822.    
  823.    >>> find_repeat_seq2(121/331)
  824.    121/331 = 0.36555891238670696 =
  825.    ('0.(36555891238670694864048338368580060422960725075528700906344410876132930513595166163141993957703927492447129909)(36555891238670694864048338368580060422960725075528700906344410876132930513595166163141993957703927492447129909)36555...', 110)
  826.    >>>
  827.    >>> find_repeat_seq2(2/81)
  828.    2/81 = 0.024691358024691357 =
  829.    ('0.(024691358)(024691358)(024691358)(024691358)(024691358)02469...', 9)
  830.    >>>
  831.    >>> find_repeat_seq2(17/32)
  832.    17/32 = 0.53125
  833.    >>>
  834.    """
  835.     from decimal import getcontext, Decimal as D
  836.     getcontext().prec = precision
  837.     from fractions import Fraction
  838.     f = str(fraction)
  839.     if f[-2:] == ".0":
  840.         num = f[:-2]
  841.         print(num,"/1 = ", num, ".0", sep="", end="")
  842.         return None
  843.         #num = int(f[:-2])
  844.         #denom = float(1.0)
  845.         #print(num, denom)
  846.     frac = Fraction(f).limit_denominator(1000000)
  847.     frac = str(frac)
  848.     num = int(frac.split("/")[0])
  849.     denom = int(frac.split("/")[1])
  850.     precision = 2*denom
  851.     if precision < 50:
  852.         precision = 50
  853.     if denom > 50000:
  854.         print("reduced denom is", denom)
  855.         print("This is too large: calculation will take too long")
  856.         return ""
  857.     # dec, the decimal expansion
  858.     dec = decDiv(num, denom, precision+3)
  859.     # index of decimal point
  860.     dec_pt_idx = str(dec).find('.')
  861.     # the mantissa of the decimal expansion, as a string
  862.     str_mantissa = str(dec)[dec_pt_idx+1:-1]
  863.  
  864.     s = str_mantissa
  865.  
  866.     # These mantissas are short, and exact. Therefore there is no repeating sequence.
  867.     # E.g., for 3/8, mantissa is exactly 375. For 79/128, exactly 6171875
  868.     #num = int(num)
  869.     #denom = int(denom)
  870.     if not is_dec_repeating(num, denom):
  871.         print(num,"/",denom, " = ", num/denom, sep="", end="")
  872.         return None
  873.     else:
  874.         def format_return():
  875.             if num > denom:
  876.                 pre = str(num//denom) + '.'
  877.             else:
  878.                 pre = '0.'
  879.             s_length = 2*len(ss)+5
  880.             if s_length < 50 and len(ss) > 1:
  881.                 s_length = 50
  882.             s1 = s[:s_length] + '...'
  883.             ss1 = '(' + ss + ')'
  884.             s2 = pre + s1.replace(ss,ss1)
  885.             return s2
  886.  
  887.         for b in range(precision):
  888.             # (re)initializing ss, which will be a sub-string of s
  889.             ss = ""  
  890.             for i in range(precision):
  891.                 # Note that s[b+i] isn't actually appended to ss until last line of this loop.
  892.                 # ss2 is the sequence of len(ss) that immediately follows ss.
  893.                 ss2 = s[b+i:b+i+len(ss)]
  894.                 # If the next digit in s after ss is also in ss, then ss is a candidate for the repeating seq.
  895.                 # If ss == ss2, then ss is a repeating sequence.
  896.                 # To test if ss is a single digit, see if all digits of s after ss are equal to ss.
  897.                 # it is if after it all the digits in mantissa are identical to it.
  898.                 if (s[b+i] in ss) and ss == ss2 and (s[b:].count(s[b+i]) == len(s[b:])):
  899.                     #print("The repeating single-digit sequence is", ss)
  900.                     #print("The repetition begins at index", b, "of the mantissa")
  901.                     #return ss, b, len(ss)
  902.                     print(num,"/",denom, " = ", num/denom, " =", sep="")
  903.                     return format_return(), len(ss)
  904.                 # to test if repeating sequence has more than one digit
  905.                 elif (s[b+i] in ss) and ss == ss2 and len(ss) > 1:
  906.                     ##print("The repeating sequence is", ss)
  907.                     ##print("The initial sequence begins at index", b, "of mantissa and has", len(ss), "digits")
  908.                     # Note that len(ss) == i
  909.                     print(num,"/",denom, " = ", num/denom, " =", sep="")
  910.                     return format_return(), len(ss)
  911.                 else:
  912.                     ss += s[b+i]
  913.  
  914.  
  915. def is_dec_repeating(num, denom):
  916.     """
  917.    Test denominator of fraction. Does it have a repeating decimal?
  918.  
  919.    First, reduce the fraction, if possible. 3/24 -> 1/8
  920.    If the (new) denominator has a prime factor which is neither 2 nor 5,
  921.    then the fraction will have a repeating decimal in its expansion.
  922.    The importance of reduction is shown by the denom 24 = 2*2*2*3: 3/24 -> 3/8 (False);
  923.    6/24 -> 1/4 (False); 2/12 -> 1/6 (True); 1/24 (True)
  924.    """
  925.     denom = reduceFraction(num, denom)[1]
  926.     denom = abs(denom)
  927.     factors = factorsOfInteger(denom)
  928.     if factors.count(2) + factors.count(5) == len(factors):
  929.         return False
  930.     else:
  931.         return True
  932.  
  933. def croots(c, n):
  934.     """
  935.    Return list of the n n'th roots of complex c.
  936.  
  937.    by Tim Peters
  938.    """
  939.  
  940.     from math import sin, cos, atan2, pi
  941.     arg = abs(c)**(1/n)
  942.     theta = atan2(c.imag, c.real)
  943.     result = []
  944.     for i in range(n):
  945.         theta2 = (theta + 2*pi*i)/n
  946.         x = arg * cos(theta2)
  947.         y = arg * sin(theta2)
  948.         result.append(complex(x, y))
  949.     return result
  950.  
  951.  
  952. def prestrings2list(a_str):
  953.     """
  954.    Given a string of comma-separated words and phrases, or even passwords, return a list of them.
  955.    """
  956.     import re
  957.     mult_space = re.compile(r'\s+')
  958.     return [re.sub(mult_space, ' ', x).strip() for x in a_str.split(',')]
  959.  
  960. def float2Decimal(f):
  961.     """
  962.    Given a float, return the exact number stored in computer
  963.  
  964.    See http://docs.python.org/3.1/tutorial/floatingpoint.html#representation-error
  965.    """
  966.     from decimal import Decimal
  967.     return Decimal.from_float(f)
  968.  
  969. def values_dupe_keys(d):
  970.     """
  971.    Return a list of values in a dict d that have more than one key each.
  972.    The returned list will be of the form
  973.    [[value1, [key1, key2, key3, ...]], [value2, [[key11, key12, key13, ...], ...]]]
  974.    """
  975.     ## This is by Kent Johnson. See thread at
  976.     ## <http://thread.gmane.org/gmane.comp.python.tutor/49675/focus=49680>
  977.     from collections import defaultdict
  978.     rev = defaultdict(list)
  979.     for k, v in d.items():
  980.         rev[v].append(k)
  981.     return [ [v, keys] for v, keys in rev.items() if len(keys) > 1 ]
  982.  
  983. def gcd2(a, b):
  984.     """
  985.    Given integers a, b, return their greatest common divisor.
  986.    """
  987.     a, b = abs(a), abs(b)
  988.     while b != 0:
  989.         a, b = b, a % b
  990.     return a
  991.  
  992. def gcd3(a, b, c):
  993.     """
  994.    Given integers a, b, c, return their greatest common divisor.
  995.    """
  996.     a, b, c = abs(a), abs(b), abs(c)
  997.     d = gcd2(a, b)
  998.     return gcd2(d, c)
  999.  
  1000.  
  1001. def sin_deg(n):
  1002.     """
  1003.    Return sine of n, n in degrees
  1004.    """
  1005.     from math import sin, radians
  1006.     return sin(radians(n))
  1007.  
  1008. def asin_deg(a, c=1):
  1009.     """
  1010.    Given sides a and c of a right triangle,
  1011.    where c is the hypoteneuse,
  1012.    return angle A in degrees
  1013.    When a/c is known, e.g. is .345,
  1014.    use it alone: asin_deg(0.345)
  1015.    """
  1016.     from math import asin, degrees
  1017.     return degrees(asin(a/c))
  1018.  
  1019. def cos_deg(n):
  1020.     """
  1021.    Return cosine of n, n in degrees
  1022.    """
  1023.     from math import cos, radians
  1024.     return cos(radians(n))
  1025.  
  1026. def acos_deg(a, c=1):
  1027.     """
  1028.    Given sides b and c of a right triangle, where c is the hypoteneuse,
  1029.    return angle A in degrees. When b/c is known, e.g. is .655, use it alone: acos_deg(0.655)
  1030.    """
  1031.     from math import acos, degrees
  1032.     return degrees(acos(a/c))
  1033.  
  1034. def tan_deg(n):
  1035.     """
  1036.    Return tangent of n, n in degrees
  1037.    """
  1038.     from math import tan, radians
  1039.     return tan(radians(n))
  1040.  
  1041. def atan_deg(a, b=1):
  1042.     """
  1043.    Given sides b and a of a right triangle,
  1044.    where c is the hypoteneuse,
  1045.    return angle A in degrees
  1046.    When a/c is known, e.g. is 0.821,
  1047.    use it alone: atan_deg(0.821)
  1048.    """
  1049.     from math import atan, degrees
  1050.     return degrees(atan(a/b))
  1051.  
  1052. def foo():
  1053.     print("FOO on YO")
  1054.  
  1055. def remove_prompt(s):  #TODO
  1056.     """
  1057.    Print s with shell prompt's '>>> ' removed.
  1058.    Prepare an s such as this:
  1059.    """
  1060.  
  1061.     from string import replace
  1062.     s = s.replace(">>> ",'')
  1063.     print(s)
  1064.  
  1065.  
  1066. def sci_notation(n, sig_digits=30): #TODO
  1067.     """
  1068.    Return n in scientific notation form to sig_digits significant digits.
  1069.    If n is in float form, must be entered ether in quotes or as an mpf.
  1070.    If n is an integer, enter it as is.
  1071.    n must be a positive number.
  1072.    Setting sig_digits to 0 will set it to 1000.
  1073.    """
  1074.     from mpmath import mpf, mp, log
  1075.     precision = sig_digits
  1076.     if precision == 0:
  1077.         precision = 1000
  1078.     mp.dps = precision
  1079.     n = mpf(n)
  1080.     assert n > 0
  1081.     if n > 1:
  1082.         divisor = mpf(10)**int(log(n,10))
  1083.         return "%se+%03d" % (n/divisor, int(log(n,10)))
  1084.     else:
  1085.         divisor = mpf(10)**((int(log(n,10)))-1)
  1086.         return "%se%04d" % (n/divisor, (int(log(n,10)))-1)
  1087.  
  1088.  
  1089. def find_indexes_all_x_in_list(x, alist):
  1090.     """
  1091.    Return list of indexes of all x in a list.
  1092.    If no x in list, return []
  1093.    """
  1094.     n = alist.count(x)
  1095.     if n == 0:
  1096.         return []
  1097.     i = 0
  1098.     idx_list = []
  1099.     for j in range(n):
  1100.         idx = alist.index(x,i)
  1101.         idx_list.append(idx)
  1102.         i = idx + 1
  1103.     return idx_list
  1104.  
  1105. def sort_tuple_list_by_2nd_elements(alist):
  1106.     """
  1107.    Return a list of 2-element tuples, with the list
  1108.    sorted by the 2nd element of the tuples.
  1109.    """
  1110.     alist_tup_elements_reversed = [ (x[1], x[0]) for x in alist ]
  1111.     alist_tup_elements_reversed.sort()
  1112.     alist_tup_elements_reversed_and_reversed_again = [
  1113.         (x[1], x[0]) for x in alist_tup_elements_reversed ]
  1114.     return alist_tup_elements_reversed_and_reversed_again
  1115.  
  1116. def strip_punctuation(astr):
  1117.     from string import ascii_letters, digits
  1118.     return ''.join(c for c in astr if c in ascii_letters + digits + ' ')
  1119.  
  1120. def delete_underscores(astr):
  1121.     """
  1122.    Given a string with underscores, returns it without.
  1123.    E.g. "_cat_" --> "cat"
  1124.    """
  1125.     from mycalc import replace2
  1126.     return replace2(astr, r'_', '', 0, 0)
  1127.  
  1128. ##def text(filename):
  1129. ##    """
  1130. ##    Return text of E:\PythonWork\Nutshell\\<filename> as a string
  1131. ##    """
  1132. ##    # see http://docs.python.org/lib/bltin-file-objects.html, close()
  1133. ##
  1134. ##    path = 'E:\PythonWork\Nutshell\\' + filename
  1135. ##    with open(path) as file:
  1136. ##        return file.read()
  1137.  
  1138. ##def cap_words(astr):
  1139. ##    """
  1140. ##    Return a list of non-trivial capitalized words in a string/text.
  1141. ##
  1142. ##    The absence of trivial words in the list depends on both the string/text
  1143. ##    and the list of trivial words in E:\PythonWork\Nutshell\words.txt .
  1144. ##    Thus the output of cap_words() can be used to contribute to words.txt .
  1145. ##    """
  1146. ##    import re
  1147. ##    from mycalc import unique, make_first_words
  1148. ##    first_words = make_first_words() # make_first_words() is in mycalc.py
  1149. ##    first_words.sort()
  1150. ##    regex = r"[A-Za-z0-9]+(?:['-][A-Za-z0-9]+)*'?"
  1151. ##    p = re.compile(regex)
  1152. ##    cap_w = p.findall(astr)
  1153. ##    lst = []
  1154. ##    for word in first_words:
  1155. ##        while word in cap_w:
  1156. ##            cap_w.remove(word)
  1157. ##        lst.append(word)
  1158. ##    cap_w.sort()
  1159. ##    u = unique(cap_w)
  1160. ##    return u
  1161.  
  1162. ##def make_first_words():
  1163. ##    """
  1164. ##    Make the list, "first_words", for use with various scripts
  1165. ##    """
  1166. ##    file = open('E:\PythonWork\Nutshell\\words.txt', 'r')
  1167. ##    first_words = []
  1168. ##    for line in file.readlines():
  1169. ##        first_words.append(line[:-1])
  1170. ##    file.close()
  1171. ##    return first_words
  1172.  
  1173. def word_count(astr, hit_list=0):
  1174.     """
  1175.    Return a count of words in a string/text, and  optionally, a list of the words.
  1176.    """
  1177.     import re
  1178.  
  1179.     regex = r"[A-Za-z0-9]+(?:['-][A-Za-z0-9]+)*'?"
  1180.     p = re.compile(regex)
  1181.     f = p.findall(astr)
  1182.     if hit_list:
  1183.         lst = []
  1184.         for i, e in enumerate(f):
  1185.             lst.append(f[i])
  1186.         lst.sort()
  1187.         f = lst
  1188.         return f, len(f)
  1189.     return len(f)
  1190.  
  1191. def char_count(astr):
  1192.     """
  1193.    Return a count of visible characters in a string/text.
  1194.    """
  1195.     import re
  1196.     regex = r'[^\s]'
  1197.     p = re.compile(regex)
  1198.     f = p.findall(astr)
  1199.     return len(f)
  1200.  
  1201. def replace2(astr, regex, repl, I=0, count=0):
  1202.     """
  1203.    Replace all regex matches in a string with repl.
  1204.    I=0 is case sensitive; IGNORECASE is not used.
  1205.    count=0 means make all possible replacements.
  1206.    count=n (n > 0) means make the first n possible replacements.
  1207.  
  1208.    Couldn't name this function 'replace()' because
  1209.    'replace()' is an existing string method.
  1210.    """
  1211.     import re
  1212.     if I == 0:
  1213.         p = re.compile(regex)
  1214.     else:
  1215.         p = re.compile(regex, re.IGNORECASE)
  1216.     return p.sub(repl, astr, count)
  1217.  
  1218. # for 2.6 and 3.x, use isinstance(anobj,str) instead
  1219. def isStringLike(anobj):
  1220.     """
  1221.    Return True if anobj is a string; False if not
  1222.    """
  1223.     # Recipe 1.3 in Python Cookook, 2nd ed.
  1224.     # http://www.ubookcase.com/book/Oreilly/Python.Cookbook.2nd.edition/0596007973/pythoncook2-chp-1-sect-3.html
  1225.     try: anobj.lower( ) + anobj + ''
  1226.     except: return False
  1227.     else: return True
  1228.  
  1229. def is_dst():
  1230.     """
  1231.    Return True if local time is Daylight Time, False if not.
  1232.    """
  1233.     # from p. 129 of Python Cookbook, 2nd ed.
  1234.     import time
  1235.     return bool(time.localtime().tm_isdst)
  1236.  
  1237. def intListToString(intList):
  1238.     "convert a list of integers to a string, and return the string"
  1239.     # OR: return ''.join([str(x) for x in intList])
  1240.     return ''.join(map(str, intList))
  1241.  
  1242. def findFactor(n, startingAt):
  1243.     """
  1244.    Written by Kent Johnson
  1245.    """
  1246.     limit = int(n**.5) + 1
  1247.     x = startingAt
  1248.     while x < limit:
  1249.         if not n % x:
  1250.             return x
  1251.         x += 2
  1252.     return False
  1253.  
  1254. def factorsOfInteger(n):
  1255.     """
  1256.    Return list of prime factors of n.
  1257.    Returns [n] if n is prime.
  1258.    Re-written largely by Kent Johnson
  1259.    """
  1260.     factors = []
  1261.     if n == 1:
  1262.         return [1]
  1263.     # Get the factors of two out of the way to simplify findFactor
  1264.     while n % 2 == 0:
  1265.         factors.append(2)
  1266.         n = n // 2
  1267.     lastFactor = 3
  1268.     r = n
  1269.     while True:
  1270.         factor = findFactor(r, lastFactor)
  1271.         if not factor:
  1272.             # r is prime
  1273.             if r == 1: # This is needed, at least for powers of 2
  1274.                 break
  1275.             factors.append(r)
  1276.             break
  1277.         factors.append(factor)
  1278.         lastFactor = factor
  1279.         r = r / factor
  1280.     if len(factors) == 1: # changed this from  if n in factors
  1281.         return factors
  1282.     factors[-1] = int(factors[-1]) # without this some last factors are floats, ending in .0
  1283.     return factors
  1284.  
  1285. def findDayOfWeek(year, month, day):
  1286.     from calendar import weekday
  1287.     dayNumber = weekday(year, month, day)
  1288.     dayNames = ('Monday', 'Tuesday', 'Wednesday', 'Thursday',
  1289.                 'Friday', 'Saturday', 'Sunday')
  1290.     return dayNames[dayNumber]
  1291.  
  1292. ##def strIsInt(astr):
  1293. ##    """
  1294. ##    Tests if a string is comprised of just an integer.
  1295. ##    E.g., "-1234" --> True; "A34" --> False; "34.56" --> False
  1296. ##    """
  1297. ##    try:
  1298. ##        int(astr)
  1299. ##        return True
  1300. ##    except:
  1301. ##        return False
  1302.  
  1303. def strIsInt(astr): #Revise? employ isinstance()?
  1304.     """
  1305.    Tests if a string is comprised of just an integer.
  1306.    E.g., "-1234" --> True; "A34" --> False; "34.56" --> False "01234" --> False
  1307.    """
  1308.     #strip initial "-", if any, to test if the first digit is a zero; if it is, return False
  1309.     if astr[0] == "-":
  1310.         astr = astr[1:]
  1311.     if astr[0] == "0":
  1312.         return False
  1313.     try:
  1314.         int(astr)
  1315.         return True
  1316.     except:
  1317.         return False
  1318.  
  1319.  
  1320. def rstripToInt(n):
  1321.     """
  1322.    If a decimal (as a string) ends in .0, .00, .000, etc.,
  1323.    strip that ending to convert to an integer (as string).
  1324.    """
  1325.     n = n.rstrip(".0")
  1326.     return n
  1327.  
  1328. def floatToNearestInt(x):
  1329.     """
  1330.    convert float x to the nearest integer n
  1331.    e.g., 3.4 --> 3;  45.5 --> 46; -2.1 --> -2; -0.8 --> -1
  1332.    """
  1333.     return int(round(x))
  1334.  
  1335. def reduceFraction(num, denom): # TODO use fractions module
  1336.     """
  1337.    Given num and denom of a fraction, return
  1338.    the num and denom of the reduced fraction.
  1339.    """
  1340.     div = gcd2(num, denom)
  1341.     reducedNum = num/div
  1342.     reducedDenom = denom/div
  1343.     return int(reducedNum), int(reducedDenom)
  1344.  
  1345. def printReducedFraction():  #TODO use fractions moduled
  1346.     """
  1347.    Get a fraction from user and print the reduced fraction"
  1348.    """
  1349.     print("Enter the num and denom of the fraction to reduce")
  1350.     num, denom = get2NonzeroIntsFromUser()
  1351.     div = gcd2(num, denom)
  1352.     reducedNum = num/div
  1353.     reducedDenom = denom/div
  1354.     print('%d%s%d' % (reducedNum, '/', reducedDenom))
  1355.  
  1356. def get_integer():
  1357.     """
  1358.    Get integer from user and return it.
  1359.    """
  1360.     while True:
  1361.         try:
  1362.             return int(input("Enter an integer: "))
  1363.         except ValueError:
  1364.             print('You did not enter an integer')
  1365.  
  1366. def get2IntsFromUser():
  1367.     """
  1368.    Get 2 integers from user and return them.
  1369.    """
  1370.     while True:
  1371.         print("Enter 2 integers separated by a comma")
  1372.         try:
  1373.             m, n = (input("m, n: ")).split(',')
  1374.             m, n = int(m.strip()), int(n.strip())
  1375.         except ValueError:
  1376.             print()
  1377.             continue
  1378.         return m, n
  1379.  
  1380. def get2PosIntsFromUser():
  1381.     """
  1382.    Get 2 positive integers from use and return them.
  1383.    """
  1384.     while True:
  1385.         print("Enter 2 positive integers separated by a comma")
  1386.         try:
  1387.             m, n = (input("m, n: ")).split(',')
  1388.             m, n = int(m.strip()), int(n.strip())
  1389.         except ValueError:
  1390.             print()
  1391.             continue
  1392.         if m < 1 or n < 1:
  1393.             print()
  1394.             continue
  1395.         return m, n
  1396.  
  1397. def get_2_non_negative_ints_from_user():
  1398.     """
  1399.    Get 2 non-negative integers from use and return them.
  1400.    """
  1401.     while True:
  1402.         print("Enter 2 non-negative integers separated by a comma")
  1403.         try:
  1404.             m, n = (input("m, n: ")).split(',')
  1405.             m, n = int(m.strip()), int(n.strip())
  1406.         except ValueError:
  1407.             print()
  1408.             continue
  1409.         if m < 0 or n < 0:
  1410.             print()
  1411.             continue
  1412.         return m, n
  1413.  
  1414. def get2NonzeroIntsFromUser():
  1415.     """
  1416.    Get 2 non-zero integers from use and return them.
  1417.    """
  1418.     while True:
  1419.         print("Enter 2 non-zero integers separated by a comma")
  1420.         try:
  1421.             m, n = (input("m, n: ")).split(',')
  1422.             m, n = int(m.strip()), int(n.strip())
  1423.         except ValueError:
  1424.             print()
  1425.             continue
  1426.         if m == 0 or n == 0:
  1427.             print()
  1428.             continue
  1429.         return m, n
  1430.  
  1431. def numTailZeros(n):
  1432.     """
  1433.    Return the number of consecutive zeros at end of an integer.
  1434.    E.g., 25! = 15511210043330985984000000 ends in 6 zeros.
  1435.    """
  1436.     astr = str(n)
  1437.     return len(astr) - len(astr.rstrip('0'))
  1438.  
  1439. def uniform(n):
  1440.     """
  1441.    return distribution of digits in an int
  1442.    """
  1443.     #if not (isinstance(n, int)):
  1444.         #return "Not an int or long"
  1445.     a = str(n)
  1446.     i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1447.     for x in range(len(a)):
  1448.         if a[x] == '0':
  1449.             i0 += 1
  1450.         elif a[x] == '1':
  1451.             i1 += 1
  1452.         elif a[x] == '2':
  1453.             i2 += 1
  1454.         elif a[x] == '3':
  1455.             i3 += 1
  1456.         elif a[x] == '4':
  1457.             i4 += 1
  1458.         elif a[x] == '5':
  1459.             i5 += 1
  1460.         elif a[x] == '6':
  1461.             i6 += 1
  1462.         elif a[x] == '7':
  1463.             i7 += 1
  1464.         elif a[x] == '8':
  1465.             i8 += 1
  1466.         elif a[x] == '9':
  1467.             i9 += 1
  1468.     dist = [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  1469.     return dist
  1470.  
  1471. def to_base(n, base):   #TODO
  1472.     """
  1473.    converts base 10 integer to another base, up thru base 36.
  1474.    Returns the integer in that base.
  1475.    """
  1476.     import string
  1477.     n = int(n)
  1478.     base = int(base)
  1479.     if base < 2 or base > 36:
  1480.         raise ValueError("Base must be between 2 and 36")
  1481.     if not n:
  1482.         return 0
  1483.     symbols = string.digits + string.uppercase[:26]
  1484.     answer = []
  1485.     while n:
  1486.         n, remainder = divmod(n, base)
  1487.         answer.append(symbols[remainder])
  1488.     return ''.join(reversed(answer))
  1489.  
  1490. def nTo35Bases(n):  #TODO
  1491.     """
  1492.    Returns list of 35 tuples of form (base, n to that base)
  1493.    from base 2 through base 36.
  1494.    """
  1495.     tupleLst = []
  1496.     for base in range(2,37):
  1497.         nToBase = to_base(n,base)
  1498.         tupleLst.append((base,nToBase))
  1499.     return tupleLst
  1500.  
  1501.  
  1502. def base10ToBaseN(n, base=2):
  1503.     """
  1504.    converts base 10 integer n to base 2-9 integer as string
  1505.    """
  1506.     if n == 0: return '0'
  1507.     if n < 0:
  1508.         sign = '-'
  1509.     else:
  1510.         sign = ''
  1511.     num = abs(n)
  1512.     seq = []
  1513.     while (num != 0):
  1514.         (num, bit) = divmod(num, base)
  1515.         seq.append(str(bit))
  1516.     seq.append(sign)
  1517.     return ''.join(reversed(seq))
  1518.  
  1519. def n_to_bases_2_thru_9(n):
  1520.     """
  1521.    Use base10ToBaseN() to compute base 10 integer n to bases 2 through 9
  1522.    as strings and put them into a list.
  1523.    """
  1524.     aList = []
  1525.     for x in range(2,10):
  1526.         s = base10ToBaseN(n, x)
  1527.         aList.append(s)
  1528.     return aList
  1529.  
  1530. def b2tob10(n):
  1531.     """
  1532.    Given a base 2 number (in either string or integer form, return the base 10 integer
  1533.    """
  1534.     s = str(n)
  1535.     pow = len(s)-1
  1536.     b10 = 0
  1537.     for x in s:
  1538.         if x == '1':
  1539.             b10 += 2**pow
  1540.         elif int(x) > 1:
  1541.             print("The base 2 can't have an integer > 1!")
  1542.             return
  1543.         pow -= 1
  1544.     return b10
  1545.  
  1546. def base2_explained(b2):
  1547.     """
  1548.    Given a base 2 number (b2) as either an integer or a string, returns a string that explains b2.
  1549.    
  1550.    >>> base2_explained('1011')
  1551.    '1*2**3 + 0*2**2 + 1*2**1 + 1*2**0'
  1552.    (Use with b2tob10(n) to both explain and evaluate b2)
  1553.    >>> b2 = 111
  1554.    >>> base2_explained(b2);b2tob10(b2)
  1555.    '1*2**2 + 1*2**1 + 1*2**0'
  1556.    7
  1557.    """
  1558.     b2 = str(b2)
  1559.     pow2 = len(b2)-1
  1560.     b2explained = ''
  1561.     for i,x in enumerate(b2):
  1562.         if pow2 > 0:
  1563.             b2explained += x + '*' + '2' + '**' + str(pow2) + ' + '
  1564.             pow2 -= 1
  1565.         else:
  1566.             b2explained += x + '*' + '2' + '**' + str(pow2)
  1567.     return b2explained
  1568.  
  1569. def baseN2base10(n, N=2):
  1570.     """
  1571.    Given a base N number (N <= 10) (in either string or integer form), return the base 10 integer
  1572.    
  1573.    >>> baseN2base10(101,2)
  1574.    5
  1575.    >>> baseN2base10('101',2)
  1576.    5
  1577.    >>> baseN2base10(1234,5)
  1578.    194
  1579.    >>> baseN2base10(194,10)
  1580.    194
  1581.    >>> baseN2base10(1234,16)
  1582.    The base, N, can't be > 10!
  1583.    >>>
  1584.    """
  1585.     s = str(n)
  1586.     power = len(s)-1
  1587.     b10 = 0
  1588.     if N > 10:
  1589.         print("The base, N, must be <= 10!")
  1590.         return
  1591.    
  1592.     for x in s:
  1593.         if 0 < int(x) < N:
  1594.             b10 += int(x)*N**power
  1595.         elif int(x) >= N:
  1596.             print("The base", N, "can't have an integer >= N!")
  1597.             return
  1598.         power -= 1
  1599.     return b10
  1600.  
  1601. def sumRndInt(m, n):
  1602.     """
  1603.    Generates a list of length m of random positive integers that sum to n.
  1604.    All possible lists are equally probable.
  1605.    m, n must be <= 2,147,483,647 (i.e., 2**31-1)
  1606.  
  1607.    Of course, m >= n
  1608.    This is the "telegraph pole" solution described at
  1609.    http://tinyurl.com/2wdt48 .
  1610.    """
  1611.     import random
  1612.     t = sorted(random.sample(range(1,n), n-1))
  1613.     t2 = [0] + t + [m]
  1614.     return [ (t2[i] - t2[i-1]) for i in range(1, len(t2)) ]
  1615.  
  1616. # Delete because of Python 3 built-in, round() (However, even it doesn't always round to even. E.g. round(0.1301675, 6) => 0.130167)
  1617. #def roundToEven(n, digits):
  1618.     #"""
  1619.     #For "round-to-even" rounding.
  1620.     #See http://en.wikipedia.org/wiki/Rounding#Round-to-even_method
  1621.     #"""
  1622.     #s = str(n)
  1623.     #if '.' in s:
  1624.         #mantissa = s.split('.')[1]
  1625.         #if len(mantissa) - digits != 1:
  1626.             #return round(float(s), digits)
  1627.         #if mantissa[digits] != '5':
  1628.             #return round(float(s), digits)
  1629.         #if mantissa[digits -1] in '13579':
  1630.             #return round(float(s), digits)
  1631.         #else:
  1632.             #return  s[:-1]
  1633.     #else:
  1634.         #return round(float(s), digits)
  1635.  
  1636. #def round2(n, digits):
  1637.     #"""
  1638.     #A corrective for the built-in function, round().
  1639.  
  1640.     #round() is wrong about 4% of time when mantissa ends in "45",
  1641.     #and rounding calls for, e.g. rounding 0.1301345 to 0.130135
  1642.     #round(0.1301345, 6) returns instead 0.130134
  1643.     #round2(0.1301345, 6) returns 0.130135
  1644.     #This is correct "common method rounding"
  1645.     #See http://en.wikipedia.org/wiki/Rounding#Common_method
  1646.     #"""
  1647.     #s = str(n)
  1648.     #if '.' in s and s[-2:] == '45':
  1649.         #mantissa = s.split('.')[1]
  1650.         #if len(mantissa) - digits == 1:
  1651.             #s = s[:-2] + '5'
  1652.             #return s
  1653.         #else:
  1654.             #return round(float(s), digits)
  1655.     #else:
  1656.         #return round(float(n), digits)
  1657.  
  1658. def sumStringDigits(s):
  1659.     """
  1660.    Return the sum of the digits in a string.
  1661.    The string may contain non-digit characters.
  1662.    """
  1663.     lstS = list(s)
  1664.     lstN = []
  1665.     for x in lstS:
  1666.         if x in "0123456789":
  1667.             lstN.append(int(x))
  1668.     return sum(lstN)
  1669.  
  1670. def productStringDigits(s):
  1671.     """
  1672.    Return the product of the digits in a string.
  1673.    The string may contain non-digit characters.
  1674.    """
  1675.     lstS = list(s)
  1676.     lstN = []
  1677.     for x in lstS:
  1678.         if x in "01234456789":
  1679.             lstN.append(int(x))
  1680.     product = 1
  1681.     for x in lstN:
  1682.         product *= x
  1683.     return product
  1684.  
  1685. def avgStringDigits(s):
  1686.     """
  1687.    Return the mean of the digits in a string.
  1688.    The string may contain non-digit characters.
  1689.    Return 0 if string is empty or has no digits.
  1690.    """
  1691.     lstN = []
  1692.     digit_count = 0
  1693.     for x in s:
  1694.         if x in "0123456789":
  1695.             digit_count += 1
  1696.             lstN.append(int(x))
  1697.     if digit_count == 0:
  1698.         return 0
  1699.     return sum(lstN)/digit_count
  1700.  
  1701. def unique(seq):
  1702.     """
  1703.    Take a sequence--a string, list, or tuple--and return a sorted
  1704.    sequence of the same type, and of all unique elements.
  1705.  
  1706.    Cannot be used if sequence contains complex numbers. This will
  1707.    raise a TypeError: no ordering relation is defined for complex numbers.
  1708.    """
  1709.     def types(example):
  1710.         """
  1711.        Given an object, return its type.
  1712.        """
  1713.         import re
  1714.         astr = str(type(example))
  1715.         regex = "\'(\w+)\'"
  1716.         p = re.compile(regex)
  1717.         pf = p.findall(astr)
  1718.         if pf:
  1719.             return pf[0]
  1720.  
  1721.     def unique_list(l):
  1722.         l = set(l)
  1723.         return list(l)
  1724.  
  1725.     def unique_str(s):
  1726.         lst = list(s)
  1727.         lst = unique_list(lst)
  1728.         lst.sort()
  1729.         return "".join(lst)
  1730.  
  1731.     def unique_tuple(t):
  1732.         lst = list(t)
  1733.         lst = unique_list(lst)
  1734.         return tuple(lst)
  1735.  
  1736.     typ = types(seq)
  1737.  
  1738.     if typ == "str":
  1739.         return unique_str(seq)
  1740.     elif typ == "list":
  1741.         return unique_list(seq)
  1742.     elif typ == "tuple":
  1743.         return unique_tuple(seq)
  1744.  
  1745. def pi_digits2():
  1746.     """
  1747.    generator for digits of pi
  1748.  
  1749.    Cannot be used alone. Used by printNPiDigits()
  1750.    """
  1751.     q,r,t,k,n,l = 1,0,1,1,3,3
  1752.     while True:
  1753.         if 4*q+r-t < n*t:
  1754.             yield n
  1755.             q,r,t,k,n,l = (10*q,10*(r-n*t),t,k,(10*(3*q+r))/t-10*n,l)
  1756.         else:
  1757.             q,r,t,k,n,l = (q*k,(2*q+r)*l,t*l,k+1,(q*(7*k+2)+r*l)/(t*l),l+2)
  1758.  
  1759. #def piToNDigits(n):
  1760. #    """
  1761. #    Returns PI to n digits.
  1762. #    E.g. if n is 4, returns 3.141
  1763. #    Does no rounding (e.g., returns 3.141, not 3.142)
  1764. #    """
  1765. #    digits = pi_digits2()
  1766. #
  1767. #    piList = []
  1768. #    for i in range(n):
  1769. #        piList.append(str(digits.next()))
  1770. #    piList.insert(1,".") # insert period between the 3 and the 1
  1771. #    piString = "".join(piList)
  1772. #    return piString
  1773. #
  1774. #def printNPiDigits(n):
  1775. #    """
  1776. #    Prints PI to n digits.
  1777. #    E.g. if n is 4, prints 3.141
  1778. #    Does no rounding (e.g., prints 3.141, not 3.142)
  1779. #    """
  1780. #    digits = pi_digits2()
  1781. #
  1782. #    piList = []
  1783. #    for i in range(n):
  1784. #        piList.append(str(digits.next()))
  1785. #    piList.insert(1,".") # insert period between the 3 and the 1
  1786. #    piString = "".join(piList)
  1787. #    print piString
  1788.  
  1789. #def piDigits(digits):
  1790.     #"""
  1791.     #Returns pi to any number of digits.
  1792.  
  1793.     #Rounding is inconsistent, in that 5 is sometimes rounded up,
  1794.       #and sometimes down.
  1795.     #"""
  1796.     ##from mpmath import *;mp.dps=digits;mp.pretty=True
  1797.     #from mpmath import mpf, mp, pi
  1798.     #mpf.dps = digits
  1799.     #return pi()
  1800.  
  1801. #def piDigits(digits):
  1802.     #"""
  1803.     #Returns pi to any number of digits.
  1804.  
  1805.     #Rounding is inconsistent, in that 5 is sometimes rounded up,
  1806.       #and sometimes down.
  1807.     #"""
  1808.     ##from mpmath import mpf, mp, pi
  1809.     #from mpmath import *
  1810.     #mp.dps = digits
  1811.     #return pi()
  1812.  
  1813.  
  1814.  
  1815.  
  1816. ## this reinvents the wheel! random.randint() also handles negative min and max!!
  1817. #def rndInt(min, max=None):
  1818. #    """
  1819. #    Returns a random integer in closed interval [min,max],
  1820. #    where min, max are non-negative and min <= max
  1821. #    """
  1822. #    from random import random
  1823. #    if max is None:
  1824. #        max, min = min, 0
  1825. #    diff = max - min + 1
  1826. #    diff = max - min + 1
  1827. #    while True:
  1828. #        # remove initial "0." and possible final 0's, to leave a string of 10 digits
  1829. #        s = str(random())[2:12]
  1830. #        # when diff > 10; need to add extra number of 10 digit strings to s
  1831. #        digits = len(str(diff))
  1832. #        if digits > 10:
  1833. #            # find how many extra strings of 10 to add, if necessary
  1834. #            if digits % 10 == 0:
  1835. #                extra = digits/10 - 1
  1836. #            else:
  1837. #                extra = digits/10
  1838. #            astr = ""
  1839. #            # add the extra strings to s
  1840. #            for x in range(extra):
  1841. #                astr += str(random())[2:12]
  1842. #            s = s + astr
  1843. #        # remove unneeded digits at end of s, i.e., when len(s) > digits
  1844. #        s = s[:digits]
  1845. #        s = s.lstrip("0")
  1846. #        # in case s above was all ""0""'s
  1847. #        if s == "":
  1848. #            s = "0"
  1849. #        n = int(s)
  1850. #        if min <= (n + min) <= max:
  1851. #            return n + min
  1852.  
  1853. def random_digits_string(n):
  1854.     """
  1855.    Return n (n > 0) random digits in a string with one call to random.
  1856.  
  1857.    by Steve D'Aprano of the Tutor list
  1858.    
  1859.    >>> random_digits(6)
  1860.    '041890'
  1861.    >>> random_digits(20)
  1862.    '89372507420797668889'
  1863.    """
  1864.     return "%0*d" % (n, random.randrange(10**n))
  1865.  
  1866. def randIntOfGivenLength(length):
  1867.     """
  1868.    Return a random int of a given number of digits
  1869.    """
  1870.     return random.randint(10**(length-1), 10**length - 1)
  1871.  
  1872. def randIntOfRandLength(minLength, maxLength):  #TODO this returns a string!
  1873.     """
  1874.    First, the function generates a random length in closed interval
  1875.    [minLength, maxLength]. Then it generates a random integer n of that length,
  1876.    i.e., that many digits. The important feature of this function is that
  1877.    lengths within the max and min are all equally likely, as opposed to
  1878.    functions such as random.randint(). For example, for
  1879.    random.randint(10, 999), integers of 3-digit integers are 10 times more
  1880.    likely to be generated than 2-digit integers.
  1881.    """
  1882.     import random
  1883.     x = None
  1884.     s = ""
  1885.     n = None
  1886.     length = random.randint(minLength, maxLength)
  1887.     while True:
  1888.         x = random.randint(0, 9)
  1889.         s = s + str(x)
  1890.         if s[0] == '0':
  1891.             s.lstrip('0')
  1892.         n = int(s)
  1893.         if n >= 10**(length - 1):
  1894.             return n
  1895.  
  1896.  
  1897. def isLeap(y):
  1898.     """
  1899.    Returns True if y is a leap year; False if not.
  1900.    
  1901.    y is a leap year unless (1) it is either not divisible by 4,
  1902.    or (2) divisible by 100 but not divisible by 400.
  1903.    E.g., 1937 is not a leap year; 2100 is not; 2000 is; 2008 is.
  1904.    
  1905.    >>> isLeap(1937)
  1906.    False
  1907.    >>> isLeap(2100)
  1908.    False
  1909.    >>> isLeap(2000)
  1910.    True
  1911.    >>> isLeap(2008)
  1912.    True
  1913.    """
  1914.     if y % 4 != 0 or (y % 100 == 0 and y % 400 != 0):
  1915.         return False
  1916.     else:
  1917.         return True
  1918.  
  1919. #def easterAndAshWednesdayDates(y):
  1920.     #"""
  1921.     #Under the ecclesiastical rules, Easter is never earlier than March 22,
  1922.     #nor later than April 25.
  1923.     #This function will print the date of Easter for each year in the Gregorian calendar.
  1924.     #(Algorithm is from http://aa.usno.navy.mil/faq/docs/easter.html)
  1925.  
  1926.     #Ash Wednesday is always 46 days earlier than Easter.
  1927.     #"""
  1928.     ## compute Easter, given the year, y
  1929.     #c = y / 100
  1930.     #n = y - 19 * ( y / 19 )
  1931.     #k = ( c - 17 ) / 25
  1932.     #i = c - c / 4 - ( c - k ) / 3 + 19 * n + 15
  1933.     #i = i - 30 * ( i / 30 )
  1934.     #i = i - ( i / 28 ) * ( 1 - ( i / 28 ) * ( 29 / ( i + 1 ) ) * ( ( 21 - n ) / 11 ) )
  1935.     #j = y + y / 4 + i + 2 - c + c / 4
  1936.     #j = j - 7 * ( j / 7 )
  1937.     #l = i - j
  1938.     #m = 3 + ( l + 40 ) / 44
  1939.     #d = l + 28 - 31 * ( m / 4 )
  1940.     #easterMonth = "March"
  1941.     #easterDate = d
  1942.     #if m == 4:
  1943.         #easterMonth = "April"
  1944.     #print("Easter in %d is %s %d" % (y, easterMonth, easterDate))
  1945.     ## now compute Ash Wednesday, given year y, easterMonth, and easterDate
  1946.     #ashWednesdayDate = None
  1947.     #ashWednesdayMonth = None
  1948.     #leap = 0
  1949.     #if isLeap(y): # isLeap() is a mycalc function
  1950.         #leap = 1
  1951.     #if easterMonth == "April":
  1952.         #febDateForEaster = easterDate + 28 + leap + 31
  1953.         #ashWednesdayDate = febDateForEaster - 46
  1954.         #ashWednesdayMonth = "February"
  1955.     #elif easterMonth == "March":
  1956.         #febDateForEaster = easterDate + 28 + leap
  1957.         #ashWednesdayDate = febDateForEaster - 46
  1958.         #ashWednesdayMonth = "February"
  1959.     #if ashWednesdayDate > 28:
  1960.         #ashWednesdayDate -= 28
  1961.         #ashWednesdayMonth = "March"
  1962.     #print("Ash Wednesday in %d is %s %d" % (y, ashWednesdayMonth, ashWednesdayDate))
  1963.  
  1964. def easter_date(year):
  1965.     """
  1966.    Under the ecclesiastical rules, Easter is never earlier than March 22,
  1967.    nor later than April 25.
  1968.    This function will print the date of Easter for each year in the Gregorian calendar.
  1969.    (Algorithm is from http://aa.usno.navy.mil/faq/docs/easter.php)
  1970.    (online calculator: http://aa.usno.navy.mil/data/docs/easter.php)
  1971.  
  1972.    Ash Wednesday is always 46 days earlier than Easter.
  1973.    """
  1974.     # compute Easter, given the year
  1975.     y = year
  1976.     c = y // 100
  1977.     n = y - 19 * ( y // 19 )
  1978.     k = ( c - 17 ) // 25
  1979.     i = c - c // 4 - ( c - k ) // 3 + 19 * n + 15
  1980.     i = i - 30 * ( i // 30 )
  1981.     i = i - ( i // 28 ) * ( 1 - ( i // 28 ) * ( 29 // ( i + 1 ) ) * ( ( 21 - n ) // 11 ) )
  1982.     j = y + y // 4 + i + 2 - c + c // 4
  1983.     j = j - 7 * ( j // 7 )
  1984.     l = i - j
  1985.     m = 3 + ( l + 40 ) // 44
  1986.     d = l + 28 - 31 * ( m // 4 )
  1987.     easterMonth = "March"
  1988.     easterDate = d
  1989.     if m == 4:
  1990.         easterMonth = "April"
  1991.     print("Easter in", y, "is", easterMonth, easterDate)
  1992.    
  1993. def specific_easter_date_over_range_of_years(month, date, start_year, end_year):
  1994.     """
  1995.    Under the ecclesiastical rules, Easter is never earlier than March 22,
  1996.    nor later than April 25.
  1997.    This function will print the date of Easter for each year in the Gregorian calendar. (The first complete Gregorian calendar year was 1583.)
  1998.    (Algorithm is from http://aa.usno.navy.mil/faq/docs/easter.php)
  1999.    (online calculator: http://aa.usno.navy.mil/data/docs/easter.php)
  2000.  
  2001.    Ash Wednesday is always 46 days earlier than Easter.
  2002.    
  2003.    >>> specific_easter_date_over_range_of_years("April", 24, 1583, 3000)
  2004.    April 24 1639, April 24 1707, April 24 1791, April 24 1859, April 24 2011, April 24 2095, April 24 2163, April 24 2231, April 24 2383, April 24 2467, April 24 2478, April 24 2535, April 24 2603, April 24 2687, April 24 2698, April 24 2755, April 24 2839, April 24 2850, April 24 2907, April 24 2918, 20 Easters
  2005.    
  2006.    >>> specific_easter_date_over_range_of_years("March", 26, 1583, 3000)
  2007.    March 26 1595, March 26 1606, March 26 1617, March 26 1690, March 26 1758, March 26 1769, March 26 1780, March 26 1815, March 26 1826, March 26 1837, March 26 1967, March 26 1978, March 26 1989, March 26 2062, March 26 2073, March 26 2084, March 26 2119, March 26 2130, March 26 2141, March 26 2209, March 26 2282, March 26 2293, March 26 2339, March 26 2350, March 26 2361, March 26 2372, March 26 2434, March 26 2445, March 26 2456, March 26 2502, March 26 2513, March 26 2524, March 26 2586, March 26 2597, March 26 2654, March 26 2665, March 26 2676, March 26 2711, March 26 2722, March 26 2733, March 26 2806, March 26 2817, March 26 2828, March 26 2969, March 26 2980, 45 Easters
  2008.    
  2009.    >>> specific_easter_date_over_range_of_years("April", 26, 1583, 3000)
  2010.    0 Easters
  2011.    """
  2012.     count = 0
  2013.     for y in range(start_year, end_year+1):
  2014.         c = y // 100
  2015.         n = y - 19 * ( y // 19 )
  2016.         k = ( c - 17 ) // 25
  2017.         i = c - c // 4 - ( c - k ) // 3 + 19 * n + 15
  2018.         i = i - 30 * ( i // 30 )
  2019.         i = i - ( i // 28 ) * ( 1 - ( i // 28 ) * ( 29 // ( i + 1 ) ) * ( ( 21 - n ) // 11 ) )
  2020.         j = y + y // 4 + i + 2 - c + c // 4
  2021.         j = j - 7 * ( j // 7 )
  2022.         l = i - j
  2023.         m = 3 + ( l + 40 ) // 44
  2024.         d = l + 28 - 31 * ( m // 4 )
  2025.         easterMonth = "March"
  2026.         easterDate = d
  2027.         if m == 4:
  2028.             easterMonth = "April"
  2029.            
  2030.         if easterMonth == month and easterDate == date:
  2031.             count += 1
  2032.             print(easterMonth, easterDate, y, end = ', '),
  2033.             #print("Easter in", y, "is", easterMonth, easterDate, end = ', ')
  2034.     print(count, "Easters")
  2035.  
  2036. def permute(word):
  2037.     """
  2038.    By Barry Carrol <[email protected]>
  2039.    on Tutor list, revised (last line) by me.
  2040.    """
  2041.     retList=[]
  2042.     if len(word) == 1:
  2043.         # There is only one possible permutation
  2044.         retList.append(word)
  2045.     else:
  2046.         # Return a list of all permutations using all characters
  2047.         for pos in range(len(word)):
  2048.             # Get the permutations of the rest of the word
  2049.             permuteList=permute(word[0:pos]+word[pos+1:len(word)])
  2050.             # Now, tack the first char onto each word in the list
  2051.             # and add it to the output
  2052.             for item in permuteList:
  2053.                 retList.append(word[pos]+item)
  2054.     #return retList
  2055.     return list(set(retList)) # My revision of last line to make elements of retList unique
  2056.  
  2057.  
  2058. #def round_to_n(x, n):
  2059.     #"""
  2060.     #Rounds float x to n significant digits, in scientific notation.
  2061.     #Written by Tim Peters. See his Tutor list post of 7/3/04 at
  2062.     #http://mail.python.org/pipermail/tutor/2004-July/030324.html
  2063.  
  2064.     #The largest x this function can compute is approximately
  2065.     #1.7976931348623158e+308
  2066.     #"""
  2067.     #if n < 1:
  2068.         #raise ValueError("number of significant digits must be >= 1")
  2069.     #if n > 16:
  2070.         #raise ValueError("round_to_n(x, n) is accurate only for n <= 16")
  2071.     #if x > 1.7976931348623158e+308:
  2072.         #raise ValueError("x must be < approximately 1.7976931348623158e+308")
  2073.     #return "%.*e" % (n-1, x)
  2074.  
  2075. def round_to_n(x, n=10000):
  2076.     """
  2077.    Rounds float x to n significant digits, in scientific notation.
  2078.    An early, simpler version was written by Tim Peters.
  2079.    See his Tutor list post of 7/3/04 at
  2080.    http://mail.python.org/pipermail/tutor/2004-July/030324.html
  2081.    
  2082.    For floats, n must be 1 >= n <= 16
  2083.    i.e., n must be in closed interval [1,16]
  2084.    n < 1 raises ValueError
  2085.    For n > 16, n silently set to 16.
  2086.    
  2087.    For integers, converts int to scientific notation.
  2088.    If want the full int expressed in scientific notation,
  2089.    omit n. The exponent+1 = number of digits in the integer x.
  2090.    
  2091.    >>> x = 337234222221111113333333333333333333333333333333
  2092.    >>> print(round_to_n(x))
  2093.    3.37234222221111113333333333333333333333333333333e+47
  2094.    >>> len(str(x))
  2095.    48
  2096.    
  2097.    >>> x = 337234222221111113333333333333333333333333333333
  2098.    >>> print(round_to_n(x,7))
  2099.    3.372342e+47
  2100.    >>> len(str(x))
  2101.    9
  2102.    
  2103.    >>> x = 123456789
  2104.    >>> print(round_to_n(x))
  2105.    1.23456789e+8
  2106.    >>> len(str(x))
  2107.    9
  2108.    
  2109.    >>> x = 56784567.34567689345678906789023455673578900987
  2110.    >>> print(round_to_n(x))
  2111.    5.678456734567689e+07
  2112.    
  2113.    >>> x = 56784567.34567689345678906789023455673578900987
  2114.    >>> print(round_to_n(x,4))
  2115.    5.678e+07
  2116.    
  2117.    The largest x this function can compute is approximately
  2118.    x = 1.7976931348623158e+308, or x = 1.999999999999999*2**1023
  2119.    
  2120.    TODO
  2121.    >>> x = .00000123456
  2122.    >>> round_to_n(x)
  2123.    '1.234560000000000e-06'
  2124.    """
  2125.     if n < 1:
  2126.         raise ValueError("number of significant digits must be >= 1")
  2127.    
  2128.     if x < 0:
  2129.         sign = '-'
  2130.         x = abs(x)
  2131.     else:
  2132.         sign = ''
  2133.    
  2134.     if x > 1.7976931348623158e+308:
  2135.         stmt1 = "x must be <= approximately 1.7976931348623158e+308\n"
  2136.         stmt2 = "or <= 1.999999999999999*2**1023;\n"
  2137.         stmt3 = "x = 2**1024 is too big"
  2138.         stmt = stmt1 + stmt2 + stmt3
  2139.         raise ValueError(stmt)
  2140.    
  2141.     if n == 10000 and isinstance(x, int):
  2142.         n = len(str(x))
  2143.         temp = "%.*e" % (n-1, x)
  2144.         idx = temp.find('+')
  2145.         exp = temp[idx+1:]
  2146.         x = str(x)
  2147.         exp = str(len(x)-1)
  2148.         return sign + x + 'e+' + exp
  2149.        
  2150.     elif isinstance(x, int):
  2151.         temp = "%.*e" % (n-1, x)
  2152.         idx = temp.find('+')
  2153.         exp = temp[idx+1:]
  2154.         x = str(x)
  2155.         exp = str(len(x)-1)
  2156.         return sign + x[0] + '.' + x[1:n] + 'e+' + exp
  2157.            
  2158.     elif isinstance(x, float):
  2159.         if n > 16:
  2160.             n = 16
  2161.         if x < 1:
  2162.             if n == 16:
  2163.                 #print("x =",x)
  2164.                 temp = str(x)
  2165.                 if 'e' in temp:
  2166.                     #print("SECTION 1")
  2167.                     return sign + temp
  2168.                 elif 'e' not in temp:
  2169.                     #print("SECTION 2")
  2170.                     temp2 = temp.replace('.','')
  2171.                     #print("temp2 =", temp2)
  2172.                    
  2173.                     #now count the zeroes between before the first non-zero
  2174.                     temp3 = temp2
  2175.                     count = 0
  2176.                     while temp3[0] == '0':
  2177.                         temp3 = temp3[1:]
  2178.                         count += 1
  2179.                     #print("temp3 =", temp3)
  2180.                     #print("count =", count)
  2181.                     exp = str(-count)
  2182.                     #print("exp =", exp)
  2183.                     return sign + temp3[0] + '.' + temp3[1:] + 'e' + exp
  2184.                 else:
  2185.                     print("BUG3!")
  2186.                    
  2187.             elif n < 16:
  2188.                 #print("SECTION 3")
  2189.                 #print("x =", x)
  2190.                 temp = str(x)
  2191.                 #print("temp =", temp)
  2192.                 idx1 = temp.find('-')
  2193.                 exp = temp[idx1+1:]
  2194.                 temp2 = temp.replace('.','')
  2195.                 #print("temp2 =", temp2)
  2196.                 idx2 = temp2.find('e')
  2197.                 #print("idx2 =", idx2)
  2198.                 temp3 = temp2[:idx2]
  2199.                 temp4 = temp3[0] + '.' + temp3[1:]
  2200.                 #print("temp4 =", temp4)
  2201.                 temp5 = round(float(temp4),n-1)
  2202.                 #print("after rounding: ", temp5)
  2203.                 return sign + str(temp5) + 'e-' + exp
  2204.            
  2205.             else:
  2206.                 print("BUG4!")
  2207.            
  2208.         elif x >= 1:
  2209.             return sign + "%.*e" % (n-1, x)
  2210.        
  2211.         else:
  2212.             print("BUG2!")
  2213.            
  2214.     else:
  2215.         print("BUG1!")
  2216.  
  2217. def numberRounding(n, significantDigits): #TODO Swap sig_digits for this in my scripts
  2218.     """
  2219.    Rounds a string in the form of a string number
  2220.    (float or integer, negative or positive) to any number of
  2221.    significant digits. If an integer, there is no limitation on it's size.
  2222.    Safer to always have n be a string.
  2223.    """
  2224.     import decimal
  2225.     def d(x):
  2226.         return decimal.Decimal(str(x))
  2227.     decimal.getcontext().prec = significantDigits
  2228.     s = str(d(n)/1)
  2229.     s = s.lstrip('0')
  2230.     return s
  2231.  
  2232. #TODO Swap sig_digits for this in my scripts
  2233. # Don't use -- can't use
  2234. def numberRounding2a(n, significantDigits):
  2235.     """
  2236.    Rounds a string in the form of a string number
  2237.    (float or integer, negative or positive) to any number of
  2238.    significant digits. If an integer, there is no limitation on it's size.
  2239.    Safer to always have n be a string.
  2240.    """
  2241.     if isinstance(n, float) and significantDigits > 16:
  2242.         significantDigits = 16
  2243.     #import decimal
  2244.     #def d(x):
  2245.         #return decimal.Decimal(str(x))
  2246.     import decimal
  2247.     decimal.getcontext().prec = significantDigits
  2248.     s = str(d(n)/1)
  2249.     s = s.lstrip('0')
  2250.    
  2251.     return s
  2252.  
  2253. def sig_digits(n, d=6):
  2254.     """
  2255.    Return any real number n to d significant digits, in scientific notation.
  2256.    """
  2257.     return '%.*e' % (d-1, n)
  2258.  
  2259. def sig_digits2(n, d):
  2260.     """
  2261.    If abs(n) > 1 ten-thousandth (1/10000) or abs(n) < 1 trillion, returns n in ordinary, non-scientific notation. For other abs(n), returns n in scientific notation. All n's are returned to d significant digits.
  2262.    
  2263.    >>> sig_digits2(1234.5678, 3)
  2264.    '1,230'
  2265.    >>> sig_digits2(1234.5678, 6)
  2266.    '1,234.57'
  2267.    >>> sig_digits2(1234.5678 * 5555, 4)
  2268.    '6,858,000'
  2269.    >>> sig_digits2(12.345678 ** 55, 4)
  2270.    '1.080e+60'
  2271.    >>> sig_digits2(12.345678/555, 4)
  2272.    '0.02224'
  2273.    >>> sig_digits2(12.345678/-1234567890, 4)
  2274.    '-0.02224'
  2275.    >>> sig_digits2(22.345678/-123456, 4)
  2276.    '-0.0001810'
  2277.    >>> sig_digits2(22.345678/-1234567, 4)
  2278.    '-1.810e-05'
  2279.    """
  2280.     from mycalc import numberCommas
  2281.     orig_n = n
  2282.     if n < 0:
  2283.         sign = '-'
  2284.         n = abs(n)
  2285.     else:
  2286.         sign = ''
  2287.        
  2288.     # equivalent to applying my sig_digits(n, d)
  2289.     n = '%.*e' % (d-1, n)
  2290.    
  2291.     #Extract exp (exponent), with leading zeros stripped.
  2292.     #the [2] means the 3rd part of the 3-part partition, which is the exponent.
  2293.     #remember, n is always >= 0 (through use of abs() above.
  2294.     exp = n.partition('e')[2].lstrip('0')
  2295.     #handle case where exp is originally '00'; both zeros will be stripped.
  2296.     if exp == '':
  2297.         exp = '0'
  2298.    
  2299.     #if abs(n) <= 1 ten-thousandth (1/10000), returns n in scientific notation
  2300.     if int(exp) < -4:
  2301.         return sign + n
  2302.    
  2303.     # return an n where abs(n) >= 1 trillion in scientific notation
  2304.     elif int(exp) > 11:
  2305.         return sign + n
  2306.    
  2307.     if float(n) < 1:
  2308.         #remove the decimal point
  2309.         n = n.replace('.','')
  2310.         exp = n[n.find('e-')+2:].lstrip('0')
  2311.         return sign + '0.' + (int(exp)-1)*'0' + n.partition('e-')[0]
  2312.    
  2313.     elif float(n) >= 1:
  2314.         #remove the decimal point
  2315.         n = n.replace('.','')
  2316.        
  2317.         # the head is what is before the 'e' (my term)
  2318.         head = n.partition('e+')[0] #+ int(exp)*'0'
  2319.         n = head +(int(exp) - len(head) +1) * '0'
  2320.        
  2321.         #replace the decimal point
  2322.         n = n[:int(exp)+1] + '.' + n[int(exp)+1:]
  2323.        
  2324.         # remove decimal point if there is no fractional part of n
  2325.         if n[-1] == '.':
  2326.             n = n[:-1]
  2327.         return sign + numberCommas(n)
  2328.  
  2329. def getMinAndMaxIntegersFromUser(default_min, default_max):
  2330.     print("Enter 2 integers > 1 for min and max, with max >= min")
  2331.     print("Put a comma between the numbers. E.g., '8, 20'")
  2332.     print("Press Enter to set default of  %d, %d" % (default_min, default_max))
  2333.  
  2334.     while True:
  2335.         ans = input("min, max: ")
  2336.         if ans == '':
  2337.             print("The default min, max have been set to %d, %d\n" % (default_min, default_max))
  2338.             return (5, 20)
  2339.         try:
  2340.             min, max = ans.split(',')
  2341.         except ValueError:
  2342.             print("\nPlease start over and enter correct min and max.")
  2343.             print("Enter 2 integers > 1 for min and max, with max >= min")
  2344.             print("Press Enter to set default of  5, 20\n")
  2345.             continue
  2346.         try:
  2347.             min = int(min)
  2348.         except ValueError:
  2349.             print("\nPlease start over and enter correct min and max.")
  2350.             print("Enter 2 INTEGERS > 1 for min and max, with max >= min")
  2351.             print("Press Enter to set default of  5, 20\n")
  2352.             continue
  2353.         try:
  2354.             max = int(max)
  2355.         except ValueError:
  2356.             print("\nPlease start over and enter correct min and max.")
  2357.             print("Enter 2 INTEGERS > 1 for min and max, with max >= min")
  2358.             print("Press Enter to set default of  5, 20\n")
  2359.             continue
  2360.         if min > max or min < 2:
  2361.             print("\nPlease start over and enter correct min and max.")
  2362.             print("min must be <= max and min must be > 1")
  2363.             print("Enter 2 integers > 1 for min and max, with max >= min")
  2364.             print("Press Enter to set default of  5, 20\n")
  2365.             continue
  2366.         else:
  2367.             break
  2368.     return (min, max)
  2369.  
  2370. def group_num_to_group_name(group_num):
  2371.     """
  2372.    Function used only by intSpell
  2373.  
  2374.    Find American English illionName of group, given its illionNum.
  2375.    Example: illionName of group "345" (illionNum 2) in "111345666000" is "million"
  2376.    Reference: http://mathworld.wolfram.com/LargeNumber.html
  2377.    Reference: http://en.wikipedia.org/wiki/Nonillion#The_.22standard_dictionary_numbers.22
  2378.    """
  2379.     names = [ \
  2380.         "",
  2381.         " thousand,",
  2382.         " million,",
  2383.         " billion,",
  2384.         " trillion,",  
  2385.         " quadrillion,",        #5
  2386.         " quintillion,",
  2387.         " sextillion,",
  2388.         " septillion,",
  2389.         " octillion,",
  2390.         " nonillion,",           #10  
  2391.         " decillion,",
  2392.         " undecillion,",
  2393.         " duodecillion,",
  2394.         " tredecillion,",
  2395.         " quattuordecillion,",
  2396.         " quindecillion,",
  2397.         " sexdecillion,",
  2398.         " septendecillion,",
  2399.         " octodecillion,",
  2400.         " novemdecillion,",      #20
  2401.         " vigintillion,",
  2402.         " unvigintillion,",
  2403.         " duovigintillion,",
  2404.         " tresvigintillion,",
  2405.         " quattuorvigintillion",
  2406.         " quinquavigintillion",
  2407.         " sesvigintillion",
  2408.         " septemvigintillion",
  2409.         " octovigintillion",
  2410.         " novemvigintillion",    #30
  2411.         " trigintillion",
  2412.         " untrigintillion",
  2413.         " duotrigintillion",
  2414.         " trestrigintillion",
  2415.         " quattuortrigintillion",
  2416.         " quinquatrigintillion",
  2417.         " sestrigintillion",
  2418.         " septentrigintillion",
  2419.         " octotrigintillion",
  2420.         " novemtrigintillion",   #40
  2421.         " quadragintillion",
  2422.     ]
  2423.     group_name = names[group_num]
  2424.     return group_name
  2425.  
  2426.  
  2427. def stripZeros(group):
  2428.     """
  2429.    strip zeros at front of group, if any; or whole group if "000".
  2430.    E.g., 045 -> 45; 003 -> 3; 000 -> ''
  2431.    """
  2432.     if int(group) == 0:
  2433.         return ""
  2434.     return str(int(group))
  2435.  
  2436. #def isIntTooLarge(n): #TODO: delete this?
  2437.     #"""
  2438.     #Function used only by intSpell()
  2439.  
  2440.     #Largest n that can be spelled out is 10**66 - 1, or
  2441.     #999999999999999999999999999999999999999999999999999999999999999999
  2442.     #i.e., 999 vigintillion, 999 novemdecillion, 999 octodecillion,
  2443.     #999 septendecillion, 999 sexdecillion, 999 quindecillion,
  2444.     #999 quattuordecillion, 999 tredecillion, 999 duodecillion,
  2445.     #999 undecillion, 999 decillion, 999 nonillion, 999 octillion,
  2446.     #999 septillion, 999 sextillion, 999 quintillion, 999 quadrillion,
  2447.     #999 trillion, 999 billion, 999 million, 999 thousand, 999
  2448.  
  2449.     #There seem to be no more words for larger integers.
  2450.     #"""
  2451.     #if len(str(n)) > 66:
  2452.         #return True
  2453.     #else:
  2454.         #return False
  2455.  
  2456. def intSpell(n):
  2457.     """
  2458.    Returns spelling of any integer up to 126 digits in length.
  2459.  
  2460.    E.g. 1234567 -> 1 million, 234 thousand, 567
  2461.    """
  2462.     s = format(n, ',d')
  2463.     # no group names for n >= 10**126 (IOW, for a int of 128 digits or longer)
  2464.     if n >= 10**126:
  2465.         return s
  2466.     #handle s = 300 or 30 or 3, and have nothing to spell
  2467.     if "," not in s:
  2468.         return s
  2469.     # begin the creation of a list of the groups
  2470.     spelled_s = []
  2471.     #number of commas determines group_num of initial group
  2472.     initial_group_num = s.count(",")
  2473.     # employ group_num_to_group_name() function to get group_name (e.g., ' million,')
  2474.     initial_group_name = group_num_to_group_name(initial_group_num)
  2475.     # the ints of initial group are the characters up to the first comma of s, so need comma's index
  2476.     initial_group_ints = s[:s.find(",")]
  2477.     num_initial_group_ints = len(initial_group_ints)
  2478.     initial_group = initial_group_ints + initial_group_name
  2479.     spelled_s.append(initial_group)
  2480.     # the initial group having been determined, use the while loop to determine
  2481.     # the succeeding groups, all of which will have 3-digit group_ints
  2482.     group_num = initial_group_num
  2483.     count = -1
  2484.     while group_num >= 1:
  2485.         count += 1
  2486.         group_num -= 1
  2487.         group_name = group_num_to_group_name(group_num)
  2488.         group_ints = s[num_initial_group_ints+1+count*4:num_initial_group_ints+1+count*4+3]
  2489.         # when the group_ints are all zeros, skip processing it and continue on with the next
  2490.         if group_ints == "000":
  2491.             continue
  2492.         else:
  2493.             group_ints = group_ints.lstrip("0")
  2494.             group = group_ints + group_name
  2495.             spelled_s.append(group)
  2496.  
  2497.     spelled_s = ' '.join(spelled_s)
  2498.     # get rid of final comma in spelled_s such as "123 million, 456 thousand,"
  2499.     if spelled_s[-1] == ",":
  2500.         spelled_s = spelled_s[:-1]
  2501.     return spelled_s
  2502.  
  2503. def intFullSpell(n):  #TODO  output uses 2 commas for separator
  2504.     """
  2505.    Returns full spelling of an integer.
  2506.  
  2507.    E.g. 1234567 -> one million, two hundred thirty-four thousand, five hundred sixty-seven
  2508.    """
  2509.     s = format(n, ',d')
  2510.     list_of_group_ints = s.split(",")
  2511.     list_of_spelled_group_ints = []
  2512.     for gi in list_of_group_ints:
  2513.         list_of_spelled_group_ints.append(three_digit_int_spell(gi))
  2514.     num_groups = len(list_of_group_ints)
  2515.     spelled_s = []
  2516.     for i, group_int in enumerate(list_of_spelled_group_ints, 1):
  2517.         group_num = num_groups - i
  2518.         group_int = group_int.lstrip("0")
  2519.         if group_int == "":
  2520.             continue
  2521.         else:
  2522.             group_name = group_num_to_group_name(group_num)
  2523.             #group = group_int + " " + group_name + ","
  2524.             group = group_int + group_name
  2525.             spelled_s.append(group)
  2526.     spelled_s = ' '.join(spelled_s)
  2527.     spelled_s = spelled_s.rstrip(",' '")
  2528.     return spelled_s
  2529.  
  2530. def three_digit_int_spell(gi):
  2531.     """
  2532.    Used only by intFullSpell()
  2533.    """
  2534.  
  2535.     gi = str(gi)
  2536.  
  2537.     # if gi isn't a 3-digit int, prepend zeros to make it 3 digits
  2538.     while len(gi) < 3:
  2539.         gi = "0" + gi
  2540.     #print("gi =", gi)
  2541.  
  2542.     sd_lst = [ \
  2543.         "",
  2544.         "one",
  2545.         "two",
  2546.         "three",
  2547.         "four",
  2548.         "five",
  2549.         "six",
  2550.         "seven",
  2551.         "eight",
  2552.         "nine",
  2553.     ]
  2554.  
  2555.     hd_lst = sd_lst
  2556.  
  2557.     td_lst = [ \
  2558.         "",
  2559.         "twenty",
  2560.         "thirty",
  2561.         "forty",
  2562.         "fifty",
  2563.         "sixty",
  2564.         "seventy",
  2565.         "eighty",
  2566.         "ninety",
  2567.     ]
  2568.  
  2569.     teen_lst = [ \
  2570.         "",
  2571.         "ten",
  2572.         "eleven",
  2573.         "twelve",
  2574.         "thirteen",
  2575.         "fourteen",
  2576.         "fifteen",
  2577.         "sixteen",
  2578.         "seventeen",
  2579.         "eighteen",
  2580.         "nineteen",
  2581.     ]
  2582.  
  2583.     hd = gi[0]
  2584.     if gi[0] == "0":
  2585.         spelled_hd = ""
  2586.     elif gi[:2] == "00":
  2587.         return sd_lst[gi[2]]
  2588.     else:
  2589.         spelled_hd = hd_lst[int(hd)] + " hundred"
  2590.  
  2591.     td = gi[1]
  2592.     sd = gi[2]
  2593.     spelled_sd = sd_lst[int(sd)]
  2594.     if td == "1":
  2595.         sd = gi[2]
  2596.         spelled_dd = teen_lst[int(sd)+1] # "dd": double digit
  2597.         spelled_gi = spelled_hd + " " + spelled_dd
  2598.     elif int(td) > 1:
  2599.         spelled_td = td_lst[int(td)-1]
  2600.         spelled_sd = sd_lst[int(sd)]
  2601.         spelled_gi = spelled_hd + " " + spelled_td + "-" + spelled_sd
  2602.     elif td == "0":
  2603.         spelled_gi = spelled_hd + " " + spelled_sd
  2604.     spelled_gi = spelled_gi.lstrip(" ")
  2605.     spelled_gi = spelled_gi.rstrip("-")
  2606.     return spelled_gi
  2607.  
  2608. def secsToHMS(seconds):
  2609.     """
  2610.    Convert seconds to hours:minutes:seconds, with seconds rounded to hundredths of a second.
  2611.    """
  2612.     minutes, seconds = divmod(seconds, 60)
  2613.     hours, minutes = divmod(minutes, 60)
  2614.     return "%02d:%02d:%05.2f" % (hours, minutes, seconds)
  2615.  
  2616. def hms(seconds):
  2617.     """
  2618.    Convert seconds to tuple (hours, minutes, seconds)
  2619.    """
  2620.     hours, minutes = 0, 0
  2621.  
  2622.     if seconds >= 60 and seconds < 3600:
  2623.         minutes, seconds = divmod(seconds, 60)
  2624.     elif seconds >= 3600:
  2625.         hours, seconds = divmod(seconds, 3600)
  2626.         minutes, seconds = divmod(seconds, 60)
  2627.  
  2628.     return hours, minutes, seconds
  2629.  
  2630. def print_hms(seconds):
  2631.     """
  2632.    Convert seconds to hours, minutes, seconds and print result
  2633.    """
  2634.     seconds = floatToNearestInt(seconds)
  2635.     hours, minutes = 0, 0
  2636.  
  2637.     if seconds >= 60 and seconds < 3600:
  2638.         minutes, seconds = divmod(seconds, 60)
  2639.     elif seconds >= 3600:
  2640.         hours, seconds = divmod(seconds, 3600)
  2641.         minutes, seconds = divmod(seconds, 60)
  2642.  
  2643.     hp, mp, sp = "s", "s", "s" # add "s" to make "hour", "minute", "second" plural
  2644.     if hours == 1:
  2645.         hp = "" # no "s" on "hour"
  2646.     if minutes == 1:
  2647.         mp = ""
  2648.     if seconds >= 1 and seconds < 2:
  2649.         sp = ""
  2650.  
  2651.     if hours == 0 and minutes == 0:
  2652.         print("%d second%s" % (seconds, sp))
  2653.     elif hours == 0:
  2654.         if seconds == 0:
  2655.             print("%d minute%s exactly" % (minutes, mp))
  2656.         else:
  2657.             print("%d minute%s, %d second%s" % (minutes, mp, seconds, sp))
  2658.  
  2659.     elif minutes == 0:
  2660.         if seconds == 0:
  2661.             print("%d hour%s exactly" % (hours, hp))
  2662.         else:
  2663.             print("%d hour%s, %d second%s" % (hours, hp, seconds, sp))
  2664.     else:
  2665.         print("%d hour%s, %d minute%s, %d second%s" % (hours, hp, minutes, mp, seconds, sp))
  2666.  
  2667. def hmsToText(seconds):
  2668.     """
  2669.    Convert seconds to hours, minutes, seconds and return result
  2670.    """
  2671.     seconds = floatToNearestInt(seconds)
  2672.     hours, minutes = 0, 0
  2673.  
  2674.     if seconds >= 60 and seconds < 3600:
  2675.         minutes, seconds = divmod(seconds, 60)
  2676.     elif seconds >= 3600:
  2677.         hours, seconds = divmod(seconds, 3600)
  2678.         minutes, seconds = divmod(seconds, 60)
  2679.  
  2680.     hp, mp, sp = "s", "s", "s" # add "s" to make "hour", "minute", "second" plural
  2681.     if hours == 1:
  2682.         hp = "" # no "s" on "hour"
  2683.     if minutes == 1:
  2684.         mp = ""
  2685.     if seconds >= 1 and seconds < 2:
  2686.         sp = ""
  2687.  
  2688.     if hours == 0 and minutes == 0:
  2689.         result = "%d second%s" % (seconds, sp)
  2690.     elif hours == 0:
  2691.         if seconds == 0:
  2692.             result = "%d minute%s exactly" % (minutes, mp)
  2693.         else:
  2694.             result = "%d minute%s, %d second%s" % (minutes, mp, seconds, sp)
  2695.     elif minutes == 0:
  2696.         if seconds == 0:
  2697.             result = "%d hour%s exactly" % (hours, hp)
  2698.         else:
  2699.             result = "%d hour%s, %d second%s" % (hours, hp, seconds, sp)
  2700.     else:
  2701.         result = "%d hour%s, %d minute%s, %d second%s" % (hours, hp, minutes, mp, seconds, sp)
  2702.     return result
  2703.  
  2704. def iter_primes():
  2705.     """
  2706.    an iterator of all prime numbers between 2 and +infinity
  2707.    """
  2708.     import itertools
  2709.     numbers = itertools.count(2)
  2710.  
  2711.     # generate primes forever
  2712.     while True:
  2713.         # get the first number from the iterator (always a prime)
  2714.         prime = next(numbers)
  2715.         yield prime
  2716.  
  2717.         # remove all numbers from the (infinite) iterator that are
  2718.         # divisible by the prime we just generated
  2719.         numbers = filter(prime.__rmod__, numbers)
  2720.  
  2721.  
  2722. def primeList(n):
  2723.     """
  2724.    Returns list of all primes in closed interval [2,n].
  2725.    psyco will greatly increase speed.
  2726.    """
  2727.     import math
  2728.     if n == 2:
  2729.         return [2]
  2730.     primes=[3]
  2731.     for x in range(5,n+1,2):
  2732.         maxfact = math.sqrt(x)
  2733.         for y in primes:
  2734.             if y > maxfact:
  2735.                 primes.append(x)
  2736.                 break
  2737.             if not x%y:
  2738.                 break
  2739.     primes = [2] + primes
  2740.     return primes
  2741.  
  2742. def nextPrime(n):
  2743.     """
  2744.    Return the first prime >= n.
  2745.    """
  2746.     x = n
  2747.     if x % 2 == 0:
  2748.         x += 1
  2749.     while True:
  2750.         if isPrime(x):
  2751.             p = x
  2752.             return p
  2753.         x += 2
  2754.  
  2755. def nextLargerPrime(n):
  2756.     """
  2757.    Return the first prime >= n.
  2758.    """
  2759.     x = n
  2760.     if x % 2 == 0:
  2761.         x += 1
  2762.     while True:
  2763.         if isPrime(x):
  2764.             p = x
  2765.             return p
  2766.         x += 2
  2767.  
  2768. def nextSmallerPrime(n):
  2769.     """
  2770.    Return the first prime <= n (n >= 2).
  2771.    """
  2772.     x = n
  2773.     if x != 2 and x % 2 == 0:
  2774.         x -= 1
  2775.     while True:
  2776.         if isPrime(x):
  2777.             p = x
  2778.             return p
  2779.         x -= 2
  2780.  
  2781. def nearestPrime(n):
  2782.     """
  2783.    Return the nearest prime to n, or if n is prime, return n.
  2784.    In case of ties, return the smaller.
  2785.  
  2786.    Thus if n = 17 return 17; if 16 return 17; if 14 return 13;
  2787.    if n = 15 return 13 (not 17)
  2788.    """
  2789.     x = n
  2790.     if x % 2 == 0:
  2791.         x += 1
  2792.     y = x - 2
  2793.     while True:
  2794.         if isPrime(x):
  2795.             return x
  2796.         if isPrime(y):
  2797.             return y
  2798.         x += 2
  2799.         y -= 2
  2800.  
  2801. def nearestPrimes(n, num_of_primes):
  2802.     """
  2803.    Return list of num_of_primes nearest primes to integer n; if n is prime, list will include n.
  2804.  
  2805.    List will include the prime 2 if appropriate, but no "prime" < 2.
  2806.    """
  2807.     primes = []
  2808.     count = 0
  2809.     lx = n  #for ints >= n  (l for larger)
  2810.     if lx == 2:
  2811.         primes.append(2)
  2812.         count += 1
  2813.         lx = 3
  2814.     elif lx % 2 == 0:
  2815.         lx += 1
  2816.     sx = lx - 2  #for ints < n  (s for smaller)
  2817.  
  2818.     while count < num_of_primes:
  2819.         if isPrime(lx):
  2820.             primes.append(lx)
  2821.             count += 1
  2822.         lx += 2
  2823.         if sx >= 2:
  2824.             if isPrime(sx):
  2825.                 primes.append(sx)
  2826.                 count += 1
  2827.         if sx == 3:
  2828.             sx = 2
  2829.         else:
  2830.             sx -= 2
  2831.     primes.sort()
  2832.     return primes
  2833.  
  2834. def nextNPrimes(m,n=1):
  2835.     """
  2836.    Return list of n primes >= m and smaller than any other primes
  2837.    """
  2838.     count = 0
  2839.     primes = []
  2840.     if m % 2 == 0:
  2841.         m += 1
  2842.     while count < n:
  2843.         if isPrime(m):
  2844.             primes.append(m)
  2845.             count += 1
  2846.         m += 2
  2847.     return primes
  2848.  
  2849. def nextNLargerPrimes(m,n=1):
  2850.     """
  2851.    Return list of first n primes >= m
  2852.    """
  2853.     count = 0
  2854.     primes = []
  2855.     if m % 2 == 0:
  2856.         m += 1
  2857.     while count < n:
  2858.         if isPrime(m):
  2859.             primes.append(m)
  2860.             count += 1
  2861.         m += 2
  2862.     return primes
  2863.  
  2864. def nextNSmallerPrimes(m,n=1):
  2865.     """
  2866.    Return list of n, or less than n primes that are the largest primes < m
  2867.  
  2868.    For example, if m = 8, there are only 4 primes less than 8 (7, 5, 3 and 2)
  2869.    """
  2870.     x = m
  2871.     count = 0
  2872.     primes = []
  2873.     if x <= 1:
  2874.         return []
  2875.     if x == 2:
  2876.         return [2]
  2877.     if x % 2 == 0:
  2878.         x -= 1
  2879.     while count < n:
  2880.         if x > 3:
  2881.             if isPrime(x):
  2882.                 primes.append(x)
  2883.                 count += 1
  2884.             x -= 2
  2885.         elif x == 3:
  2886.             primes.append(3)
  2887.             count += 1
  2888.             x -= 1
  2889.         elif x == 2:
  2890.             primes.append(2)
  2891.             return primes
  2892.  
  2893.     return primes
  2894.  
  2895. def maxDiffBetPrimes(n):
  2896.     """
  2897.    Prints max diff between primes that are in interval [2,n],
  2898.    and also prints those pairs of primes.
  2899.    """
  2900.     from mycalc import primeList
  2901.     primes = primeList(n)
  2902.     maxDiff = 1
  2903.     pairs = []
  2904.     for i in range(len(primes)-1):
  2905.         diff = primes[i+1] - primes[i]
  2906.         #pairs.append((primes[i], primes[i+1]))
  2907.         if diff == maxDiff:
  2908.             pairs.append((primes[i], primes[i+1]))
  2909.  
  2910.         if diff > maxDiff:
  2911.             pairs = []
  2912.             pairs.append((primes[i], primes[i+1]))
  2913.             maxDiff = diff
  2914.  
  2915.     print("For primes up through %d, max diff is %d" % (n, maxDiff))
  2916.     print("between the %d pair(s) of primes %s" % (len(pairs),pairs))
  2917.  
  2918. def maxAndMinDiffBetPrimes(n,m):  #TODO
  2919.     """
  2920.    Prints max diff and min diff between consecutive primes that are in
  2921.    closed interval [n,m], and prints those pairs of primes. If the min diff is
  2922.    2, also prints the percentage of the pairs that differ by 2.
  2923.    """
  2924.     from mycalc import primesNToM, numberCommas, intSpell
  2925.     primes = primesNToM(n,m)
  2926.     maxDiff = 1
  2927.     minDiff = 1000000000
  2928.     pairsMax = []
  2929.     pairsMin = []
  2930.     for i in range(len(primes)-1):
  2931.         diff = primes[i+1] - primes[i]
  2932.         #pairs.append((primes[i], primes[i+1]))
  2933.         if diff == maxDiff:
  2934.             pairsMax.append((primes[i], primes[i+1]))
  2935.         if diff == minDiff:
  2936.             pairsMin.append((primes[i], primes[i+1]))
  2937.  
  2938.  
  2939.         if diff > maxDiff:
  2940.             pairsMax = []
  2941.             pairsMax.append((primes[i], primes[i+1]))
  2942.             maxDiff = diff
  2943.         if diff < minDiff:
  2944.             pairsMin = []
  2945.             pairsMin.append((primes[i], primes[i+1]))
  2946.             minDiff = diff
  2947.  
  2948.     if n >= 1000000000:
  2949.         print("n = %s (%s)" % (numberCommas(n), intSpell(n)))
  2950.         print("m = %s (%s)" % (numberCommas(m), intSpell(m)))
  2951.     else:
  2952.         print("n = %s" % numberCommas(n))
  2953.         print("m = %s" % numberCommas(m))
  2954.     percent = len(primes)*100.0/(m-n+1)
  2955.     print("%d/%d (%.4g percent) of the integers in [n,m] are prime." % (len(primes), (m-n+1), percent))
  2956.     print()
  2957.     print("The %d primes in closed interval [n,m] are %s" % (len(primes), primes))
  2958.     print("The max diff between consecutive primes is %d," % maxDiff)
  2959.     print("between the %d pair(s) of primes %s" % (len(pairsMax),pairsMax))
  2960.     print()
  2961.     print("The min diff between consecutive primes is %d," % minDiff)
  2962.     print("between the %d pair(s) of primes %s" % (len(pairsMin),pairsMin))
  2963.     if minDiff == 2:
  2964.         percent = len(pairsMin)*100.0/(len(primes)-1)
  2965.         print("%d of the %d pairs (%.4g percent) differ by 2" % (len(pairsMin), len(primes)-1, percent))
  2966.  
  2967. def isPrime(n):
  2968.     """
  2969.    Return True if n is prime, False if not prime.
  2970.    """
  2971.     #import gmpy2
  2972.     #from gmpy2 import is_prime
  2973.     if not isinstance(n, int):
  2974.         raise TypeError("The argument to isPrime() must be an int.")
  2975.     x = gmpy2.is_prime(n, 25)
  2976.     return x != False
  2977.  
  2978. def primesNtoM(n, m):
  2979.     """
  2980.    returns the list of all primes in closed interval [n,m]
  2981.  
  2982.    assumes n <= m
  2983.    n may be < 0 or both n and m may be < 0
  2984.    """
  2985.     primes = []
  2986.     if m < 2:
  2987.         return []
  2988.     if n <= 2 and m >= 2:
  2989.         primes.append(2)
  2990.         n = 3
  2991.     elif n % 2 == 0:
  2992.         n += 1
  2993.     for x in range(n, m + 1, 2):
  2994.         if isPrime(x):
  2995.             primes.append(x)
  2996.     return primes
  2997.  
  2998. def primesNtoM2a(n, m):
  2999.     """
  3000.    Returns the list of all primes in closed interval [n,m]
  3001.    
  3002.    primesNtoM2a() is faster than primesNtoM2b() up to ~500 trillion, and
  3003.    """
  3004.     from gmpy import next_prime
  3005.    
  3006.     p = int(next_prime(n-1))
  3007.     primes = []
  3008.     primes.append(p)
  3009.     prev_p = p
  3010.     while True:
  3011.         p = int(next_prime(prev_p))
  3012.         if p > m:
  3013.             return primes
  3014.         primes.append(p)
  3015.         prev_p = p
  3016.        
  3017. def primesNtoM2b(n, m):
  3018.     """
  3019.    Returns the list of all primes in closed interval [n,m]
  3020.    """
  3021.     from gmpy2 import next_prime
  3022.    
  3023.     p = int(next_prime(n-1))
  3024.     primes = []
  3025.     primes.append(p)
  3026.     prev_p = p
  3027.     while True:
  3028.         p = int(next_prime(prev_p))
  3029.         if p > m:
  3030.             return primes
  3031.         primes.append(p)
  3032.         prev_p = p
  3033.  
  3034. def primesToN(n):
  3035.     """
  3036.    Return list of primes in closed interval [2,n]
  3037.    Note: find_primes() is about 10X faster
  3038.    """
  3039.     primes = [2]
  3040.     x = 3
  3041.     while x < n + 1:
  3042.         if isPrime(x):
  3043.             primes.append(x)
  3044.         x += 2
  3045.     return primes
  3046.  
  3047.  
  3048. def find_primes(n):
  3049.     """
  3050.    Return list of primes in closed interval [2,n]
  3051.    Note: find_primes() is about 10X faster than primesToN()
  3052.    """
  3053.     # from a post by bluemoo for #187 in Project Euler.
  3054.     # a very fast algorithm.
  3055.     # see http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
  3056.     from math import sqrt
  3057.     if n < 2:
  3058.         return []
  3059.     if n == 2:
  3060.         return [2]
  3061.     # do only odd numbers starting at 3
  3062.     s = list(range(3, n, 2))
  3063.     # n**0.5 may be slightly faster than math.sqrt(n)
  3064.     mroot = sqrt(n)
  3065.     half = len(s)
  3066.     i = 0
  3067.     m = 3
  3068.     while m <= mroot:
  3069.         if s[i]:
  3070.             j = (m * m - 3)//2
  3071.             s[j] = 0
  3072.             while j < half:
  3073.                 s[j] = 0
  3074.                 j += m
  3075.         i = i + 1
  3076.         m = 2 * i + 3
  3077.     # make exception for 2
  3078.     return [2]+[x for x in s if x]
  3079.  
  3080. def poi(lmda, k):
  3081.     """
  3082.    Poisson distribution. Returns probability of exactly k occurrences given lmda
  3083.  
  3084.    See http://en.wikipedia.org/wiki/Poisson_distribution
  3085.    Examples of lmdas:
  3086.    The number of soldiers killed by horse-kicks each year in each corps in the Prussian cavalry.
  3087.    The number of phone calls at a call center per minute.
  3088.    The number of times a web server is accessed per minute.
  3089.    The number of mutations in a given stretch of DNA after a certain amount of radiation.
  3090.    >>> poi(3.7, 4)
  3091.    0.19306612122157396
  3092.    >>> poi(10,4)
  3093.    0.018916637401035365
  3094.    """
  3095.     from math import e, factorial
  3096.     #if int(k) != k:
  3097.         #print k, "is not an integer"
  3098.     if not isinstance(k, int):
  3099.         raise TypeError("WTF you didn't pass me an int")
  3100.     p = (e**(-lmda)*(lmda**k))/factorial(k)
  3101.     return p
  3102.  
  3103. def poi_for_range_of_k(lmda, begin, end):
  3104.     """
  3105.    Returns probability of range of k occurrences given lmda.
  3106.  
  3107.    Example: for lmbda of 6.5, and k's of 3,4,5
  3108.    poi_for_range_of_k(6.5, 3, 5) = poi(6, 3) + poi(6, 4) + poi(6, 5) = 0.383710836948
  3109.    """
  3110.     p = 0
  3111.     for k in range(begin, end+1):
  3112.         p += poi(lmda, k)
  3113.     return p
  3114.  
  3115. def poiAtMost(lmda, k):
  3116.     """
  3117.    Poisson distribution. Returns probability of at most k occurrences given lmda.
  3118.  
  3119.    >>> poiAtMost(3.7, 4)
  3120.    0.6872193653719925
  3121.    """
  3122.     p = 0
  3123.     for k in range(k + 1):
  3124.         p += poi(lmda, k)
  3125.     return p
  3126.  
  3127. def poiAtLeast(lmda, k):
  3128.     """
  3129.    Poisson distribution. Returns probability of at least k occurrences given lmda.
  3130.  
  3131.    >>> poiAtLeast(3.7, 5)
  3132.    0.31278063462800754
  3133.    """
  3134.     return 1 - poiAtMost(lmda, k - 1)
  3135.  
  3136. def poiInterval(lmda, kMin, kMax):
  3137.     """
  3138.    Returns sum of probabilities of k occurrences for all kMin <= k <= kMax, given lmda.
  3139.  
  3140.    >>> poiInterval(3.7,0,4)
  3141.    0.6872193653719925
  3142.    >>> poiInterval(3.7,6,10)
  3143.    0.16833952392312523
  3144.    """
  3145.     p = 0
  3146.     for k in range(kMin, kMax + 1):
  3147.         p += poi(lmda, k)
  3148.     return p
  3149.  
  3150. def avg(sequence_):
  3151.     from math import fsum
  3152.     from fractions import Fraction
  3153.     return fsum(sequence_) * Fraction(1, len(sequence_))
  3154.  
  3155. def median(list_):
  3156.     """
  3157.    Returns the median of list_.
  3158.    In order to preserve the original order of list_,
  3159.    first makes a copy (tmp) of list_, and computes on the copy.
  3160.    """
  3161.     tmp = list_[:] # make a copy of list_ and then sort the copy
  3162.     tmp.sort()
  3163.     half = len(tmp) // 2
  3164.     if (len(tmp)%2)==1:
  3165.         return tmp[half]
  3166.     else:
  3167.         return sum(tmp[half-1:half+1])/2
  3168.  
  3169.  
  3170. def compareSequences(seq1, seq2):
  3171.     """
  3172.    Returns first index at which two sequences differ. If one is longer than the other,
  3173.    ignores the elements of the longer for which there are no corresponding elements in the shorter.
  3174.    The 2 sequences can be of different types.
  3175.  
  3176.    >>> a = "Now is the time"
  3177.    >>> b = "Now was the time"
  3178.    >>> compareSequences(a, b)
  3179.    4
  3180.    >>> a = '125477'
  3181.    >>> b = ['1','2','3','4']
  3182.    >>> compareSequences(a, b)
  3183.    >>> 2
  3184.    >>> b = ('1','2','3','4')
  3185.    >>> compareSequences(a, b)
  3186.    >>> 2
  3187.    >>> a = 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
  3188.    >>> b = 'zzzzzzzzzzzzz+zzzzzzzzzzzzzzzzzzzzzzzzzzz'
  3189.    >>> compareSequences(a, b)
  3190.    >>> 13
  3191.    >>> b = 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
  3192.    >>> compareSequences(a, b)
  3193.    >>> None
  3194.    >>> a
  3195.    >>> 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
  3196.    >>> b
  3197.    >>> 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
  3198.    """
  3199.     if len(seq2) > len(seq1):
  3200.         seq1, seq2 = seq2, seq1
  3201.     for index in range(0, len(seq2)):
  3202.         if seq1[index] != seq2[index]:
  3203.             return index
  3204.        
  3205. def comp_seqs_and_mark(str1, str2):
  3206.     """
  3207.    Prints 3 lines: str1, a line with only a '|' marker, and str2.
  3208.    If strings are identical up to end of shorter one, only the strings are printed.
  3209.    
  3210.    >>> a = 'Now is the time'
  3211.    >>> b = 'Now is our time'
  3212.    >>> comp_seqs_and_mark(a, b)
  3213.    Now is the time
  3214.           |
  3215.    Now is our time
  3216.    >>> a = '1.2345'
  3217.    >>> b = '1.2345678'
  3218.    >>> comp_seqs_and_mark(a, b)
  3219.    1.2345
  3220.    1.2345678
  3221.    >>> a = '1.23457777777777777777777777777777777777777777777777777777777777777777777'
  3222.    >>> b = '1.2345777777777777777777707777777777777777777777777777777777777777'
  3223.    >>> comp_seqs_and_mark(a, b)
  3224.    1.23457777777777777777777777777777777777777777777777777777777777777788777
  3225.                             |
  3226.    1.2345777777777777777777707777777777777777777777777777777777777777
  3227.    """
  3228.     reversed_flag = None
  3229.     if len(str2) > len(str1):
  3230.         str1, str2 = str2, str1
  3231.         print(str2)
  3232.         reversed_flag = True
  3233.     else:
  3234.         print(str1)
  3235.     for index in range(0,len(str2)):
  3236.         if str1[index] != str2[index]:
  3237.             if index == 0:
  3238.                 print('|')
  3239.                 break
  3240.             elif index > 0:
  3241.                 print((index-1)*' ', '|')
  3242.                 break
  3243.             else:
  3244.                 print('BUG')
  3245.                
  3246.     if reversed_flag == True:
  3247.         print(str1)
  3248.     else:
  3249.         print(str2)
  3250.  
  3251. #def comp_seqs_and_mark(str1, str2):
  3252.     #reversed_flag = None
  3253.     #if len(str2) > len(str1):
  3254.         #str1, str2 = str2, str1
  3255.         #print(str2, label2)
  3256.         #reversed_flag = True
  3257.     #else:
  3258.         #print(str1)
  3259.     #for index in range(0,len(str2)):
  3260.         #if str1[index] != str2[index]:
  3261.             #if index == 0:
  3262.                 #print('|')
  3263.                 #break
  3264.             #elif index > 0:
  3265.                 #print((index-1)*' ', '|')
  3266.                 #break
  3267.             #else:
  3268.                 #print('BUG')
  3269.     #if reversed_flag:
  3270.         #print(str1)
  3271.     #else:
  3272.         #print(str2)
  3273.  
  3274. def cmpSeq(seq1, seq2):
  3275.     """
  3276.    find first index at which two sequences differ
  3277.    """
  3278.     if seq1 == seq2:
  3279.         print("Sequences are identical, and of length %d" % len(seq1))
  3280.         return None
  3281.     if len(seq1) >= len(seq2):
  3282.         shorterOrEqualSequence = seq2
  3283.     else:
  3284.         shorterOrEqualSequence = seq1
  3285.  
  3286.     for index in range(len(shorterOrEqualSequence)):
  3287.         if seq1[index] != seq2[index]:
  3288.             print("sequences first differ at index", index)
  3289.             print("seq1[%d] = %s" % (index, seq1[index]))
  3290.             print("seq2[%d] = %s" % (index, seq2[index]))
  3291.             break
  3292.  
  3293.     if index == len(shorterOrEqualSequence)-1:
  3294.         print("sequences are identical thru end of shorter sequence at index", index)
  3295.  
  3296.     print("len(seq1) =", len(seq1))
  3297.     print("len(seq2) =", len(seq2))
  3298.  
  3299. def ordSuff(n):
  3300.     """
  3301.    returns suffix for ordinal integer n; e.g. 1237 -> 1237th
  3302.    """
  3303.     n = str(n)
  3304.     if n[-1] in "0456789":
  3305.         suff = "th"
  3306.     elif n[-2:] in ['11', '12', '13']:
  3307.         suff = "th"
  3308.     elif n[-1] == "1":
  3309.         suff = "st"
  3310.     elif n[-1] == "2":
  3311.         suff = "nd"
  3312.     else:
  3313.         suff = "rd"
  3314.     return suff
  3315.  
  3316. def int_to_ordinal(n):
  3317.     """
  3318.    Takes an int and returns the string ordinal integer, with commas as appropriate
  3319.    plus the appropriate suffix; e.g. 1237 -> 1,237th
  3320.    """
  3321.     n = str(n)
  3322.     if n[-1] in "0456789":
  3323.         suff = "th"
  3324.     elif n[-2:] in ['11', '12', '13']:
  3325.         suff = "th"
  3326.     elif n[-1] == "1":
  3327.         suff = "st"
  3328.     elif n[-1] == "2":
  3329.         suff = "nd"
  3330.     else:
  3331.         suff = "rd"
  3332.     return intCommas(n) + suff
  3333.  
  3334. def intCommas(n):
  3335.     """
  3336.    inserts commas into integers. E.g. -12345678 -> -12,345,789
  3337.    """
  3338.     s = str(n)
  3339.     sign = ''
  3340.     if s[0] == '-':
  3341.         sign = '-'
  3342.         s = s[1:]
  3343.     slen = len(s)
  3344.     a = ''
  3345.     for index in range(slen):
  3346.         if index > 0 and index % 3 == slen % 3:
  3347.             a = a + ','
  3348.         a = a + s[index]
  3349.     return sign + a
  3350.  
  3351. #TODO
  3352.  
  3353. def numberCommas(n):
  3354.     """
  3355.    Inserts commas into integers, or into the integer part of floats.
  3356.    (If for integers only, can use my function, intCommas().)
  3357.    Returns a string
  3358.    """
  3359.     def handle_minus(n):
  3360.         n = str(n)
  3361.         if n[0] == "-":
  3362.             n = n[1:]
  3363.             minus = "-"
  3364.         else:
  3365.             minus = ""
  3366.         return n, minus
  3367.  
  3368.     n, minus = handle_minus(n)
  3369.     n = n.lstrip("0") # E.g 00123->123 and 00034.4500->34.4500
  3370.     if "." in n:
  3371.         n = n.split(".")
  3372.         return minus + intCommas(n[0]) + "." + n[1]
  3373.     else:
  3374.         return minus + intCommas(n)
  3375.  
  3376. def stripZeroes(number):
  3377.     """
  3378.    Strips trailing zeroes in fraction part of a float converted to a string.
  3379.    This is not easily done with rstrip().
  3380.    """
  3381.     number = str(number)
  3382.     if "." in number:
  3383.         while number[-1] in ".0":
  3384.             number = number[:-1]
  3385.     return number # as string
  3386.  
  3387. def flatten(seq):
  3388.     """
  3389.    example of sequence to flatten: [1,2,3,4,[5,6,'seven',8,(9,10,11)]]
  3390.    output: [1, 2, 3, 4, 5, 6, 'seven', 8, 9, 10, 11]
  3391.    from http://aspn.activestate.com/ASPN/Mail/Message/python-list/453883
  3392.    """
  3393.     from types import TupleType, ListType
  3394.     res = []
  3395.     for item in seq:
  3396.         if type(item) in (TupleType, ListType):
  3397.             res.extend(flatten(item))
  3398.         else:
  3399.             res.append(item)
  3400.     return res
  3401.  
  3402. #def beep():  #doesn't work in Vista
  3403.     #"""A very short Beep"""
  3404.     #import winsound
  3405.     #pitch = 500
  3406.     #length = 30
  3407.     #winsound.Beep(pitch,length)
  3408.  
  3409. def beep():  
  3410.     """A very short bop sound"""
  3411.     import winsound
  3412.     winsound.PlaySound("/P31Working/Sounds/beat", winsound.SND_ALIAS)
  3413.  
  3414. def beepN(times,interval):
  3415.     """Calls beep() n times at interval of x seconds."""
  3416.     import time
  3417.     for k in range(times-1):
  3418.         beep()
  3419.         time.sleep(interval)
  3420.     beep()
  3421.  
  3422. def tadaa():
  3423.     """a Ta Daa! sound"""
  3424.     import winsound
  3425.     winsound.PlaySound("/P31Working/Sounds/TaDa", winsound.SND_ALIAS)
  3426.  
  3427. #def beethoven(): #doesn't work in Vista
  3428.     #"""
  3429.     #The first notes of his 5th symphony.
  3430.     #"""
  3431.     #import time, winsound
  3432.     #seconds = .03
  3433.     #pitch = 490
  3434.     #length = 200
  3435.     #winsound.Beep(pitch,length)
  3436.     #time.sleep(seconds)
  3437.     #winsound.Beep(pitch,length)
  3438.     #time.sleep(seconds)
  3439.     #winsound.Beep(pitch,length)
  3440.  
  3441.     #time.sleep(.05)
  3442.     #winsound.Beep(400,900)
  3443.     #time.sleep(.8)
  3444.     #winsound.MessageBeep()
  3445.  
  3446. def beethoven():
  3447.     """
  3448.    A clip of the first notes of his 5th symphony.
  3449.    """
  3450.     import winsound
  3451.     winsound.PlaySound("/P31Working/Sounds/DaDaDaDaaa", winsound.SND_ALIAS)
  3452.  
  3453.  
  3454. def add():
  3455.     x = "0"
  3456.     sum = 0
  3457.     while True:
  3458.         x = input("enter a number to add: ")
  3459.         if x == "":
  3460.             break
  3461.         if "," in x:
  3462.             x = x.replace(",","")
  3463.         if "." in x:
  3464.             x = float(x)
  3465.         else:
  3466.             x = int(x)
  3467.         sum += x
  3468.     print(numberCommas(sum))
  3469.  
  3470. def mult():
  3471.     x = "0"
  3472.     product = 1
  3473.     while True:
  3474.         x = input("enter a number to multiply: ")
  3475.         if x == "":
  3476.             break
  3477.         if "," in x:
  3478.             x = x.replace(",","")
  3479.         if "." in x:
  3480.             x = float(x)
  3481.         else:
  3482.             x = int(x)
  3483.         product *= x
  3484.     print(numberCommas(product))
  3485.  
  3486. def div():
  3487.     x = "0"
  3488.     y = "0"
  3489.     x = input("enter a number to be divided: ")
  3490.     if "," in x:
  3491.         x = x.replace(",","")
  3492.     if "." in x:
  3493.         x = float(x)
  3494.     else:
  3495.         x = int(x)
  3496.  
  3497.     y = input("enter the divisor: ")
  3498.     if "," in y:
  3499.         y = y.replace(",","")
  3500.     if "." in y:
  3501.         y = float(y)
  3502.     else:
  3503.         y = int(y)
  3504.     print("%.17g" % (x*1.0/y))
  3505.  
  3506. def tdstelecomer():
  3507.     print("using math.pow()")
  3508.     import math
  3509.     x = "0"
  3510.     y = "0"
  3511.  
  3512.     x = input("enter a number to raise to a power: ")
  3513.     if "," in x:
  3514.         x = x.replace(",","")
  3515.     if "." in x:
  3516.         x = float(x)
  3517.     else:
  3518.         x = int(x)
  3519.  
  3520.     y = input("enter the exponent: ")
  3521.     if "," in y:
  3522.         y = y.replace(",","")
  3523.     if "." in y:
  3524.         y = float(y)
  3525.     else:
  3526.         y = int(y)
  3527.     print("%.17g" % math.pow(x,y))
  3528.  
  3529. def decPow(n, power, precision=4):
  3530.     """
  3531.    Raise any real number to any power to any precision
  3532.  
  3533.    If power is negative, must be an integer.
  3534.    If n is negative, power must be an integer
  3535.    """
  3536.     from decimal import getcontext, Decimal as D
  3537.     getcontext().prec = precision
  3538.     return D(str(n))**D(str(power))
  3539.  
  3540. def stripCommas(s):
  3541.     """Strips commas from a string"""
  3542.     a = s.split(",")
  3543.     s = ''.join(a)
  3544.     return s
  3545.  
  3546. def fact(n, d=0):
  3547.     """
  3548.    Returns n! to d significant digits
  3549.    Set digits to 0 to return the full n! integer. I.e, use fact(n,0) or fact(n).
  3550.    """
  3551.     import gmpy2
  3552.     from mycalc import sig_digits
  3553.  
  3554.     if d == 0:
  3555.         return int(gmpy2.fac(n))
  3556.     elif d > 0:
  3557.         return float(sig_digits(gmpy2.fac(n),d))
  3558.  
  3559. def print_fact(n):
  3560.     from mycalc import intCommas, sci_notation
  3561.     import gmpy2
  3562.     m = int(gmpy2.fac(n))
  3563.     print("%d! = %s" % (n, intCommas(m)))
  3564.     print("=", sci_notation(m, 4))
  3565.  
  3566. def printTime(timeStart, timeEnd):
  3567.     from mycalc import hmsToText
  3568.     timeElapsed = timeEnd - timeStart
  3569.     if timeElapsed > 60:
  3570.         print("Time was", hmsToText(timeElapsed))
  3571.     else:
  3572.         print("Time was %.4g seconds" % timeElapsed)
  3573.  
  3574. def get_time(timeStart, timeEnd):
  3575.     from mycalc import hmsToText
  3576.     timeElapsed = timeEnd - timeStart
  3577.     if timeElapsed > 60:
  3578.         return "Time was", hmsToText(timeElapsed)
  3579.     else:
  3580.         return "Time was %.4g seconds" % timeElapsed
  3581.  
  3582.  
  3583. if __name__ == '__main__':
  3584.     import time
  3585.     assert(numberCommas('7657657.7554') == "7,657,657.7554")
  3586.     assert(intCommas(76576577554) == "76,576,577,554")
  3587.     assert(nextNPrimes(1000000000000,10) == ([1000000000039, 1000000000061, 1000000000063, 1000000000091,
  3588.                                               1000000000121, 1000000000163, 1000000000169, 1000000000177,
  3589.                                               1000000000189, 1000000000193]))
  3590.     assert get_time(1215322934.0398701, 1215322947.0320001) == ('Time was 12.99 seconds')
  3591.     assert get_time(1215323011.4567342, 1215323947.0320001) == ('Time was', '15 minutes, 36 seconds')
  3592.     assert get_time(1215312921.0054233, 1215322947.0320001) == ('Time was', '2 hours, 47 minutes, 6 seconds')
  3593.     assert(int_to_ordinal(19283743) == '19,283,743rd')
  3594.     assert(word_count("Now is the time for all good men to come to the aid of their party.") == 16)
  3595.     result = fact(10,4)
  3596.     #print("result:", result)
  3597.     e = float(result)/100000
  3598.     #print("e:", e)
  3599.     assert(result - e < fact(10,4) < result + e)
  3600.     assert fact(30,0) == 265252859812191058636308480000000
  3601.  
  3602.     #print(mpPow('34.5', '57.4', 31))
Advertisement
Add Comment
Please, Sign In to add comment