RosettaCodeData/Task/Own-digits-power-sum/Python/own-digits-power-sum-3.py
2023-07-01 13:44:08 -04:00

94 lines
2.3 KiB
Python

'''Own digit power sums'''
from itertools import accumulate, chain, islice, repeat
from functools import reduce
# ownDigitsPowerSums :: Int -> [Int]
def ownDigitsPowerSums(n):
'''All own digit power sums of digit length N'''
def go(xs):
m = reduce(lambda a, x: a + (x ** n), xs, 0)
return [m] if digitsMatch(m)(xs) else []
return concatMap(go)(
combinationsWithRepetitions(n)(range(0, 1 + 9))
)
# digitsMatch :: Int -> [Int] -> Bool
def digitsMatch(n):
'''True if the digits in ds contain exactly
the digits of n, in any order.
'''
def go(ds):
return sorted(ds) == sorted(digits(n))
return go
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''Own digit power sums for digit lengths 3..9'''
print(
'\n'.join([
'N ∈ [3 .. 8]',
*map(str, concatMap(ownDigitsPowerSums)(
range(3, 1 + 8)
)),
'\nN=9',
*map(str, ownDigitsPowerSums(9))
])
)
# ----------------------- GENERIC ------------------------
# combinationsWithRepetitions :: Int -> [a] -> [kTuple a]
def combinationsWithRepetitions(k):
'''Combinations with repetitions.
A list of tuples, representing
sets of cardinality k,
with elements drawn from xs.
'''
def f(a, x):
def go(ys, xs):
return xs + [[x] + y for y in ys]
return accumulate(a, go)
def combsBySize(xs):
return [
tuple(x) for x in next(islice(
reduce(
f, xs, chain(
[[[]]],
islice(repeat([]), k)
)
), k, None
))
]
return combsBySize
# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
'''A concatenated list over which a function has been
mapped.
The list monad can be derived by using a function f
which wraps its output in a list, (using an empty
list to represent computational failure).
'''
def go(xs):
return list(chain.from_iterable(map(f, xs)))
return go
# digits :: Int -> [Int]
def digits(n):
'''The individual digits of n as integers'''
return [int(c) for c in str(n)]
# MAIN ---
if __name__ == '__main__':
main()