Humble numbers: Difference between revisions

Content added Content deleted
(→‎{{header|Haskell}}: Added a first sketch in Haskell)
(→‎{{header|Python}}: Added a first sketch in Python.)
Line 1,735: Line 1,735:
152,515 humble numbers have 42 digits (23.9s, total:1,703,635)
152,515 humble numbers have 42 digits (23.9s, total:1,703,635)
</pre>
</pre>

=={{header|Python}}==
<lang python>'''Humble numbers'''

from itertools import count, groupby, islice
from functools import reduce
from math import floor, sqrt


# humbles :: () -> [Int]
def humbles():
'''A non-finite stream of Humble numbers.
OEIS A002473
'''
def isHumble(x):
return all(8 > x for x in primeFactors(x))
return filter(isHumble, count(1))


# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''First 50, and counts with N digits'''

print('First 50 Humble numbers:\n')
for row in chunksOf(10)(
take(50)(humbles())
):
print(' '.join(map(
lambda x: str(x).rjust(3),
row
)))

print('\nCounts of Humble numbers with n digits:\n')
for tpl in take(5)(
(k, len(list(g))) for k, g in
groupby(map(compose(len, str), humbles()))
):
print(tpl)


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

# chunksOf :: Int -> [a] -> [[a]]
def chunksOf(n):
'''A series of lists of length n, subdividing the
contents of xs. Where the length of xs is not evenly
divible, the final list will be shorter than n.
'''
return lambda xs: reduce(
lambda a, i: a + [xs[i:n + i]],
range(0, len(xs), n), []
) if 0 < n else []


# compose :: ((a -> a), ...) -> (a -> a)
def compose(*fs):
'''Composition, from right to left,
of a series of functions.
'''
return lambda x: reduce(
lambda a, f: f(a),
fs[::-1], x
)


# 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)


# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
'''The prefix of xs of length n,
or xs itself if n > length xs.
'''
return lambda xs: list(islice(xs, n))


# 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()</lang>
{{Out}}
<pre>First 50 Humble numbers:

1 2 3 4 5 6 7 8 9 10
12 14 15 16 18 20 21 24 25 27
28 30 32 35 36 40 42 45 48 49
50 54 56 60 63 64 70 72 75 80
81 84 90 96 98 100 105 108 112 120

Counts of Humble numbers with n digits:

(1, 9)
(2, 36)
(3, 95)
(4, 197)
(5, 356)</pre>


=={{header|Racket}}==
=={{header|Racket}}==