How to resolve the algorithm Proper divisors step by step in the Python programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Proper divisors step by step in the Python programming language

Table of Contents

Problem Statement

The   proper divisors   of a positive integer N are those numbers, other than N itself, that divide N without remainder. For N > 1 they will always include 1,   but for N == 1 there are no proper divisors.

The proper divisors of     6     are   1, 2, and 3. The proper divisors of   100   are   1, 2, 4, 5, 10, 20, 25, and 50.

Show all output here.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Proper divisors step by step in the Python programming language

Overview

This code explores the concept of proper divisors and provides various implementations and methods to analyze the properties of numbers with respect to proper divisors and prime factors.

Implementation Details

1. proper_divs2 Function

  • This function calculates the set of proper divisors of a given number'n'.
  • It does this by iterating through the range from 1 to (n + 1) // 2 + 1
  • It checks if 'n' is divisible by 'x' (without remainder) and if 'n' is not equal to 'x' (to exclude 'n' itself as a proper divisor).

2. Prime Factors Function

  • This function computes the prime factors of a given number 'n' and returns them as a dictionary where the keys are the prime factors and the values are their multiplicities.
  • It uses a memoized recursive function _divs to determine the prime factors of 'n' efficientl

3. proper_divs Function

  • This function determines the set of proper divisors of a given number 'n' using prime factorization.
  • It creates a list of prime factors and their occurrences (i.e., their multiplicities).
  • It then generates all possible combinations of multiplicities for the prime factors and calculates the divisors by multiplying the prime factors with their corresponding multiplicities.
  • Finally, it excludes 'n' from the set of divisors and returns the set of proper divisors.

4. properDivisors Function

  • This function calculates the proper divisors of a given number 'n' using prime factorization.
  • It identifies the prime factors of 'n' and groups them by their values.
  • For each group, it generates a list of divisors by varying the powers of prime factors within each group.

5. fTable Function

  • This function is used to generate a formatted table of results, where the first column represents input values, and the second column shows the results of applying a given function to those input values.

6. until Function

  • This function is used to repeatedly apply a given function 'f' to an initial value 'x' until a predicate 'p' becomes true.
  • It returns the value when the predicate is satisfied.

7. pd Function

  • This function calculates the proper divisors of a number 'num' by iterating through the numbers from 1 to 'num//2' and checking for divisibility.
  • It returns a list of proper divisors.

8. pdc Function

  • This function calculates the number of proper divisors of a given number 'num' by iterating through the numbers from 1 to 'num//2' and checking for divisibility.
  • It returns the count of proper divisors.

9. fmtres Function

  • This function formats a string with the provided title, limit, best number, and best count.
  • It is used to display the results of the analysis.

10. showcount Function

  • This function iterates through numbers up to a specified limit and calculates the number of proper divisors for each number.
  • It identifies the number with the highest number of proper divisors and the number with the lowest number of proper divisors.
  • It then displays the results in a formatted manner.

Source code in the python programming language

>>> def proper_divs2(n):
...     return {x for x in range(1, (n + 1) // 2 + 1) if n % x == 0 and n != x}
... 
>>> [proper_divs2(n) for n in range(1, 11)]
[set(), {1}, {1}, {1, 2}, {1}, {1, 2, 3}, {1}, {1, 2, 4}, {1, 3}, {1, 2, 5}]
>>> 
>>> n, length = max(((n, len(proper_divs2(n))) for n in range(1, 20001)), key=lambda pd: pd[1])
>>> n
15120
>>> length
79
>>>


from math import sqrt
from functools import lru_cache, reduce
from collections import Counter
from itertools import product


MUL = int.__mul__


def prime_factors(n):
    'Map prime factors to their multiplicity for n'
    d = _divs(n)
    d = [] if d == [n] else (d[:-1] if d[-1] == d else d)
    pf = Counter(d)
    return dict(pf)

@lru_cache(maxsize=None)
def _divs(n):
    'Memoized recursive function returning prime factors of n as a list'
    for i in range(2, int(sqrt(n)+1)):
        d, m  = divmod(n, i)
        if not m:
            return [i] + _divs(d)
    return [n]


def proper_divs(n):
    '''Return the set of proper divisors of n.'''
    pf = prime_factors(n)
    pfactors, occurrences = pf.keys(), pf.values()
    multiplicities = product(*(range(oc + 1) for oc in occurrences))
    divs = {reduce(MUL, (pf**m for pf, m in zip(pfactors, multis)), 1)
            for multis in multiplicities}
    try:
        divs.remove(n)
    except KeyError:
        pass
    return divs or ({1} if n != 1 else set())


if __name__ == '__main__':
    rangemax = 20000
    
    print([proper_divs(n) for n in range(1, 11)])
    print(*max(((n, len(proper_divs(n))) for n in range(1, 20001)), key=lambda pd: pd[1]))


'''Proper divisors'''

from itertools import accumulate, chain, groupby, product
from functools import reduce
from math import floor, sqrt
from operator import mul


# properDivisors :: Int -> [Int]
def properDivisors(n):
    '''The ordered divisors of n, excluding n itself.
    '''
    def go(a, group):
        return [x * y for x, y in product(
            a,
            accumulate(chain([1], group), mul)
        )]
    return sorted(
        reduce(go, [
            list(g) for _, g in groupby(primeFactors(n))
        ], [1])
    )[:-1] if 1 < n else []


# --------------------------TEST---------------------------
# main :: IO ()
def main():
    '''Tests'''

    print(
        fTable('Proper divisors of [1..10]:')(str)(str)(
            properDivisors
        )(range(1, 1 + 10))
    )

    print('\nExample of maximum divisor count in the range [1..20000]:')
    print(
        max(
            [(n, len(properDivisors(n))) for n in range(1, 1 + 20000)],
            key=snd
        )
    )


# -------------------------DISPLAY-------------------------

# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
    '''Heading -> x display function -> fx display function ->
       f -> xs -> tabular string.
    '''
    def go(xShow, fxShow, f, xs):
        ys = [xShow(x) for x in xs]
        w = max(map(len, ys))
        return s + '\n' + '\n'.join(map(
            lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
            xs, ys
        ))
    return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
        xShow, fxShow, f, xs
    )


# -------------------------GENERIC-------------------------

# primeFactors :: Int -> [Int]
def primeFactors(n):
    '''A list of the prime factors of n.
    '''
    def f(qr):
        r = qr[1]
        return step(r), 1 + r

    def step(x):
        return 1 + (x << 2) - ((x >> 1) << 1)

    def go(x):
        root = floor(sqrt(x))

        def p(qr):
            q = qr[0]
            return root < q or 0 == (x % q)

        q = until(p)(f)(
            (2 if 0 == x % 2 else 3, 1)
        )[0]
        return [x] if q > root else [q] + go(x // q)

    return go(n)


# snd :: (a, b) -> b
def snd(tpl):
    '''Second member of a pair.'''
    return tpl[1]


# until :: (a -> Bool) -> (a -> a) -> a -> a
def until(p):
    '''The result of repeatedly applying f until p holds.
       The initial seed value is x.
    '''
    def go(f, x):
        v = x
        while not p(v):
            v = f(v)
        return v
    return lambda f: lambda x: go(f, x)


# MAIN ---
if __name__ == '__main__':
    main()


def pd(num):
	factors = []
	for divisor in range(1,1+num//2):
		if num % divisor == 0: factors.append(divisor)
	return factors

def pdc(num):
	count = 0
	for divisor in range(1,1+num//2):
		if num % divisor == 0: count += 1
	return count

def fmtres(title, lmt, best, bestc):
	return "The " + title + " number up to and including " + str(lmt) + " with the highest number of proper divisors is " + str(best) + ", which has " + str(bestc)

def showcount(limit):
	best, bestc, bh, bhc = 0, 0, 0, 0
	for i in range(limit+1):
		divc = pdc(i)
		if divc > bestc: bestc, best = divc, i
		if divc >= bhc: bhc, bh = divc, i
	if best == bh:
		print(fmtres("only", limit, best, bestc))
	else:
		print(fmtres("lowest", limit, best, bestc))
		print(fmtres("highest", limit, bh, bhc))
	print()

lmt = 10
for i in range(1, lmt + 1):
	divs = pd(i)
	if len(divs) == 0:
		print("There are no proper divisors of", i)
	elif len(divs) == 1:
		print(divs[0], "is the only proper divisor of", i)
	else:
		print(divs, "are the proper divisors of", i)
print()
showcount(20000)
showcount(25000)


  

You may also check:How to resolve the algorithm File extension is in extensions list step by step in the APL programming language
You may also check:How to resolve the algorithm Fibonacci sequence step by step in the Retro programming language
You may also check:How to resolve the algorithm Spelling of ordinal numbers step by step in the Java programming language
You may also check:How to resolve the algorithm Align columns step by step in the Oforth programming language
You may also check:How to resolve the algorithm Safe addition step by step in the Scala programming language