Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,3 @@
---
from: http://rosettacode.org/wiki/Humble_numbers
note: Prime Numbers

View file

@ -0,0 +1,32 @@
Humble numbers are positive integers which have &nbsp; no &nbsp; prime factors &nbsp; <big> &gt; </big> &nbsp; '''7'''.
Humble numbers are also called &nbsp; ''7-smooth numbers'', &nbsp; and sometimes called &nbsp; ''highly composite'',
<br>although this conflicts with another meaning of &nbsp; ''highly composite numbers''.
Another way to express the above is:
<big><big> humble = 2<sup>i</sup> &times; 3<sup>j</sup> &times; 5<sup>k</sup> &times; 7<sup>m</sup> </big></big>
where <big> i, j, k, m <big>&ge;</big> 0 </big>
;Task:
:* &nbsp; show the first &nbsp; '''50''' &nbsp; humble numbers &nbsp; (in a horizontal list)
:* &nbsp; show the number of humble numbers that have &nbsp; '''x''' &nbsp; decimal digits for all &nbsp; '''x's''' &nbsp; up to &nbsp; '''n''' &nbsp; (inclusive).
:* &nbsp; show &nbsp; (as many as feasible or reasonable for above) &nbsp; on separate lines
:* &nbsp; show all output here on this page
;Related tasks:
:* &nbsp; [[Hamming numbers]]
;References:
:* &nbsp; [[wp:Smooth_number#Definition_smooth_numbers|Wikipedia: Smooth numbers]], see the 2<sup>nd</sup> paragraph.
:* &nbsp; [[oeis:A002473|OEIS A002473: humble numbers]]
:* &nbsp; [http://www.informatik.uni-ulm.de/acm/Locals/1996/number.sol University of Ulm, The first 5842 terms of humble numbers]
<br><br>

View file

@ -0,0 +1,30 @@
F is_humble(i)
I i <= 1
R 1B
I i % 2 == 0 {R is_humble(i I/ 2)}
I i % 3 == 0 {R is_humble(i I/ 3)}
I i % 5 == 0 {R is_humble(i I/ 5)}
I i % 7 == 0 {R is_humble(i I/ 7)}
R 0B
DefaultDict[Int, Int] humble
V limit = 7F'FF
V count = 0
V num = 1
L count < limit
I is_humble(num)
humble[String(num).len]++
I count < 50
print(num, end' )
count++
num++
print()
print()
print(Of the first count humble numbers:)
L(num) 1 .< humble.len - 1
I num !C humble
L.break
print(#5 have #. digits.format(humble[num], num))

View file

@ -0,0 +1,45 @@
BEGIN # find some Humble numbers - numbers with no prime factors above 7 #
INT max humble = 2048;
INT max shown humble = 50;
PROC min = ( INT a, b )INT: IF a < b THEN a ELSE b FI;
[ 1 : max humble ]INT h;
[ 0 : 6 ]INT h count;
FOR i FROM LWB h count TO UPB h count DO h count[ i ] := 0 OD;
INT p2 := 2, p3 := 3, p5 := 5, p7 := 7;
INT last2 := 1, last3 := 1, last5 := 1, last7 := 1;
# 1 is the first humble number ( 2^0 * 3^0 * 5^0 * 7^0 ) and has 1 digit #
h[ 1 ] := 1;
h count[ 1 ] := 1;
print( ( "1" ) );
FOR n FROM 2 TO max humble DO
# the next humble number is the lowest of the next multiples of #
# 2, 3, 5, 7 #
INT m = min( min( min( p2, p3 ), p5 ), p7 );
h[ n ] := m;
IF n <= max shown humble THEN print( ( " ", whole( m, 0 ) ) ) FI;
IF m = p2 THEN p2 := 2 * h[ last2 := last2 + 1 ] FI;
IF m = p3 THEN p3 := 3 * h[ last3 := last3 + 1 ] FI;
IF m = p5 THEN p5 := 5 * h[ last5 := last5 + 1 ] FI;
IF m = p7 THEN p7 := 7 * h[ last7 := last7 + 1 ] FI;
h count[ IF m < 10 THEN 1
ELIF m < 100 THEN 2
ELIF m < 1 000 THEN 3
ELIF m < 10 000 THEN 4
ELIF m < 100 000 THEN 5
ELIF m < 1 000 000 THEN 6
ELSE 0
FI
] +:= 1
OD;
print( ( newline ) );
FOR i TO 6 DO
print( ( "There are "
, whole( h count[ i ], -4 )
, " Humble numbers with "
, whole( i, 0 )
, " digits"
, newline
)
)
OD
END

View file

@ -0,0 +1,65 @@
begin % find some Humble numbers - numbers with no prime factors above 7 %
% returns the minimum of a and b %
integer procedure min ( integer value a, b ) ; if a < b then a else b;
% find and print Humble Numbers %
integer MAX_HUMBLE;
MAX_HUMBLE := 2048;
begin
integer array H( 1 :: MAX_HUMBLE );
integer p2, p3, p5, p7, last2, last3, last5, last7, h1, h2, h3, h4, h5, h6;
i_w := 1; s_w := 1; % output formatting %
% 1 is the first Humble number %
H( 1 ) := 1;
h1 := h2 := h3 := h4 := h5 := h6 := 0;
last2 := last3 := last5 := last7 := 1;
p2 := 2;
p3 := 3;
p5 := 5;
p7 := 7;
for hPos := 2 until MAX_HUMBLE do begin
integer m;
% the next Humble number is the lowest of the next multiple of 2, 3, 5, 7 %
m := min( min( min( p2, p3 ), p5 ), p7 );
H( hPos ) := m;
if m = p2 then begin
% the Humble number was the next multiple of 2 %
% the next multiple of 2 will now be twice the Humble number following %
% the previous multple of 2 %
last2 := last2 + 1;
p2 := 2 * H( last2 )
end if_used_power_of_2 ;
if m = p3 then begin
last3 := last3 + 1;
p3 := 3 * H( last3 )
end if_used_power_of_3 ;
if m = p5 then begin
last5 := last5 + 1;
p5 := 5 * H( last5 )
end if_used_power_of_5 ;
if m = p7 then begin
last7 := last7 + 1;
p7 := 7 * H( last7 )
end if_used_power_of_5 ;
end for_hPos ;
i_w := 1; s_w := 1; % output formatting %
write( H( 1 ) );
for hPos := 2 until 50 do writeon( H( hPos ) );
for hPos := 1 until MAX_HUMBLE do begin
integer m;
m := H( hPos );
if m < 10 then h1 := h1 + 1
else if m < 100 then h2 := h2 + 1
else if m < 1000 then h3 := h3 + 1
else if m < 10000 then h4 := h4 + 1
else if m < 100000 then h5 := h5 + 1
else if m < 1000000 then h6 := h6 + 1
end for_hPos ;
i_w := 5; s_w := 0;
write( "there are", h1, " Humble numbers with 1 digit" );
write( "there are", h2, " Humble numbers with 2 digits" );
write( "there are", h3, " Humble numbers with 3 digits" );
write( "there are", h4, " Humble numbers with 4 digits" );
write( "there are", h5, " Humble numbers with 5 digits" );
write( "there are", h6, " Humble numbers with 6 digits" )
end
end.

View file

@ -0,0 +1,31 @@
# syntax: GAWK -f HUMBLE_NUMBERS.AWK
#
# sorting:
# PROCINFO["sorted_in"] is used by GAWK
# SORTTYPE is used by Thompson Automation's TAWK
#
BEGIN {
PROCINFO["sorted_in"] = "@ind_num_asc" ; SORTTYPE = 1
n = 1
for (; count<5193; n++) {
if (is_humble(n)) {
arr[length(n)]++
if (count++ < 50) {
printf("%d ",n)
}
}
}
printf("\nCount Digits of the first %d humble numbers:\n",count)
for (i in arr) {
printf("%5d %6d\n",arr[i],i)
}
exit(0)
}
function is_humble(i) {
if (i <= 1) { return(1) }
if (i % 2 == 0) { return(is_humble(i/2)) }
if (i % 3 == 0) { return(is_humble(i/3)) }
if (i % 5 == 0) { return(is_humble(i/5)) }
if (i % 7 == 0) { return(is_humble(i/7)) }
return(0)
}

View file

@ -0,0 +1,59 @@
;;; Find some humble numbers - numbers with no prime factors above 7
PROC humbleStat( CARD s, d ) ;;; displays a statistic about humble numbers
Print( "There are " )
IF s < 10 THEN Put(' ) FI
IF s < 100 THEN Put(' ) FI
PrintC( s )Print( " humble numbers with " )PrintC( d )Print( " digit" )
IF d > 1 THEN Put('s) FI
PutE()
RETURN
PROC Main() ;;; find and print humble numbers
DEFINE MAX_HUMBLE = "400"
CARD ARRAY H( MAX_HUMBLE )
CARD h1, h2, h3, h4, h5, h6, hPos, m
CARD p2, p3, p5, p7
CARD last2, last3, last5, last7
; 1 is the first humble number
H( 0 ) = 1
h1 = 0 h2 = 0 h3 = 0 h4 = 0 h5 = 0 h6 = 0
last2 = 0 last3 = 0 last5 = 0 last7 = 0
p2 = 2 p3 = 3 p5 = 5 p7 = 7
FOR hPos = 1 TO MAX_HUMBLE - 1 DO
; the next humble number is the lowest of the
; next multiples of 2, 3, 5, 7
IF p2 < p3 THEN m = p2 ELSE m = p3 FI
IF p5 < m THEN m = p5 FI
IF p7 < m THEN m = p7 FI
H( hPos ) = m
IF m = p2 THEN last2 = last2 + 1 p2 = 2 * H( last2 ) FI
IF m = p3 THEN last3 = last3 + 1 p3 = 3 * H( last3 ) FI
IF m = p5 THEN last5 = last5 + 1 p5 = 5 * H( last5 ) FI
IF m = p7 THEN last7 = last7 + 1 p7 = 7 * H( last7 ) FI
OD
FOR hPos = 0 TO 49 DO
Put(' )PrintC( H( hPos ) )
OD
PutE()
FOR hPos = 0 TO MAX_HUMBLE - 1 DO
m = H( hPos )
IF m < 10 THEN h1 = h1 + 1
ELSEIF m < 100 THEN h2 = h2 + 1
ELSEIF m < 1000 THEN h3 = h3 + 1
ELSEIF m < 10000 THEN h4 = h4 + 1
FI
OD
humbleStat( h1, 1 )
humbleStat( h2, 2 )
humbleStat( h3, 3 )
humbleStat( h4, 4 )
RETURN

View file

@ -0,0 +1,66 @@
with Ada.Text_IO;
procedure Show_Humble is
type Positive is range 1 .. 2**63 - 1;
First : constant Positive := Positive'First;
Last : constant Positive := 999_999_999;
function Is_Humble (I : in Positive) return Boolean is
begin
if I <= 1 then return True;
elsif I mod 2 = 0 then return Is_Humble (I / 2);
elsif I mod 3 = 0 then return Is_Humble (I / 3);
elsif I mod 5 = 0 then return Is_Humble (I / 5);
elsif I mod 7 = 0 then return Is_Humble (I / 7);
else return False;
end if;
end Is_Humble;
subtype Digit_Range is Natural range First'Image'Length - 1 .. Last'Image'Length - 1;
Digit_Count : array (Digit_Range) of Natural := (others => 0);
procedure Count_Humble_Digits is
use Ada.Text_IO;
Humble_Count : Natural := 0;
Len : Natural;
begin
Put_Line ("The first 50 humble numbers:");
for N in First .. Last loop
if Is_Humble (N) then
Len := N'Image'Length - 1;
Digit_Count (Len) := Digit_Count (Len) + 1;
if Humble_Count < 50 then
Put (N'Image);
Put (" ");
end if;
Humble_Count := Humble_Count + 1;
end if;
end loop;
New_Line (2);
end Count_Humble_Digits;
procedure Show_Digit_Counts is
package Natural_IO is
new Ada.Text_IO.Integer_IO (Natural);
use Ada.Text_IO;
use Natural_IO;
Placeholder : String := "Digits Count";
Image_Digit : String renames Placeholder (1 .. 6);
Image_Count : String renames Placeholder (8 .. Placeholder'Last);
begin
Put_Line ("The digit counts of humble numbers:");
Put_Line (Placeholder);
for Digit in Digit_Count'Range loop
Put (Image_Digit, Digit);
Put (Image_Count, Digit_Count (Digit));
Put_Line (Placeholder);
end loop;
end Show_Digit_Counts;
begin
Count_Humble_Digits;
Show_Digit_Counts;
end Show_Humble;

View file

@ -0,0 +1,60 @@
n := 1, c := 0
while (c < 50)
{
if isHumbleNumbers(prime_numbers(n))
c++, result .= n " "
n++
}
n := 1, l := 0, c:=[]
loop
{
if (l:=StrLen(n)) > 5
break
if isHumbleNumbers(prime_numbers(n))
c[l] := c[l] ? c[l] + 1 : 1
n++
}
for i, v in c
result .= "`n" i ":`t" v
MsgBox, 262144, ,% result
return
isHumbleNumbers(x){
for i, v in x
if v > 7
return false
return true
}
prime_numbers(n) {
if (n <= 3)
return [n]
ans := [], done := false
while !done {
if !Mod(n,2)
ans.push(2), n/=2
else if !Mod(n,3)
ans.push(3), n/=3
else if (n = 1)
return ans
else {
sr:=sqrt(n), done:=true, i:=6
; try to divide the checked number by all numbers till its square root.
while (i <= sr+6) {
if !Mod(n, i-1) { ; is n divisible by i-1?
ans.push(i-1), n/=i-1, done:=false
break
}
if !Mod(n, i+1) { ; is n divisible by i+1?
ans.push(i+1), n/=i+1, done:=false
break
}
i += 6
}
}
}
ans.push(n)
return ans
}

View file

@ -0,0 +1,60 @@
#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>
bool isHumble(int i) {
if (i <= 1) return true;
if (i % 2 == 0) return isHumble(i / 2);
if (i % 3 == 0) return isHumble(i / 3);
if (i % 5 == 0) return isHumble(i / 5);
if (i % 7 == 0) return isHumble(i / 7);
return false;
}
auto toString(int n) {
std::stringstream ss;
ss << n;
return ss.str();
}
int main() {
auto limit = SHRT_MAX;
std::map<int, int> humble;
auto count = 0;
auto num = 1;
while (count < limit) {
if (isHumble(num)) {
auto str = toString(num);
auto len = str.length();
auto it = humble.find(len);
if (it != humble.end()) {
it->second++;
} else {
humble[len] = 1;
}
if (count < 50) std::cout << num << ' ';
count++;
}
num++;
}
std::cout << "\n\n";
std::cout << "Of the first " << count << " humble numbers:\n";
num = 1;
while (num < humble.size() - 1) {
auto it = humble.find(num);
if (it != humble.end()) {
auto c = *it;
std::cout << std::setw(5) << c.second << " have " << std::setw(2) << num << " digits\n";
num++;
} else {
break;
}
}
return 0;
}

View file

@ -0,0 +1,38 @@
#include <chrono>
#include <cmath>
#include <locale>
using UI = unsigned long long;
using namespace std;
using namespace chrono;
int limc = 877;
const double l2 = log(2), l3 = log(3), l5 = log(5), l7 = log(7), l0 = log(10), fac = 1e12;
static bool IsHum(int num) { if (num <= 1) return true; for (int j : { 2, 3, 5, 7 })
if (num % j == 0) return IsHum(num / j); return false; }
// slow way to determine whether numbers are humble numbers
static void First_Slow(int firstAmt) { printf("The first %d humble numbers are: ", firstAmt);
for (int gg = 0, g = 1; gg < firstAmt; g++) if (IsHum(g)) { printf("%d ", g); gg++; }
printf("\n\n"); }
int main(int argc, char **argv) {
First_Slow(50); setlocale(LC_ALL, ""); auto st = steady_clock::now();
if (argc > 1) limc = stoi(argv[1]);
UI *bins = new UI[limc], lb0 = (UI)round(fac * l0),
lb2 = (UI)round(fac * l2), lb3 = (UI)round(fac * l3),
lb5 = (UI)round(fac * l5), lb7 = (UI)round(fac * l7),
tot = 0, lmt = limc * lb0, lm2 = lb5 * 3;
printf("Digits Count Accum\n");
for (int g = 0; g < limc; g++) bins[g] = 0;
for (UI i = 0; i < lmt; i += lb2) for (UI j = i; j < lmt; j += lb3)
for (UI k = j; k < lmt; k += lb5) for (UI l = k; l < lmt; l += lb7)
bins[l / lb0]++;
for (int f = 0, g = 1; f < limc; f = g++) { tot += bins[f];
//if (g < 110 || g % 100 == 0 || (g < 200 && g % 10 == 0)) // uncomment to emulate pascal output
printf ("%4d %'13llu %'18llu\n", g, bins[f], tot); }
delete [] bins;
printf("Counting took %8f seconds\n", duration<double>(steady_clock::now() - st).count());
}

View file

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
namespace HumbleNumbers {
class Program {
static bool IsHumble(int i) {
if (i <= 1) return true;
if (i % 2 == 0) return IsHumble(i / 2);
if (i % 3 == 0) return IsHumble(i / 3);
if (i % 5 == 0) return IsHumble(i / 5);
if (i % 7 == 0) return IsHumble(i / 7);
return false;
}
static void Main() {
var limit = short.MaxValue;
Dictionary<int, int> humble = new Dictionary<int, int>();
var count = 0;
var num = 1;
while (count < limit) {
if (IsHumble(num)) {
var str = num.ToString();
var len = str.Length;
if (humble.ContainsKey(len)) {
humble[len]++;
} else {
humble[len] = 1;
}
if (count < 50) Console.Write("{0} ", num);
count++;
}
num++;
}
Console.WriteLine("\n");
Console.WriteLine("Of the first {0} humble numbers:", count);
num = 1;
while (num < humble.Count - 1) {
if (humble.ContainsKey(num)) {
var c = humble[num];
Console.WriteLine("{0,5} have {1,2} digits", c, num);
num++;
} else {
break;
}
}
}
}
}

View file

@ -0,0 +1,42 @@
#define BI
using System;
using System.Linq;
using System.Collections.Generic;
#if BI
using UI = System.Numerics.BigInteger;
#else
using UI = System.UInt64;
#endif
class Program {
static void Main(string[] args) {
#if BI
const int max = 100;
#else
const int max = 19;
#endif
List<UI> h = new List<UI> { 1 };
UI x2 = 2, x3 = 3, x5 = 5, x7 = 7, hm = 2, lim = 10;
int i = 0, j = 0, k = 0, l = 0, lc = 0, d = 1;
Console.WriteLine("Digits Count Time Mb used");
var elpsd = -DateTime.Now.Ticks;
do {
h.Add(hm);
if (hm == x2) x2 = h[++i] << 1;
if (hm == x3) x3 = (h[++j] << 1) + h[j];
if (hm == x5) x5 = (h[++k] << 2) + h[k];
if (hm == x7) x7 = (h[++l] << 3) - h[l];
hm = x2; if (x3 < hm) hm = x3; if (x5 < hm) hm = x5; if (x7 < hm) hm = x7;
if (hm >= lim) {
Console.WriteLine("{0,3} {1,9:n0} {2,9:n0} ms {3,9:n0}", d, h.Count - lc,
(elpsd + DateTime.Now.Ticks) / 10000, GC.GetTotalMemory(false) / 1000000);
lc = h.Count; if (++d > max) break; lim *= 10;
}
} while (true);
Console.WriteLine("{0,13:n0} Total", lc);
int firstAmt = 50;
Console.WriteLine("The first {0} humble numbers are: {1}", firstAmt, string.Join(" ",h.Take(firstAmt)));
}
}

View file

@ -0,0 +1,42 @@
using System;
using UI = System.UInt64;
class Program {
// write a range (1..num) to the console when num < 0, just write the nth when num > 0, otherwise write the digits tabulation
// note: when doing range or nth, if num > ~1e19 the results will appear incorrect as UInt64 can't express numbers that large
static void humLog(int digs, int num = 0) {
bool range = num < 0, nth = num > 0, small = range | nth; num = Math.Abs(num);
int maxdim = num;
if (range | nth) digs = num.ToString().Length; // calculate number of digits when range or nth is specified
//const int maxdim = 2_147_483_647; // 2GB limit (Int32.MaxValue), causes out of memory error
//const int maxdim = 2_146_435_071; // max practical amount
//const int maxdim = 2_114_620_032; // amount needed for 255 digits
else maxdim = 2_114_620_032;
const double fac = 1e11;
UI lb2 = (UI)Math.Round(fac * Math.Log(2)), lb3 = (UI)Math.Round(fac * Math.Log(3)), lb5 = (UI)Math.Round(fac * Math.Log(5)),
lb7 = (UI)Math.Round(fac * Math.Log(7)), lb0 = (UI)Math.Round(fac * Math.Log(10)), hm,
x2 = lb2, x3 = lb3, x5 = lb5, x7 = lb7, lim = lb0;
int i = 0, j = 0, k = 0, l = 0, lc = 0, d = 1, hi = 1;
UI[] h = new UI[maxdim]; h[0] = 1;
var st = DateTime.Now.Ticks;
if (range) Console.Write("The first {0} humble numbers are: 1 ", num);
else if (nth) Console.Write("The {0}{1} humble number is ", num, (num % 10) switch { 1 => "st", 2 => "nd", 3 => "rd", _ => "th", });
else Console.WriteLine("\nDigits Dig Count Tot Count Time Mb used");
do { hm = x2; if (x3 < hm) hm = x3; if (x5 < hm) hm = x5; if (x7 < hm) hm = x7; // select the minimum
if (hm >= lim && !small) { // passed another decade, so output results
Console.WriteLine("{0,3} {1,13:n0} {4,16:n0} {2,9:n3}s {3,9:n0}", d, hi - lc,
((DateTime.Now.Ticks - st) / 10000)/1000.0, GC.GetTotalMemory(false) / 1000000, hi);
lc = hi; if (++d > digs) break; lim += lb0; }
h[hi++] = (hm); if (small) { if (nth && hi == num) { Console.WriteLine(Math.Round(Math.Exp(hm / fac))); break; }
if (range) { Console.Write("{0} ", Math.Round(Math.Exp(hm / fac))); if (hi == num) { Console.WriteLine(); break; } } }
if (hm == x2) x2 = h[++i] + lb2; if (hm == x3) x3 = h[++j] + lb3;
if (hm == x5) x5 = h[++k] + lb5; if (hm == x7) x7 = h[++l] + lb7;
} while (true);
if (!(range | nth)) Console.WriteLine("{0,17:n0} Total", lc);
}
static void Main(string[] args) {
humLog(0, -50); // see the range 1..50
humLog(255); // see tabulation for digits 1 to 255
}
}

View file

@ -0,0 +1,48 @@
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool isHumble(int i) {
if (i <= 1) return true;
if (i % 2 == 0) return isHumble(i / 2);
if (i % 3 == 0) return isHumble(i / 3);
if (i % 5 == 0) return isHumble(i / 5);
if (i % 7 == 0) return isHumble(i / 7);
return false;
}
int main() {
int limit = SHRT_MAX;
int humble[16];
int count = 0;
int num = 1;
char buffer[16];
memset(humble, 0, sizeof(humble));
for (; count < limit; num++) {
if (isHumble(num)) {
size_t len;
sprintf_s(buffer, sizeof(buffer), "%d", num);
len = strlen(buffer);
if (len >= 16) {
break;
}
humble[len]++;
if (count < 50) {
printf("%d ", num);
}
count++;
}
}
printf("\n\n");
printf("Of the first %d humble numbers:\n", count);
for (num = 1; num < 10; num++) {
printf("%5d have %d digits\n", humble[num], num);
}
return 0;
}

View file

@ -0,0 +1,24 @@
def humble?(i)
return true if (i < 2)
return humble?(i // 2) if (i % 2 == 0)
return humble?(i // 3) if (i % 3 == 0)
return humble?(i // 5) if (i % 5 == 0)
return humble?(i // 7) if (i % 7 == 0)
false
end
count, num = 0, 0_i64
digits = 10 # max digits for humble numbers
limit = 10_i64 ** digits # max numbers to search through
humble = Array.new(digits + 1, 0)
while (num += 1) < limit
if humble?(num)
humble[num.to_s.size] += 1
print num, " " if count < 50
count += 1
end
end
print "\n\nOf the first #{count} humble numbers:\n"
(1..digits).each { |num| printf("%5d have %2d digits\n", humble[num], num) }

View file

@ -0,0 +1,25 @@
require "big"
def humble(digits)
h = [1.to_big_i]
x2, x3, x5, x7 = 2.to_big_i, 3.to_big_i, 5.to_big_i, 7.to_big_i
i, j, k, l = 0, 0, 0, 0
(1..).each do |n|
x = {x2, x3, x5, x7}.min # {} tuple|stack faster [] array|heap
break if x.to_s.size > digits
h << x
x2 = 2 * h[i += 1] if x2 == h[n]
x3 = 3 * h[j += 1] if x3 == h[n]
x5 = 5 * h[k += 1] if x5 == h[n]
x7 = 7 * h[l += 1] if x7 == h[n]
end
h
end
digits = 50 # max digits for humble numbers
h = humble(digits) # humble numbers <= digits size
count = h.size # the total humble numbers count
counts = h.map { |n| n.to_s.size }.tally # hash of digits counts 1..digits
print "First 50 Humble Numbers: \n"; (0...50).each { |i| print "#{h[i]} " }
print "\n\nOf the first #{count} humble numbers:\n"
(1..digits).each { |num| printf("%6d have %2d digits\n", counts[num], num) }

View file

@ -0,0 +1,42 @@
import std.conv;
import std.stdio;
bool isHumble(int i) {
if (i <= 1) return true;
if (i % 2 == 0) return isHumble(i / 2);
if (i % 3 == 0) return isHumble(i / 3);
if (i % 5 == 0) return isHumble(i / 5);
if (i % 7 == 0) return isHumble(i / 7);
return false;
}
void main() {
auto limit = short.max;
int[int] humble;
auto count = 0;
auto num = 1;
while (count < limit) {
if (isHumble(num)) {
auto str = num.to!string;
auto len = str.length;
humble[len]++;
if (count < 50) write(num, ' ');
count++;
}
num++;
}
writeln('\n');
writeln("Of the first ", count, " humble numbers:");
num = 1;
while (num < humble.length - 1) {
if (num in humble) {
auto c = humble[num];
writefln("%5d have %2d digits", c, num);
num++;
} else {
break;
}
}
}

View file

@ -0,0 +1,183 @@
module Main exposing (main)
import Browser
import Html exposing (div, pre, text, br)
import Task exposing (Task, succeed, andThen, perform)
import BigInt
import Bitwise exposing (shiftRightBy, and)
import Time exposing (now, posixToMillis)
-- an infinite non-empty non-memoizing Co-Inductive Stream (CIS)...
type CIS a = CIS a (() -> CIS a)
takeCIS2String : Int -> (a -> String) -> CIS a -> String
takeCIS2String n cvtf cis =
let loop i (CIS hd tl) lst =
if i < 1 then List.reverse lst |> String.join ", "
else loop (i - 1) (tl()) (cvtf hd :: lst)
in loop n cis []
-- a Min Heap binary heap Priority Queue...
type PriorityQ comparable v =
Mt
| Br comparable v (PriorityQ comparable v)
(PriorityQ comparable v)
emptyPQ : PriorityQ comparable v
emptyPQ = Mt
peekMinPQ : PriorityQ comparable v -> Maybe (comparable, v)
peekMinPQ pq = case pq of
(Br k v _ _) -> Just (k, v)
Mt -> Nothing
pushPQ : comparable -> v -> PriorityQ comparable v
-> PriorityQ comparable v
pushPQ wk wv pq =
case pq of
Mt -> Br wk wv Mt Mt
(Br vk vv pl pr) ->
if wk <= vk then Br wk wv (pushPQ vk vv pr) pl
else Br vk vv (pushPQ wk wv pr) pl
siftdown : comparable -> v -> PriorityQ comparable v
-> PriorityQ comparable v -> PriorityQ comparable v
siftdown wk wv pql pqr =
case pql of
Mt -> Br wk wv Mt Mt
(Br vkl vvl pll prl) ->
case pqr of
Mt -> if wk <= vkl then Br wk wv pql Mt
else Br vkl vvl (Br wk wv Mt Mt) Mt
(Br vkr vvr plr prr) ->
if wk <= vkl && wk <= vkr then Br wk wv pql pqr
else if vkl <= vkr then Br vkl vvl (siftdown wk wv pll prl) pqr
else Br vkr vvr pql (siftdown wk wv plr prr)
replaceMinPQ : comparable -> v -> PriorityQ comparable v
-> PriorityQ comparable v
replaceMinPQ wk wv pq = case pq of
Mt -> Mt
(Br _ _ pl pr) -> siftdown wk wv pl pr
-- actual humble function implementation...
type alias Mults = { x2 : Int, x3 : Int, x5 : Int, x7 : Int }
type alias LogRep = { lg : Float, mlts : Mults }
oneLogRep : LogRep
oneLogRep = LogRep 0.0 <| Mults 0 0 0 0
lg10 : Float
lg10 = 1.0
lg7 : Float
lg7 = logBase 10 7
lg5 : Float
lg5 = logBase 10.0 5.0
lg3 : Float
lg3 = logBase 10.0 3.0
lg2 : Float
lg2 = lg10 - lg5
multLR2 : LogRep -> LogRep
multLR2 ({ lg, mlts } as lr) =
{ lr | lg = lg + lg2, mlts = { mlts | x2 = mlts.x2 + 1 } }
multLR3 : LogRep -> LogRep
multLR3 ({ lg, mlts } as lr) =
{ lr | lg = lg + lg3, mlts = { mlts | x3 = mlts.x3 + 1 } }
multLR5 : LogRep -> LogRep
multLR5 ({ lg, mlts } as lr) =
{ lr | lg = lg + lg5, mlts = { mlts | x5 = mlts.x5 + 1 } }
multLR7 : LogRep -> LogRep
multLR7 ({ lg, mlts } as lr) =
{ lr | lg = lg + lg7, mlts = { mlts | x7 = mlts.x7 + 1 } }
showLogRep : LogRep -> String
showLogRep lr =
let xpnd x m r =
if x <= 0 then r
else xpnd (shiftRightBy 1 x) (BigInt.mul m m)
(if (and 1 x) /= 0 then BigInt.mul m r else r)
in BigInt.fromInt 1 |> xpnd lr.mlts.x2 (BigInt.fromInt 2)
|> xpnd lr.mlts.x3 (BigInt.fromInt 3) |> xpnd lr.mlts.x5 (BigInt.fromInt 5)
|> xpnd lr.mlts.x7 (BigInt.fromInt 7) |> BigInt.toString
humblesLog : () -> CIS LogRep
humblesLog() =
let prmfs = [multLR7, multLR5, multLR3, multLR2]
fprmf = List.head prmfs |> Maybe.withDefault identity -- never Nothing!
rstps = List.tail prmfs |> Maybe.withDefault [] -- never Nothing!
frstcis =
let nxt lr =
CIS lr <| \ _ -> nxt (fprmf lr)
in nxt (fprmf oneLogRep)
dflt = (0.0, Mults 0 0 0 0)
mkcis lrf cis =
let frst = lrf oneLogRep
scnd = lrf frst
nxt pq (CIS hd tlf as cs) =
let (lgv, v) = peekMinPQ pq |> Maybe.withDefault dflt in
if lgv < hd.lg then let lr = (LogRep lgv v) in CIS lr <| \ _ ->
let { lg, mlts } = lrf lr
in nxt (replaceMinPQ lg mlts pq) cs
else CIS hd <| \ _ ->
let { lg, mlts } = lrf hd
in nxt (pushPQ lg mlts pq) (tlf())
in CIS frst <| \ _ -> nxt (pushPQ scnd.lg scnd.mlts emptyPQ) cis
rest() = List.foldl mkcis frstcis rstps
in CIS oneLogRep <| \ _ -> rest()
-- pretty printing function to add commas every 3 chars from left...
comma3 : String -> String
comma3 s =
let go n lst =
if n < 1 then String.join "," lst else
let nn = max (n - 3) 0
in go nn (String.slice nn n s :: lst)
in go (String.length s) []
humbleDigitCountsTo : Int -> CIS LogRep -> List String
humbleDigitCountsTo n cis =
let go i (CIS hd tlf) cnt cacc lst =
if i >= n then List.reverse lst else
if truncate hd.lg <= i then go i (tlf()) (cnt + 1) cacc lst
else let ni = i + 1
ncacc = cacc + cnt
str =
(String.padLeft 4 ' ' << String.fromInt) ni
++ (String.padLeft 14 ' ' << comma3 << String.fromInt) cnt
++ (String.padLeft 19 ' ' << comma3 << String.fromInt) ncacc
in go ni (tlf()) 1 ncacc (str :: lst) -- always > 1 per dgt
in go 0 cis 0 0 []
-- code to do with testing...
timemillis : () -> Task Never Int -- a side effect function
timemillis() = now |> andThen (\ t -> succeed (posixToMillis t))
test : () -> Cmd Msg
test() =
let numdgt = 100
hdg1 = "The first 50 humble numbers are: "
msg1 = humblesLog() |> takeCIS2String 50 showLogRep
hdg2 = "Count of humble numbers for each digit length 1-"
++ String.fromInt numdgt ++ ":"
msg2 = "Digits Count Accum"
in timemillis()
|> Task.andThen (\ strt ->
let rslt = humblesLog() |> humbleDigitCountsTo numdgt
in timemillis()
|> Task.andThen (\ stop ->
succeed (((hdg1 ++ msg1) :: "" :: hdg2 :: msg2 :: rslt)
++ ["Counting took " ++ String.fromInt (stop - strt)
++ " milliseconds."])))
|> perform Done
-- following code has to do with outputting to a web page using MUV/TEA...
type alias Model = List String
type Msg = Done Model
main : Program () Model Msg
main = Browser.element
{ init = \ _ -> ([], test())
, update = \ (Done mdl) _ -> (mdl, Cmd.none)
, subscriptions = \ _ -> Sub.none
, view = div [] << List.map (\ s ->
if s == "" then br [] []
else pre [] <| List.singleton <| text s)
}

View file

@ -0,0 +1,12 @@
// Generate humble numbers. Nigel Galloway: June 18th., 2020
let fN g=let mutable n=1UL in (fun()->n<-n*g;n)
let fI (n:uint64) g=let mutable q=n in (fun()->let t=q in q<-n*g();t)
let fG n g=let mutable vn,vg=n(),g() in fun()->match vg<vn with true->let t=vg in vg<-g();t |_->let t=vn in vn<-n();t
let rec fE n=seq{yield n();yield! fE n}
let fL n g=let mutable vn,vg,v=n(),g(),None
fun()->match v with
Some n->v<-None;n
|_->match vg() with
r when r<vn->r
|r->vg<-fG vg (fI vn (g()));vn<-n();v<-Some r;vg()
let humble = seq{yield 1UL;yield! fE(fL (fN 7UL) (fun()->fL (fN 5UL) (fun()->fL (fN 3UL) (fun()->fN 2UL))))}

View file

@ -0,0 +1 @@
humble |> Seq.take 50 |> Seq.iter (printf "%d ");printfn ""

View file

@ -0,0 +1 @@
for n in [1..18] do let g=pown 10UL n in printfn "There are %d humble numbers with %d digits" (humble|>Seq.skipWhile(fun n->n<g/10UL)|>Seq.takeWhile(fun n->n<g)|>Seq.length) n

View file

@ -0,0 +1,78 @@
// a count and logarithmic approximation of the humble value...
type LogRep = struct val lg: uint64; val x2: uint16; val x3: uint16;
val x5: uint16; val x7: uint16
new(lg, x2, x3, x5, x7) =
{lg = lg; x2 = x2; x3 = x3; x5 = x5; x7 = x7 } end
let one: LogRep = LogRep(0UL, 0us, 0us, 0us, 0us)
let logshft = 50
let fac = pown 2.0 logshft
let lg10_10 = 1UL <<< logshft
let lg7_10 = (uint64 << round) <| log 7.0 / log 10.0 * fac
let lg5_10 = (uint64 << round) <| log 5.0 / log 10.0 * fac
let lg3_10 = (uint64 << round) <| log 3.0 / log 10.0 * fac
let lg2_10 = lg10_10 - lg5_10
let inline mul2 (lr: LogRep): LogRep =
LogRep(lr.lg + lg2_10, lr.x2 + 1us, lr.x3, lr.x5, lr.x7)
let inline mul3 (lr: LogRep): LogRep =
LogRep(lr.lg + lg3_10, lr.x2, lr.x3 + 1us, lr.x5, lr.x7)
let inline mul5 (lr: LogRep): LogRep =
LogRep(lr.lg + lg5_10, lr.x2, lr.x3, lr.x5 + 1us, lr.x7)
let inline mul7 (lr: LogRep): LogRep =
LogRep(lr.lg + lg7_10, lr.x2, lr.x3, lr.x5, lr.x7 + 1us)
let lr2BigInt (lr: LogRep) =
let rec xpnd n mlt rslt =
if n <= 0us then rslt
else xpnd (n - 1us) mlt (mlt * rslt)
xpnd lr.x2 2I 1I |> xpnd lr.x3 3I |> xpnd lr.x5 5I |> xpnd lr.x7 7I
type CIS<'a> = CIS of 'a * (Unit -> CIS<'a>) // infinite Co-Inductive Stream...
let cis2Seq cis =
Seq.unfold (fun (CIS(hd, tlf)) -> Some(hd, tlf())) cis
let humblesLog() =
let prmfs = [ mul7; mul5; mul3; mul2 ]
let frstpf = Seq.head prmfs
let rstpfs = Seq.tail prmfs
let frstll =
let rec nxt n = CIS(n, fun () -> nxt (frstpf n))
nxt (frstpf one)
let mkcis cis mf =
let q = Queue<LogRep>(1024)
let fv = mf one
let nv = mf fv
let rec nxt (hdv: LogRep) (CIS(chd: LogRep, ctlf) as cis) =
if hdv.lg < chd.lg then
CIS(hdv, fun () -> q.Enqueue (mf hdv); nxt (q.Dequeue()) cis)
else CIS(chd, fun () -> q.Enqueue (mf chd); nxt hdv (ctlf()))
CIS(fv, fun () -> nxt nv cis)
CIS(one, fun () -> (Seq.fold mkcis frstll rstpfs))
let comma3 v =
let s = string v
let rec loop n lst =
if n < 1 then List.fold (fun s xs ->
s + "," + xs) (List.head lst) <| List.tail lst
else let nn = max (n - 3) 0 in loop nn (s.[nn .. n - 1] :: lst)
loop (String.length s) []
let digitCountTo n ll =
let rec loop i (CIS(hd: LogRep, tlf)) cnt cacc =
if int i <= n then
if hd.lg >>> logshft < i then loop i (tlf()) (cnt + 1) cacc else
let ncacc = cacc + cnt
printfn "%4d%14s%19s" i (comma3 cnt) (comma3 ncacc)
loop (i + 1UL) (tlf()) 1 ncacc
loop 1UL ll 0 0
printfn "The first 50 humble numbers are:"
humblesLog() |> cis2Seq |> Seq.take 50 |> Seq.map lr2BigInt
|> Seq.iter (printf "%A ");printfn ""
printfn ""
let numDigits = 255
printfn "Count of humble numbers for each digit length 1-%d:" numDigits
printfn "Digits Count Accum"
let strt = System.DateTime.Now.Ticks
humblesLog() |> digitCountTo numDigits
let stop = System.DateTime.Now.Ticks
printfn "Counting took %d milliseconds" <| ((stop - strt) / 10000L)

View file

@ -0,0 +1,93 @@
open System.Collections.Generic
open Microsoft.FSharp.NativeInterop
// a count and logarithmic approximation of the humble value...
type LogRep = struct val lg: uint64; val x2: uint16; val x3: uint16;
val x5: uint16; val x7: uint16
new(lg, x2, x3, x5, x7) =
{lg = lg; x2 = x2; x3 = x3; x5 = x5; x7 = x7 } end
let one: LogRep = LogRep(0UL, 0us, 0us, 0us, 0us)
let logshft = 50
let fac = pown 2.0 logshft
let lg10_10 = 1UL <<< logshft
let lg7_10 = (uint64 << round) <| log 7.0 / log 10.0 * fac
let lg5_10 = (uint64 << round) <| log 5.0 / log 10.0 * fac
let lg3_10 = (uint64 << round) <| log 3.0 / log 10.0 * fac
let lg2_10 = lg10_10 - lg5_10
let inline mul2 (lr: LogRep): LogRep =
LogRep(lr.lg + lg2_10, lr.x2 + 1us, lr.x3, lr.x5, lr.x7)
let inline mul3 (lr: LogRep): LogRep =
LogRep(lr.lg + lg3_10, lr.x2, lr.x3 + 1us, lr.x5, lr.x7)
let inline mul5 (lr: LogRep): LogRep =
LogRep(lr.lg + lg5_10, lr.x2, lr.x3, lr.x5 + 1us, lr.x7)
let inline mul7 (lr: LogRep): LogRep =
LogRep(lr.lg + lg7_10, lr.x2, lr.x3, lr.x5, lr.x7 + 1us)
let lr2BigInt (lr: LogRep) =
let rec xpnd n mlt rslt =
if n <= 0us then rslt
else xpnd (n - 1us) mlt (mlt * rslt)
xpnd lr.x2 2I 1I |> xpnd lr.x3 3I |> xpnd lr.x5 5I |> xpnd lr.x7 7I
type CIS<'a> = CIS of 'a * (Unit -> CIS<'a>) // infinite Co-Inductive Stream...
let cis2Seq cis =
Seq.unfold (fun (CIS(hd, tlf)) -> Some(hd, tlf())) cis
let humblesLog() =
let prmfs = [ mul7; mul5; mul3; mul2 ]
let frstpf = Seq.head prmfs
let rstpfs = Seq.tail prmfs
let frstll =
let rec nxt n = CIS(n, fun () -> nxt (frstpf n))
nxt (frstpf one)
let mkcis cis mf =
let q = Queue<LogRep>(1024)
let fv = mf one
let nv = mf fv
let rec nxt (hdv: LogRep) (CIS(chd: LogRep, ctlf) as cis) =
if hdv.lg < chd.lg then
CIS(hdv, fun () -> q.Enqueue (mf hdv); nxt (q.Dequeue()) cis)
else CIS(chd, fun () -> q.Enqueue (mf chd); nxt hdv (ctlf()))
CIS(fv, fun () -> nxt nv cis)
CIS(one, fun () -> (Seq.fold mkcis frstll rstpfs))
let comma3 v =
let s = string v
let rec loop n lst =
if n < 1 then List.fold (fun s xs ->
s + "," + xs) (List.head lst) <| List.tail lst
else let nn = max (n - 3) 0 in loop nn (s.[nn .. n - 1] :: lst)
loop (String.length s) []
printfn "The first 50 humble numbers are:"
humblesLog() |> cis2Seq |> Seq.take 50 |> Seq.map lr2BigInt
|> Seq.iter (printf "%A ");printfn ""
printfn ""
let numDigits = 877
printfn "Count of humble numbers for each digit length 1-%d:" numDigits
printfn "Digits Count Accum"
let strt = System.DateTime.Now.Ticks
let bins = Array.zeroCreate numDigits
#nowarn "9" // no warnings for the use of native pointers...
#nowarn "51"
let lmt = uint64 numDigits <<< logshft
let rec loopw w =
if w < lmt then
let rec loopx x =
if x < lmt then
let rec loopy y =
if y < lmt then
let rec loopz z =
if z < lmt then
// let ndx = z >>> logshft |> int
// bins.[ndx] <- bins.[ndx] + 1UL
// use pointers to save array bounds checking...
let ndx = &&bins.[z >>> logshft |> int]
NativePtr.write ndx (NativePtr.read ndx + 1UL)
loopz (z + lg7_10) in loopz y; loopy (y + lg5_10)
loopy x; loopx (x + lg3_10) in loopx w; loopw (w + lg2_10) in loopw 0UL
bins |> Seq.scan (fun (i, _, a) v ->
i + 1, v, a + v) (0, 0UL, 0UL) |> Seq.skip 1
|> Seq.iter (fun (i, c, a) -> printfn "%4d%14s%19s" i (comma3 c) (comma3 a))
let stop = System.DateTime.Now.Ticks
printfn "Counting took %d milliseconds" <| ((stop - strt) / 10000L)

View file

@ -0,0 +1,59 @@
USING: accessors assocs combinators deques dlists formatting fry
generalizations io kernel make math math.functions math.order
prettyprint sequences tools.memory.private ;
IN: rosetta-code.humble-numbers
TUPLE: humble-iterator 2s 3s 5s 7s digits
{ #digits initial: 1 } { target initial: 10 } ;
: <humble-iterator> ( -- humble-iterator )
humble-iterator new
1 1dlist >>2s
1 1dlist >>3s
1 1dlist >>5s
1 1dlist >>7s
H{ } clone >>digits ;
: enqueue ( n humble-iterator -- )
{
[ [ 2 * ] [ 2s>> ] ]
[ [ 3 * ] [ 3s>> ] ]
[ [ 5 * ] [ 5s>> ] ]
[ [ 7 * ] [ 7s>> ] ]
} [ bi* push-back ] map-compose 2cleave ;
: count-digits ( humble-iterator n -- )
[ over target>> >=
[ [ 1 + ] change-#digits [ 10 * ] change-target ] when ]
[ drop 1 swap [ #digits>> ] [ digits>> ] bi at+ ] bi ;
: ?pop ( 2s 3s 5s 7s n -- )
'[ dup peek-front _ = [ pop-front* ] [ drop ] if ] 4 napply ;
: next ( humble-iterator -- n )
dup dup { [ 2s>> ] [ 3s>> ] [ 5s>> ] [ 7s>> ] } cleave
4 ndup [ peek-front ] 4 napply min min min
{ [ ?pop ] [ swap enqueue ] [ count-digits ] [ ] } cleave ;
: upto-n-digits ( humble-iterator n -- seq )
1 + swap [ [ 2dup digits>> key? ] [ dup next , ] until ] { }
make [ digits>> delete-at ] dip but-last-slice ;
: .first50 ( seq -- )
"First 50 humble numbers:" print 50 head [ pprint bl ] each
nl ;
: .digit-breakdown ( humble-iterator -- )
"The digit counts of humble numbers:" print digits>> [
commas swap dup 1 = "" "s" ? "%9s have %2d digit%s\n"
printf
] assoc-each ;
: humble-numbers ( -- )
[ <humble-iterator> dup 95 upto-n-digits
[ .first50 nl ] [ drop .digit-breakdown nl ] [
"Total number of humble numbers found: " write length
commas print
] tri ] time ;
MAIN: humble-numbers

View file

@ -0,0 +1,44 @@
Function IsHumble(i As Integer) As Boolean
If i <= 1 Then Return True
If i Mod 2 = 0 Then Return IsHumble(i \ 2)
If i Mod 3 = 0 Then Return IsHumble(i \ 3)
If i Mod 5 = 0 Then Return IsHumble(i \ 5)
If i Mod 7 = 0 Then Return IsHumble(i \ 7)
Return False
End Function
Const limiteMax = 7574
Dim As Integer humble(10) 'As New Dictionary(Of Integer, Integer)
Dim As Integer cont = 0, num = 1
Print "Los 50 primeros n£meros de Humble son:";
While cont < limiteMax
If IsHumble(num) Then
Dim As Integer longitud = Len(Str(num))
If longitud > 10 Then
Exit While
End If
If humble(longitud) Then
humble(longitud) += 1
Else
humble(longitud) = 1
End If
If cont < 50 Then
If cont Mod 10 = 0 Then Print
Print Using " ###"; num;
End If
cont += 1
End If
num += 1
Wend
Print !"\n\nDe los primeros"; cont; " n£meros de Humble:"
num = 1
While num < cont
If humble(num) Then
Print Using " #### tienen ## digitos"; humble(num); num
num += 1
Else
Exit While
End If
Wend

View file

@ -0,0 +1,95 @@
package main
import (
"fmt"
"math/big"
)
var (
one = new(big.Int).SetUint64(1)
two = new(big.Int).SetUint64(2)
three = new(big.Int).SetUint64(3)
five = new(big.Int).SetUint64(5)
seven = new(big.Int).SetUint64(7)
ten = new(big.Int).SetUint64(10)
)
func min(a, b *big.Int) *big.Int {
if a.Cmp(b) < 0 {
return a
}
return b
}
func humble(n int) []*big.Int {
h := make([]*big.Int, n)
h[0] = new(big.Int).Set(one)
next2, next3 := new(big.Int).Set(two), new(big.Int).Set(three)
next5, next7 := new(big.Int).Set(five), new(big.Int).Set(seven)
var i, j, k, l int
for m := 1; m < len(h); m++ {
h[m] = new(big.Int).Set(min(next2, min(next3, min(next5, next7))))
if h[m].Cmp(next2) == 0 {
i++
next2.Mul(two, h[i])
}
if h[m].Cmp(next3) == 0 {
j++
next3.Mul(three, h[j])
}
if h[m].Cmp(next5) == 0 {
k++
next5.Mul(five, h[k])
}
if h[m].Cmp(next7) == 0 {
l++
next7.Mul(seven, h[l])
}
}
return h
}
func commatize(n int) string {
s := fmt.Sprintf("%d", n)
le := len(s)
for i := le - 3; i >= 1; i -= 3 {
s = s[0:i] + "," + s[i:]
}
return s
}
func main() {
const n = 13 * 1e6 // calculate the first 13 million humble numbers, say
h := humble(n)
fmt.Println("The first 50 humble numbers are:")
fmt.Println(h[0:50])
maxDigits := len(h[len(h)-1].String()) - 1
counts := make([]int, maxDigits+1)
var maxUsed int
digits := 1
pow10 := new(big.Int).Set(ten)
for i := 0; i < len(h); i++ {
for {
if h[i].Cmp(pow10) >= 0 {
pow10.Mul(pow10, ten)
digits++
} else {
break
}
}
if digits > maxDigits {
maxUsed = i
break
}
counts[digits]++
}
fmt.Printf("\nOf the first %s humble numbers:\n", commatize(maxUsed))
for i := 1; i <= maxDigits; i++ {
s := "s"
if i == 1 {
s = ""
}
fmt.Printf("%9s have %2d digit%s\n", commatize(counts[i]), i, s)
}
}

View file

@ -0,0 +1,27 @@
import Data.Set (deleteFindMin, fromList, union)
import Data.List.Split (chunksOf)
import Data.List (group)
import Data.Bool (bool)
--------------------- HUMBLE NUMBERS ----------------------
humbles :: [Integer]
humbles = go $ fromList [1]
where
go sofar = x : go (union pruned $ fromList ((x *) <$> [2, 3, 5, 7]))
where
(x, pruned) = deleteFindMin sofar
-- humbles = filter (all (< 8) . primeFactors) [1 ..]
-------------------------- TEST ---------------------------
main :: IO ()
main = do
putStrLn "First 50 Humble numbers:"
mapM_ (putStrLn . concat) $
chunksOf 10 $ justifyRight 4 ' ' . show <$> take 50 humbles
putStrLn "\nCount of humble numbers for each digit length 1-25:"
mapM_ print $
take 25 $ ((,) . head <*> length) <$> group (length . show <$> humbles)
------------------------- DISPLAY -------------------------
justifyRight :: Int -> a -> [a] -> [a]
justifyRight n c = (drop . length) <*> (replicate n c ++)

View file

@ -0,0 +1,93 @@
{-# OPTIONS_GHC -O2 #-}
import Data.Word (Word16)
import Data.Bits (shiftR, (.&.))
import Data.Function (fix)
import Data.List (group, intercalate)
import Data.Time.Clock.POSIX (getPOSIXTime)
--------------------- HUMBLE NUMBERS ----------------------
data LogRep = LogRep {-# UNPACK #-} !Double
{-# UNPACK #-} !Word16
{-# UNPACK #-} !Word16
{-# UNPACK #-} !Word16
{-# UNPACK #-} !Word16 deriving Show
instance Eq LogRep where
(==) (LogRep la _ _ _ _) (LogRep lb _ _ _ _) = la == lb
instance Ord LogRep where
(<=) (LogRep la _ _ _ _) (LogRep lb _ _ _ _) = la <= lb
logrep2Integer :: LogRep -> Integer
logrep2Integer (LogRep _ w x y z) = xpnd 2 w $ xpnd 3 x $ xpnd 5 y $ xpnd 7 z 1 where
xpnd m v = go v m where
go i mlt acc =
if i <= 0 then acc else
go (i `shiftR` 1) (mlt * mlt) (if i .&. 1 == 0 then acc else acc * mlt)
cOneLR :: LogRep
cOneLR = LogRep 0.0 0 0 0 0
cLgOf2 :: Double
cLgOf2 = logBase 10 2
cLgOf3 :: Double
cLgOf3 = logBase 10 3
cLgOf5 :: Double
cLgOf5 = logBase 10 5
cLgOf7 :: Double
cLgOf7 = logBase 10 7
cLgOf10 :: Double
cLgOf10 = cLgOf2 + cLgOf5
mulLR2 :: LogRep -> LogRep
mulLR2 (LogRep lg w x y z) = LogRep (lg + cLgOf2) (w + 1) x y z
mulLR3 :: LogRep -> LogRep
mulLR3 (LogRep lg w x y z) = LogRep (lg + cLgOf3) w (x + 1) y z
mulLR5 :: LogRep -> LogRep
mulLR5 (LogRep lg w x y z) = LogRep (lg + cLgOf5) w x (y + 1) z
mulLR7 :: LogRep -> LogRep
mulLR7 (LogRep lg w x y z) = LogRep (lg + cLgOf7) w x y (z + 1)
humbleLRs :: () -> [LogRep]
humbleLRs() = cOneLR : foldr u [] [mulLR2, mulLR3, mulLR5, mulLR7] where
u nmf s = fix (merge s . map nmf . (cOneLR:)) where
merge a [] = a
merge [] b = b
merge a@(x:xs) b@(y:ys) | x < y = x : merge xs b
| otherwise = y : merge a ys
-------------------------- TEST ---------------------------
main :: IO ()
main = do
putStrLn "First 50 Humble numbers:"
mapM_ (putStrLn . concat) $
chunksOf 10 $ justifyRight 4 ' ' . show <$> take 50 (map logrep2Integer $ humbleLRs())
strt <- getPOSIXTime
putStrLn "\nCount of humble numbers for each digit length 1-255:"
putStrLn "Digits Count Accum"
mapM_ putStrLn $ take 255 $ groupFormat $ humbleLRs()
stop <- getPOSIXTime
putStrLn $ "Counting took " ++ show (1.0 * (stop - strt)) ++ " seconds."
------------------------- DISPLAY -------------------------
chunksOf :: Int -> [a] -> [[a]]
chunksOf n = go where
go [] = []
go ilst = take n ilst : go (drop n ilst)
justifyRight :: Int -> a -> [a] -> [a]
justifyRight n c = (drop . length) <*> (replicate n c ++)
commaString :: String -> String
commaString =
let grpsOf3 [] = []
grpsOf3 is = let (frst, rest) = splitAt 3 is in frst : grpsOf3 rest
in reverse . intercalate "," . grpsOf3 . reverse
groupFormat :: [LogRep] -> [String]
groupFormat = go (0 :: Int) (0 :: Int) 0 where
go _ _ _ [] = []
go i cnt cacc ((LogRep lg _ _ _ _) : lrtl) =
let nxt = truncate (lg / cLgOf10) :: Int in
if nxt == i then go i (cnt + 1) cacc lrtl else
let ni = i + 1
ncacc = cacc + cnt
str = justifyRight 4 ' ' (show ni) ++
justifyRight 14 ' ' (commaString $ show cnt) ++
justifyRight 19 ' ' (commaString $ show ncacc)
in str : go ni 1 ncacc lrtl

View file

@ -0,0 +1,95 @@
{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE FlexibleContexts #-}
import Data.Word (Word64)
import Data.Bits (shiftR)
import Data.Function (fix)
import Data.Array.Unboxed (UArray, elems)
import Data.Array.Base (MArray(newArray, unsafeRead, unsafeWrite))
import Data.Array.IO (IOUArray)
import Data.List (intercalate)
import Data.Time.Clock.POSIX (getPOSIXTime)
import Data.Array.Unsafe (unsafeFreeze)
cNumDigits :: Int
cNumDigits = 877
cShift :: Int
cShift = 50
cFactor :: Word64
cFactor = 2^cShift
cLogOf10 :: Word64
cLogOf10 = cFactor
cLogOf7 :: Word64
cLogOf7 = round $ (logBase 10 7 :: Double) * fromIntegral cFactor
cLogOf5 :: Word64
cLogOf5 = round $ (logBase 10 5 :: Double) * fromIntegral cFactor
cLogOf3 :: Word64
cLogOf3 = round $ (logBase 10 3 :: Double) * fromIntegral cFactor
cLogOf2 :: Word64
cLogOf2 = cLogOf10 - cLogOf5
cLogLmt :: Word64
cLogLmt = fromIntegral cNumDigits * cLogOf10
humbles :: () -> [Integer]
humbles() = 1 : foldr u [] [2,3,5,7] where
u n s = fix (merge s . map (n*) . (1:)) where
merge a [] = a
merge [] b = b
merge a@(x:xs) b@(y:ys) | x < y = x : merge xs b
| otherwise = y : merge a ys
-------------------------- TEST ---------------------------
main :: IO ()
main = do
putStrLn "First 50 humble numbers:"
mapM_ (putStrLn . concat) $
chunksOf 10 $ justifyRight 4 ' ' . show <$> take 50 (humbles())
putStrLn $ "\nCount of humble numbers for each digit length 1-"
++ show cNumDigits ++ ":"
putStrLn "Digits Count Accum"
strt <- getPOSIXTime
mbins <- newArray (0, cNumDigits - 1) 0 :: IO (IOUArray Int Int)
let loopw w =
if w >= cLogLmt then return () else
let loopx x =
if x >= cLogLmt then loopw (w + cLogOf2) else
let loopy y =
if y >= cLogLmt then loopx (x + cLogOf3) else
let loopz z =
if z >= cLogLmt then loopy (y + cLogOf5) else do
let ndx = fromIntegral (z `shiftR` cShift)
v <- unsafeRead mbins ndx
unsafeWrite mbins ndx (v + 1)
loopz (z + cLogOf7) in loopz y in loopy x in loopx w
loopw 0
stop <- getPOSIXTime
bins <- unsafeFreeze mbins :: IO (UArray Int Int)
mapM_ putStrLn $ format $ elems bins
putStrLn $ "Counting took " ++ show (realToFrac (stop - strt)) ++ " seconds."
------------------------- DISPLAY -------------------------
chunksOf :: Int -> [a] -> [[a]]
chunksOf n = go where
go [] = []
go ilst = take n ilst : go (drop n ilst)
justifyRight :: Int -> a -> [a] -> [a]
justifyRight n c = (drop . length) <*> (replicate n c ++)
commaString :: String -> String
commaString =
let grpsOf3 [] = []
grpsOf3 s = let (frst, rest) = splitAt 3 s in frst : grpsOf3 rest
in reverse . intercalate "," . grpsOf3 . reverse
format :: [Int] -> [String]
format = go (0 :: Int) 0 where
go _ _ [] = []
go i cacc (hd : tl) =
let ni = i + 1
ncacc = cacc + hd
str = justifyRight 4 ' ' (show ni) ++
justifyRight 14 ' ' (commaString $ show hd) ++
justifyRight 19 ' ' (commaString $ show ncacc)
in str : go ni ncacc tl

View file

@ -0,0 +1,8 @@
humble=: 4 : 0
NB. x humble y generates x humble numbers based on factors y
result=. , 1
while. x > # result do.
a=. , result */ y
result=. result , <./ a #~ a > {: result
end.
)

View file

@ -0,0 +1,9 @@
FACTORS_h_=: p: i. 4
HUMBLE_h_=: 1
next_h_=: 3 : 0
result=. <./ HUMBLE
i=. HUMBLE i. result
HUMBLE=: ~. (((i&{.) , (>:i)&}.) HUMBLE) , result * FACTORS
result
)
reset_h_=: 3 :'0 $ HUMBLE=: 1'

View file

@ -0,0 +1,63 @@
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HumbleNumbers {
public static void main(String[] args) {
System.out.println("First 50 humble numbers:");
System.out.println(Arrays.toString(humble(50)));
Map<Integer,Integer> lengthCountMap = new HashMap<>();
BigInteger[] seq = humble(1_000_000);
for ( int i = 0 ; i < seq.length ; i++ ) {
BigInteger humbleNumber = seq[i];
int len = humbleNumber.toString().length();
lengthCountMap.merge(len, 1, (v1, v2) -> v1 + v2);
}
List<Integer> sorted = new ArrayList<>(lengthCountMap.keySet());
Collections.sort(sorted);
System.out.printf("Length Count%n");
for ( Integer len : sorted ) {
System.out.printf(" %2s %5s%n", len, lengthCountMap.get(len));
}
}
private static BigInteger[] humble(int n) {
BigInteger two = BigInteger.valueOf(2);
BigInteger twoTest = two;
BigInteger three = BigInteger.valueOf(3);
BigInteger threeTest = three;
BigInteger five = BigInteger.valueOf(5);
BigInteger fiveTest = five;
BigInteger seven = BigInteger.valueOf(7);
BigInteger sevenTest = seven;
BigInteger[] results = new BigInteger[n];
results[0] = BigInteger.ONE;
int twoIndex = 0, threeIndex = 0, fiveIndex = 0, sevenIndex = 0;
for ( int index = 1 ; index < n ; index++ ) {
results[index] = twoTest.min(threeTest).min(fiveTest).min(sevenTest);
if ( results[index].compareTo(twoTest) == 0 ) {
twoIndex++;
twoTest = two.multiply(results[twoIndex]);
}
if (results[index].compareTo(threeTest) == 0 ) {
threeIndex++;
threeTest = three.multiply(results[threeIndex]);
}
if (results[index].compareTo(fiveTest) == 0 ) {
fiveIndex++;
fiveTest = five.multiply(results[fiveIndex]);
}
if (results[index].compareTo(sevenTest) == 0 ) {
sevenIndex++;
sevenTest = seven.multiply(results[sevenIndex]);
}
}
return results;
}
}

View file

@ -0,0 +1,235 @@
(() => {
'use strict';
// ------------------ HUMBLE NUMBERS -------------------
// humbles :: () -> [Int]
function* humbles() {
// A non-finite stream of Humble numbers.
// OEIS A002473
const hs = new Set([1]);
while (true) {
let nxt = Math.min(...hs)
yield nxt;
hs.delete(nxt);
[2, 3, 5, 7].forEach(
x => hs.add(nxt * x)
);
}
};
// ----------------------- TEST ------------------------
// main :: IO ()
const main = () => {
console.log('First 50 humble numbers:\n')
chunksOf(10)(take(50)(humbles())).forEach(
row => console.log(
concat(row.map(compose(justifyRight(4)(' '), str)))
)
);
console.log(
'\nCounts of humble numbers of given digit lengths:'
);
const
counts = map(length)(
group(takeWhileGen(x => 11 > x)(
fmapGen(x => str(x).length)(
humbles()
)
))
);
console.log(
fTable('\n')(str)(str)(
i => counts[i - 1]
)(enumFromTo(1)(10))
);
};
// ----------------- GENERIC FUNCTIONS -----------------
// chunksOf :: Int -> [a] -> [[a]]
const chunksOf = n =>
xs => enumFromThenTo(0)(n)(
xs.length - 1
).reduce(
(a, i) => a.concat([xs.slice(i, (n + i))]),
[]
);
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
const compose = (...fs) =>
// A function defined by the right-to-left
// composition of all the functions in fs.
fs.reduce(
(f, g) => x => f(g(x)),
x => x
);
// concat :: [[a]] -> [a]
// concat :: [String] -> String
const concat = xs =>
0 < xs.length ? (() => {
const unit = 'string' !== typeof xs[0] ? (
[]
) : '';
return unit.concat.apply(unit, xs);
})() : [];
// enumFromThenTo :: Int -> Int -> Int -> [Int]
const enumFromThenTo = x1 =>
x2 => y => {
const d = x2 - x1;
return Array.from({
length: Math.floor(y - x2) / d + 2
}, (_, i) => x1 + (d * i));
};
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = m =>
n => Array.from({
length: 1 + n - m
}, (_, i) => m + i);
// fTable :: String -> (a -> String) -> (b -> String)
// -> (a -> b) -> [a] -> String
const fTable = s => xShow => fxShow => f => xs => {
// Heading -> x display function ->
// fx display function ->
// f -> values -> tabular string
const
ys = xs.map(xShow),
w = Math.max(...ys.map(length));
return s + '\n' + zipWith(
a => b => a.padStart(w, ' ') + ' -> ' + b
)(ys)(
xs.map(x => fxShow(f(x)))
).join('\n');
};
// fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b]
const fmapGen = f =>
function*(gen) {
let v = take(1)(gen);
while (0 < v.length) {
yield(f(v[0]))
v = take(1)(gen)
}
};
// group :: Eq a => [a] -> [[a]]
const group = xs => {
// A list of lists, each containing only equal elements,
// such that the concatenation of these lists is xs.
const go = xs =>
0 < xs.length ? (() => {
const
h = xs[0],
i = xs.findIndex(x => h !== x);
return i !== -1 ? (
[xs.slice(0, i)].concat(go(xs.slice(i)))
) : [xs];
})() : [];
const v = go(list(xs));
return 'string' === typeof xs ? (
v.map(x => x.join(''))
) : v;
};
// justifyRight :: Int -> Char -> String -> String
const justifyRight = n =>
// The string s, preceded by enough padding (with
// the character c) to reach the string length n.
c => s => n > s.length ? (
s.padStart(n, c)
) : s;
// length :: [a] -> Int
const length = xs =>
// Returns Infinity over objects without finite length.
// This enables zip and zipWith to choose the shorter
// argument when one is non-finite, like cycle, repeat etc
(Array.isArray(xs) || 'string' === typeof xs) ? (
xs.length
) : Infinity;
// list :: StringOrArrayLike b => b -> [a]
const list = xs =>
// xs itself, if it is an Array,
// or an Array derived from xs.
Array.isArray(xs) ? (
xs
) : Array.from(xs);
// map :: (a -> b) -> [a] -> [b]
const map = f =>
// The list obtained by applying f
// to each element of xs.
// (The image of xs under f).
xs => [...xs].map(f);
// str :: a -> String
const str = x =>
x.toString();
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = n => xs =>
'GeneratorFunction' !== xs.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], Array.from({
length: n
}, () => {
const x = xs.next();
return x.done ? [] : [x.value];
}));
// takeWhileGen :: (a -> Bool) -> Gen [a] -> [a]
const takeWhileGen = p => xs => {
const ys = [];
let
nxt = xs.next(),
v = nxt.value;
while (!nxt.done && p(v)) {
ys.push(v);
nxt = xs.next();
v = nxt.value
}
return ys;
};
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = f =>
// Use of `take` and `length` here allows zipping with non-finite lists
// i.e. generators like cycle, repeat, iterate.
xs => ys => {
const n = Math.min(length(xs), length(ys));
return Infinity > n ? (
(([as, bs]) => Array.from({
length: n
}, (_, i) => f(as[i])(
bs[i]
)))([xs, ys].map(
compose(take(n), list)
))
) : zipWithGen(f)(xs)(ys);
};
// MAIN ---
return main();
})();

View file

@ -0,0 +1,31 @@
# Input: a positive integer
# Output: true iff the input is humble
def humble:
. as $i
| if ($i < 2) then true
elif ($i % 2 == 0) then ($i / 2 | floor) | humble
elif ($i % 3 == 0) then ($i / 3 | floor) | humble
elif ($i % 5 == 0) then ($i / 5 | floor) | humble
elif ($i % 7 == 0) then ($i / 7 | floor) | humble
else false
end;
def task($digits; $count):
{len: 0, i:0, count: 0}
| until( .len > $digits;
.i += 1
| if (.i|humble)
then .len = (.i | tostring | length)
| if .len <= $digits
then .humble[.len] += 1
| if .count < $count then .count += 1 | .humbles += [.i] else . end
else .
end
else .
end)
| "First \($count):", .humbles,
"Distribution of the number of decimal digits up to \($digits) digits:",
(.humble | range(1;length) as $i | " \($i): \(.[$i])") ;
task(6; 50)

View file

@ -0,0 +1,24 @@
# A generator
def humbles($digits):
def update:
.[0] as $h
| ([$h * 2, $h * 3, $h * 5, $h * 7] | map(select(tostring|length <= $digits))) as $next
| if $next == [] then .[1:]
else (.[1:] + $next) | sort
end;
def trim: if length <= 1 then . elif .[0]==.[1] then .[1:]|trim else . end;
{ queue: [1]}
| recurse( select( .queue != [] )
| .h = .queue[0]
| queue |= (update|trim) )
| .h ;
def distribution(stream):
reduce stream as $i ([]; .[$i|tostring|length-1]+=1);
def task($digits):
"Distribution of the number of decimal digits up to \($digits) digits:",
(distribution(humbles($digits)) | range(0;length) as $i | " \($i+1): \(.[$i])") ;
task(16)

View file

@ -0,0 +1,42 @@
function counthumbledigits(maxdigits, returnsequencelength=50)
n, count, adjustindex, maxdiff = BigInt(1), 0, BigInt(0), 0
humble, savesequence = Vector{BigInt}([1]), Vector{BigInt}()
base2, base3, base5, base7 = 1, 1, 1, 1
next2, next3, next5, next7 = BigInt(2), BigInt(3), BigInt(5), BigInt(7)
digitcounts= Dict{Int, Int}(1 => 1)
while n < BigInt(10)^(maxdigits+1)
n = min(next2, next3, next5, next7)
push!(humble, n)
count += 1
if count == returnsequencelength
savesequence = deepcopy(humble[1:returnsequencelength])
elseif count > 2000000
popfirst!(humble)
adjustindex += 1
end
placesbase10 = length(string(n))
if haskey(digitcounts, placesbase10)
digitcounts[placesbase10] += 1
else
digitcounts[placesbase10] = 1
end
maxdiff = max(maxdiff, count - base2, count - base3, count - base5, count - base7)
(next2 <= n) && (next2 = 2 * humble[(base2 += 1) - adjustindex])
(next3 <= n) && (next3 = 3 * humble[(base3 += 1) - adjustindex])
(next5 <= n) && (next5 = 5 * humble[(base5 += 1) - adjustindex])
(next7 <= n) && (next7 = 7 * humble[(base7 += 1) - adjustindex])
end
savesequence, digitcounts, count, maxdiff
end
counthumbledigits(3)
@time first120, digitcounts, count, maxdiff = counthumbledigits(99)
println("\nTotal humble numbers counted: $count")
println("Maximum depth between top of array and a multiplier: $maxdiff\n")
println("The first 50 humble numbers are: $first120\n\nDigit counts of humble numbers:")
for ndigits in sort(collect(keys(digitcounts)))[1:end-1]
println(lpad(digitcounts[ndigits], 10), " have ", lpad(ndigits, 3), " digits.")
end

View file

@ -0,0 +1,40 @@
fun isHumble(i: Int): Boolean {
if (i <= 1) return true
if (i % 2 == 0) return isHumble(i / 2)
if (i % 3 == 0) return isHumble(i / 3)
if (i % 5 == 0) return isHumble(i / 5)
if (i % 7 == 0) return isHumble(i / 7)
return false
}
fun main() {
val limit: Int = Short.MAX_VALUE.toInt()
val humble = mutableMapOf<Int, Int>()
var count = 0
var num = 1
while (count < limit) {
if (isHumble(num)) {
val str = num.toString()
val len = str.length
humble.merge(len, 1) { a, b -> a + b }
if (count < 50) print("$num ")
count++
}
num++
}
println("\n")
println("Of the first $count humble numbers:")
num = 1
while (num < humble.size - 1) {
if (humble.containsKey(num)) {
val c = humble[num]
println("%5d have %2d digits".format(c, num))
num++
} else {
break
}
}
}

View file

@ -0,0 +1,53 @@
function isHumble(n)
local n2 = math.floor(n)
if n2 <= 1 then
return true
end
if n2 % 2 == 0 then
return isHumble(n2 / 2)
end
if n2 % 3 == 0 then
return isHumble(n2 / 3)
end
if n2 % 5 == 0 then
return isHumble(n2 / 5)
end
if n2 % 7 == 0 then
return isHumble(n2 / 7)
end
return false
end
function main()
local limit = 10000
local humble = {0, 0, 0, 0, 0, 0, 0, 0, 0}
local count = 0
local num = 1
while count < limit do
if isHumble(num) then
local buffer = string.format("%d", num)
local le = string.len(buffer)
if le > 9 then
break
end
humble[le] = humble[le] + 1
if count < 50 then
io.write(num .. " ")
end
count = count + 1
end
num = num + 1
end
print("\n")
print("Of the first " .. count .. " humble numbers:")
for num=1,9 do
print(string.format("%5d have %d digits", humble[num], num))
end
end
main()

View file

@ -0,0 +1,10 @@
HumbleGenerator[max_] :=
Sort[Flatten@ParallelTable[
2^i 3^j 5^k 7^m, {i, 0, Log[2, max]}, {j, 0, Log[3, max/2^i]}, {k,
0, Log[5, max/(2^i 3^j)]}, {m, 0, Log[7, max/(2^i 3^j 5^k)]}]]
{"First 50 Humble Numbers:",
HumbleGenerator[120],
"\nDigits\[Rule]Count",
Rule @@@ Tally[IntegerLength /@ Drop[HumbleGenerator[10^100], -1]] //
Column} // Column

View file

@ -0,0 +1,58 @@
import sets, strformat
proc min[T](s: HashSet[T]): T =
## Return the minimal value in a set.
if s.card == 0:
raise newException(ValueError, "set is empty.")
result = T.high
for n in s:
if n < result: result = n
iterator humbleNumbers(): Positive =
## Yield the successive humble numbers.
var s = [1].toHashSet()
while true:
let m = min(s)
yield m
s.excl(m)
for k in [2, 3, 5, 7]: s.incl(k * m)
proc showHumbleNumbers(maxCount: Positive) =
## Show the first "maxCount" humble numbers.
var currCount = 0
for n in humbleNumbers():
stdout.write n
inc currCount
if currCount == maxCount: break
stdout.write ' '
echo ""
proc showHumbleCount(ndigits: Positive) =
## Show the number of humble numbers with "n <= ndigits" digits.
echo "Digits Count"
echo "------ -----"
var currdigits = 1
var count = 0
var next = 10 # First number with "currdigits + 1" digits.
for n in humbleNumbers():
if n >= next:
# Number of digits has changed.
echo &" {currdigits:2d} {count:5d}"
inc currdigits
if currdigits > ndigits: break
next *= 10
count = 1
else:
inc count
when isMainModule:
echo "First 50 humble numbers:"
showHumbleNumbers(50)
echo ""
echo "Count of humble numbers with n digits:"
showHumbleCount(18)

View file

@ -0,0 +1,89 @@
import std/math, std/strutils
from std/times import inMilliseconds
from std/monotimes import getMonoTime, `-`
let lgshft = 50; let lg10 = 1'u64 shl lgshft; let fac = 2'f64.pow lgshft.float64
let lg7 = (7'f64.log10 * fac).round.uint64
let lg5 = (5'f64.log10 * fac).round.uint64
let lg3 = (3'f64.log10 * fac).round.uint64; let lg2 = lg10 - lg5
proc lr2UInt64(lr: uint64): uint64 = pow(10, (lr.float64 / fac)).round.uint64
iterator humblesLogQ(): uint64 = # {.closure.} =
var hd2 = lg2; var hd3 = lg3; var hd5 = lg5; var hd7 = lg7
var s2msk, s2hdi, s2tli, s3msk, s3hdi, s3tli, s5msk, s5hdi, s5tli = 0
var s2 = newSeq[uint64] 0
var s3 = newSeq[uint64] 0
var s5 = newSeq[uint64] 0
yield 0'u64
while true:
yield hd2
if s2tli == s2hdi:
let osz = if s2msk == 0: 512 else: s2msk + 1
s2.setLen (osz + osz); s2msk = s2.len - 1
if osz > 512:
if s2hdi == 0: s2tli = osz
else: # put extra space between tail and head...
copyMem(addr(s2[s2hdi + osz]), addr(s2[s2hdi]),
sizeof(uint64) * (osz - s2hdi)); s2hdi += osz
s2[s2tli] = hd2 + lg2; s2tli = (s2tli + 1) and s2msk
hd2 = s2[s2hdi]
if hd2 < hd3: s2hdi = (s2hdi + 1) and s2msk
else:
hd2 = hd3
if s3tli == s3hdi:
let osz = if s3msk == 0: 512 else: s3msk + 1
s3.setLen (osz + osz); s3msk = s3.len - 1
if osz > 512:
if s3hdi == 0: s3tli = osz
else: # put extra space between tail and head...
copyMem(addr(s3[s3hdi + osz]), addr(s3[s3hdi]),
sizeof(uint64) * (osz - s3hdi)); s3hdi += osz
s3[s3tli] = hd3 + lg3; s3tli = (s3tli + 1) and s3msk
hd3 = s3[s3hdi]
if hd3 < hd5: s3hdi = (s3hdi + 1) and s3msk
else:
hd3 = hd5
if s5tli == s5hdi:
let osz = if s5msk == 0: 512 else: s5msk + 1
s5.setLen (osz + osz); s5msk = s5.len - 1
if osz > 512:
if s5hdi == 0: s5tli = osz
else: # put extra space between tail and head...
copyMem(addr(s5[s5hdi + osz]), addr(s5[s5hdi]),
sizeof(uint64) * (osz - s5hdi)); s5hdi += osz
s5[s5tli] = hd5 + lg5; s5tli = (s5tli + 1) and s5msk
hd5 = s5[s5hdi]
if hd5 < hd7: s5hdi = (s5hdi + 1) and s5msk
else: hd5 = hd7; hd7 += lg7
proc commaString(s: string): string =
let sz = s.len; let sqlen = (sz + 2) div 3
var sq = newSeq[string](sqlen); var ndx = sqlen - 1
for i in countdown(sz - 1, 0, 3): sq[ndx] = s[(max(i-2, 0) .. i)]; ndx -= 1
sq.join ","
# testing it...
let numdigits = 255.uint64
echo "First 50 Humble numbers:"
var cnt = 0
for h in humblesLogQ():
stdout.write $h.lr2UInt64, " "; cnt += 1
if cnt >= 50: break
echo "\r\nCount of humble numbers for each digit length 1-", $numdigits, ":"
echo "Digits Count Accum"
let lmt = lg10 * numdigits
let strt = getMonoTime()
var cdigits = 0'u64; cnt = 0; var acnt = 0.int
for h in humblesLogQ():
if (h shr lgshft) <= cdigits: cnt += 1
else:
cdigits += 1; acnt += cnt
echo ($cdigits).align(4) & ($cnt).commaString.align(14) &
($acnt).commaString.align(19)
cnt = 1
if cdigits >= numdigits: break
let elpsd = (getMonoTime() - strt).inMilliseconds
echo "Counting took ", elpsd, " milliseconds."

View file

@ -0,0 +1,91 @@
import std/math, std/strutils
from std/times import inMilliseconds
from std/monotimes import getMonoTime, `-`
let lgshft = 50; let lg10 = 1'u64 shl lgshft; let fac = 2'f64.pow lgshft.float64
let lg7 = (7'f64.log10 * fac).round.uint64
let lg5 = (5'f64.log10 * fac).round.uint64
let lg3 = (3'f64.log10 * fac).round.uint64; let lg2 = lg10 - lg5
proc lr2UInt64(lr: uint64): uint64 = pow(10, (lr.float64 / fac)).round.uint64
iterator humblesLogQ(): uint64 = # {.closure.} =
var hd2 = lg2; var hd3 = lg3; var hd5 = lg5; var hd7 = lg7
var s2msk, s2hdi, s2tli, s3msk, s3hdi, s3tli, s5msk, s5hdi, s5tli = 0
var s2 = newSeq[uint64] 0
var s3 = newSeq[uint64] 0
var s5 = newSeq[uint64] 0
yield 0'u64
while true:
yield hd2
if s2tli == s2hdi:
let osz = if s2msk == 0: 512 else: s2msk + 1
s2.setLen (osz + osz); s2msk = s2.len - 1
if osz > 512:
if s2hdi == 0: s2tli = osz
else: # put extra space between tail and head...
copyMem(addr(s2[s2hdi + osz]), addr(s2[s2hdi]),
sizeof(uint64) * (osz - s2hdi)); s2hdi += osz
s2[s2tli] = hd2 + lg2; s2tli = (s2tli + 1) and s2msk
hd2 = s2[s2hdi]
if hd2 < hd3: s2hdi = (s2hdi + 1) and s2msk
else:
hd2 = hd3
if s3tli == s3hdi:
let osz = if s3msk == 0: 512 else: s3msk + 1
s3.setLen (osz + osz); s3msk = s3.len - 1
if osz > 512:
if s3hdi == 0: s3tli = osz
else: # put extra space between tail and head...
copyMem(addr(s3[s3hdi + osz]), addr(s3[s3hdi]),
sizeof(uint64) * (osz - s3hdi)); s3hdi += osz
s3[s3tli] = hd3 + lg3; s3tli = (s3tli + 1) and s3msk
hd3 = s3[s3hdi]
if hd3 < hd5: s3hdi = (s3hdi + 1) and s3msk
else:
hd3 = hd5
if s5tli == s5hdi:
let osz = if s5msk == 0: 512 else: s5msk + 1
s5.setLen (osz + osz); s5msk = s5.len - 1
if osz > 512:
if s5hdi == 0: s5tli = osz
else: # put extra space between tail and head...
copyMem(addr(s5[s5hdi + osz]), addr(s5[s5hdi]),
sizeof(uint64) * (osz - s5hdi)); s5hdi += osz
s5[s5tli] = hd5 + lg5; s5tli = (s5tli + 1) and s5msk
hd5 = s5[s5hdi]
if hd5 < hd7: s5hdi = (s5hdi + 1) and s5msk
else: hd5 = hd7; hd7 += lg7
proc commaString(s: string): string =
let sz = s.len; let sqlen = (sz + 2) div 3
var sq = newSeq[string](sqlen); var ndx = sqlen - 1
for i in countdown(sz - 1, 0, 3): sq[ndx] = s[(max(i-2, 0) .. i)]; ndx -= 1
sq.join ","
# testing it...
let numdigits = 877.uint64
echo "First 50 Humble numbers:"
var cnt = 0
for h in humblesLogQ():
stdout.write $h.lr2UInt64, " "; cnt += 1
if cnt >= 50: break
echo "\r\nCount of humble numbers for each digit length 1-", $numdigits, ":"
echo "Digits Count Accum"
let lmt = lg10 * numdigits
let strt = getMonoTime()
var bins = newSeq[int](numdigits)
for w in countup(0'u64, lmt, lg7):
for x in countup(w, lmt, lg5):
for y in countup(x, lmt, lg3):
for z in countup(y, lmt, lg2):
bins[z shr lgshft] += 1
var a = 0
for i, c in bins:
a += c
echo ($(i + 1)).align(4) & ($c).commaString.align(14) &
($a).commaString.align(19)
let elpsd = (getMonoTime() - strt).inMilliseconds
echo "Counting took ", elpsd, " milliseconds."

View file

@ -0,0 +1,76 @@
100H: /* FIND SOME HUMBLE NUMBERS - NUMBERS WITH NO PRIME FACTORS ABOVE 7 */
BDOS: PROCEDURE( FN, ARG ); /* CP/M BDOS SYSTEM CALL */
DECLARE FN BYTE, ARG ADDRESS;
GOTO 5;
END BDOS;
PRINT$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
PRINT$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
PRINT$NL: PROCEDURE; CALL PRINT$STRING( .( 0DH, 0AH, '$' ) ); END;
PRINT$NUMBER: PROCEDURE( N );
DECLARE N ADDRESS;
DECLARE V ADDRESS, N$STR( 6 ) BYTE, W BYTE;
V = N;
W = LAST( N$STR );
N$STR( W ) = '$';
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
DO WHILE( ( V := V / 10 ) > 0 );
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
END;
CALL PRINT$STRING( .N$STR( W ) );
END PRINT$NUMBER;
MIN: PROCEDURE( A, B ) ADDRESS;
DECLARE ( A, B ) ADDRESS;
IF A < B THEN RETURN( A ); ELSE RETURN( B );
END MIN;
/* DISPLAY A STATISTIC ABOUT HUMBLE NUMBERS */
PRINT$H$STAT: PROCEDURE( S, D );
DECLARE ( S, D ) ADDRESS;
CALL PRINT$STRING( .'THERE ARE $' );
IF S < 10 THEN CALL PRINT$CHAR( ' ' );
IF S < 100 THEN CALL PRINT$CHAR( ' ' );
CALL PRINT$NUMBER( S );
CALL PRINT$STRING( .' HUMBLE NUMBERS WITH $' );
CALL PRINT$NUMBER( D );
CALL PRINT$STRING( .' DIGIT$' );
IF D > 1 THEN CALL PRINT$CHAR( 'S' );
CALL PRINT$NL;
END PRINT$H$STAT;
/* FIND AND PRINT HUMBLE NUMBERS */
DECLARE MAX$HUMBLE LITERALLY '400';
DECLARE H( MAX$HUMBLE ) ADDRESS;
DECLARE ( P2, P3, P5, P7, M
, LAST2, LAST3, LAST5, LAST7
, H1, H2, H3, H4, H5, H6, HPOS
) ADDRESS;
/* 1 IS THE FIRST HUMBLE NUMBER */
H( 0 ) = 1;
H1 = 0; H2 = 0; H3 = 0; H4 = 0; H5 = 0; H6 = 0;
LAST2 = 0; LAST3 = 0; LAST5 = 0; LAST7 = 0;
P2 = 2; P3 = 3; P5 = 5; P7 = 7;
DO HPOS = 1 TO MAX$HUMBLE - 1;
/* THE NEXT HUMBLE NUMBER IS THE LOWEST OF THE NEXT MULTIPLES OF */
/* 2, 3, 5, 7 */
M = MIN( MIN( MIN( P2, P3 ), P5 ), P7 );
H( HPOS ) = M;
IF M = P2 THEN P2 = 2 * H( LAST2 := LAST2 + 1 );
IF M = P3 THEN P3 = 3 * H( LAST3 := LAST3 + 1 );
IF M = P5 THEN P5 = 5 * H( LAST5 := LAST5 + 1 );
IF M = P7 THEN P7 = 7 * H( LAST7 := LAST7 + 1 );
END;
DO HPOS = 0 TO 49;
CALL PRINT$CHAR( ' ' );
CALL PRINT$NUMBER( H( HPOS ) );
END;
CALL PRINT$NL;
DO HPOS = 0 TO MAX$HUMBLE - 1;
M = H( HPOS );
IF M < 10 THEN H1 = H1 + 1;
ELSE IF M < 100 THEN H2 = H2 + 1;
ELSE IF M < 1000 THEN H3 = H3 + 1;
ELSE IF M < 10000 THEN H4 = H4 + 1;
END;
CALL PRINT$H$STAT( H1, 1 );
CALL PRINT$H$STAT( H2, 2 );
CALL PRINT$H$STAT( H3, 3 );
CALL PRINT$H$STAT( H4, 4 );
EOF

View file

@ -0,0 +1,379 @@
{$IFDEF FPC}
{$MODE DELPHI}
{$OPTIMIZATION ON,ALL}
{$CODEALIGN proc=32,loop=1}
{$ALIGN 16}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
sysutils;
const
//PlInit(4); <= maxPrimFakCnt+1
maxPrimFakCnt = 3;//3,7,11 to keep data 8-Byte aligned
minElemCnt = 10;
type
tPrimList = array of NativeUint;
tnumber = extended;
tpNumber= ^tnumber;
tElem = record
n : tnumber;//ln(prime[0]^Pots[0]*...
dummy: array[0..5] of byte;//extend extended to 16 byte
Pots: array[0..maxPrimFakCnt] of word;
end;
tpElem = ^tElem;
tElems = array of tElem;
tElemArr = array [0..0] of tElem;
tpElemArr = ^tElemArr;
tpFaktorRec = ^tFaktorRec;
tFaktorRec = record
frElems : tElems;
frInsElems: tElems;
frAktIdx : NativeUint;
frMaxIdx : NativeUint;
frPotNo : NativeUint;
frActPot : NativeUint;
frNextFr : tpFaktorRec;
frActNumb: tElem;
frLnPrime: tnumber;
end;
tArrFR = array of tFaktorRec;
//LoE == List of Elements
function LoEGetNextElement(pFR :tpFaktorRec):tElem;forward;
var
Pl : tPrimList;
ActIndex : NativeUint;
ArrInsert : tElems;
procedure PlInit(n: integer);
const
cPl : array[0..11] of byte=(2,3,5,7,11,13,17,19,23,29,31,37);
var
i : integer;
Begin
IF n>High(cPl)+1 then
n := High(cPl)
else
IF n < 0 then
n := 1;
IF maxPrimFakCnt+1 < n then
Begin
writeln(' Need to compile with bigger maxPrimFakCnt ');
Halt(0);
end;
setlength(Pl,n);
dec(n);
For i := 0 to n do
Pl[i] := cPl[i];
end;
procedure AusgabeElem(pElem: tElem;ShowPot:Boolean=false);
var
i : integer;
Begin
with pElem do
Begin
IF n < 23 then
write(round(exp(n)),' ')
else
write('ln ',n:13:7);
IF ShowPot then
Begin
For i := 0 to maxPrimFakCnt do
write(' ',PL[i]:2,'^',Pots[i]);
writeln
end;
end;
end;
procedure LoECreate(const Pl: tPrimList;var FA:tArrFR);
var
i : integer;
Begin
setlength(ArrInsert,100);
setlength(FA,Length(PL));
For i := 0 to High(PL) do
with FA[i] do
Begin
//automatic zeroing
IF i < High(PL) then
Begin
setlength(frElems,minElemCnt);
setlength(frInsElems,minElemCnt);
frNextFr := @FA[i+1]
end
else
Begin
setlength(frElems,2);
setlength(frInsElems,0);
frNextFr := NIL;
end;
frPotNo := i;
frLnPrime:= ln(PL[i]);
frMaxIdx := 0;
frAktIdx := 0;
frActPot := 1;
With frElems[0] do
Begin
n := frLnPrime;
Pots[i]:= 1;
end;
frActNumb := frElems[0];
end;
ActIndex := 0;
end;
procedure LoEFree(var FA:tArrFR);
var
i : integer;
Begin
For i := High(FA) downto Low(FA) do
setlength(FA[i].frElems,0);
setLength(FA,0);
end;
function LoEGetActElem(pFr:tpFaktorRec):tElem;inline;
Begin
with pFr^ do
result := frElems[frAktIdx];
end;
function LoEGetActLstNumber(pFr:tpFaktorRec):tpNumber;inline;
Begin
with pFr^ do
result := @frElems[frAktIdx].n;
end;
procedure LoEIncInsArr(var a:tElems);
Begin
setlength(a,Length(a)*8 div 5);
end;
procedure LoEIncreaseElems(pFr:tpFaktorRec;minCnt:NativeUint);
var
newLen: NativeUint;
Begin
with pFR^ do
begin
newLen := Length(frElems);
minCnt := minCnt+frMaxIdx;
repeat
newLen := newLen*8 div 5 +1;
until newLen > minCnt;
setlength(frElems,newLen);
end;
end;
procedure LoEInsertNext(pFr:tpFaktorRec;Limit:tnumber);
var
pNum : tpNumber;
pElems : tpElemArr;
cnt,i,u : NativeInt;
begin
with pFr^ do
Begin
//collect numbers of heigher primes
cnt := 0;
pNum := LoEGetActLstNumber(frNextFr);
while Limit > pNum^ do
Begin
frInsElems[cnt] := LoEGetNextElement(frNextFr);
inc(cnt);
IF cnt > High(frInsElems) then
LoEIncInsArr(frInsElems);
pNum := LoEGetActLstNumber(frNextFr);
end;
if cnt = 0 then
EXIT;
i := frMaxIdx;
u := frMaxIdx+cnt+1;
IF u > High(frElems) then
LoEIncreaseElems(pFr,cnt);
IF frPotNo = 0 then
inc(ActIndex,u);
//Merge
pElems := @frElems[0];
dec(cnt);
dec(u);
frMaxIdx:= u;
repeat
IF pElems^[i].n < frInsElems[cnt].n then
Begin
pElems^[u] := frInsElems[cnt];
dec(cnt);
end
else
Begin
pElems^[u] := pElems^[i];
dec(i);
end;
dec(u);
until (i<0) or (cnt<0);
IF i < 0 then
For u := cnt downto 0 do
pElems^[u] := frInsElems[u];
end;
end;
procedure LoEAppendNext(pFr:tpFaktorRec;Limit:tnumber);
var
pNum : tpNumber;
pElems : tpElemArr;
i : NativeInt;
begin
with pFr^ do
Begin
i := frMaxIdx+1;
pElems := @frElems[0];
pNum := LoEGetActLstNumber(frNextFr);
while Limit > pNum^ do
Begin
IF i > High(frElems) then
Begin
LoEIncreaseElems(pFr,10);
pElems := @frElems[0];
end;
pElems^[i] := LoEGetNextElement(frNextFr);
inc(i);
pNum := LoEGetActLstNumber(frNextFr);
end;
inc(ActIndex,i);
frMaxIdx:= i-1;
end;
end;
procedure LoENextList(pFr:tpFaktorRec);
var
pElems : tpElemArr;
j,PotNum : NativeInt;
lnPrime : tnumber;
begin
with pFR^ do
Begin
//increase all Elements by factor
pElems := @frElems[0];
LnPrime := frLnPrime;
PotNum := frPotNo;
for j := frMaxIdx Downto 0 do
with pElems^[j] do
Begin
n := LnPrime+n;
inc(Pots[PotNum]);
end;
//x^j -> x^(j+1)
j := frActPot+1;
with frActNumb do
begin
n:= j*LnPrime;
Pots[PotNum]:= j;
end;
frActPot := j;
//if something follows
IF frNextFr <> NIL then
LoEInsertNext(pFR,frActNumb.n);
frAktIdx := 0;
end;
end;
function LoEGetNextElementPointer(pFR :tpFaktorRec):tpElem;
Begin
with pFr^ do
Begin
IF frMaxIdx < frAktIdx then
LoENextList(pFr);
result := @frElems[frAktIdx];
inc(frAktIdx);
inc(ActIndex);
end;
end;
function LoEGetNextElement(pFR :tpFaktorRec):tElem;
Begin
with pFr^ do
Begin
result := frElems[frAktIdx];
inc(frAktIdx);
IF frMaxIdx < frAktIdx then
LoENextList(pFr);
inc(ActIndex);
end;
end;
function LoEGetNextNumber(pFR :tpFaktorRec):tNumber;
Begin
with pFr^ do
Begin
result := frElems[frAktIdx].n;
inc(frAktIdx);
IF frMaxIdx < frAktIdx then
LoENextList(pFr);
inc(ActIndex);
end;
end;
procedure LoEGetNumber(pFR :tpFaktorRec;no:NativeUint);
Begin
dec(no);
while ActIndex < no do
LoENextList(pFR);
with pFr^ do
frAktIdx := (no-(ActIndex-frMaxIdx)-1);
end;
procedure first50;
var
FA: tArrFR;
i : integer;
Begin
LoECreate(Pl,FA);
write(1,' ');
For i := 1 to 49 do
AusgabeElem(LoEGetNextElement(@FA[0]));
writeln;
LoEFree(FA);
end;
procedure GetDigitCounts(MaxDigit:Uint32);
var
T1,T0 : TDateTime;
FA: tArrFR;
i,j,LastCnt : NativeUint;
Begin
T0 := now;
inc(MaxDigit);
LoECreate(Pl,FA);
i := 1;
j := 0;
writeln('Digits count total count ');
repeat
LastCnt := j;
repeat
inc(j);
with LoEGetNextElementPointer(@FA[0])^ do
IF (Pots[2]= i) AND (Pots[0]= i) then
break;
until false;
writeln(i:4,j-LastCnt:12,j:15,(now-T0)*86.6e3:10:3,' s');
LastCnt := j;
inc(i);
until i = MaxDigit;
LoEFree(FA);
T1 := now;
writeln('Total number of humble numbers found: ',j);
writeln('Running time: ',(T1-T0)*86.6e6:0:0,' ms');
end;
Begin
//check if PlInit(4); <= maxPrimFakCnt+1
PlInit(4);// 3 -> 2,3,5/ 4 -> 2,3,5,7
first50;
GetDigitCounts(100);
End.

View file

@ -0,0 +1,39 @@
use strict;
use warnings;
use List::Util 'min';
#use bigint # works, but slow
use Math::GMPz; # this module gives roughly 16x speed-up
sub humble_gen {
my @s = ([1], [1], [1], [1]);
my @m = (2, 3, 5, 7);
@m = map { Math::GMPz->new($_) } @m; # comment out to NOT use Math::GMPz
return sub {
my $n = min $s[0][0], $s[1][0], $s[2][0], $s[3][0];
for (0..3) {
shift @{$s[$_]} if $s[$_][0] == $n;
push @{$s[$_]}, $n * $m[$_]
}
return $n
}
}
my $h = humble_gen;
my $i = 0;
my $upto = 50;
my $list;
++$i, $list .= $h->(). " " until $i == $upto;
print "$list\n";
$h = humble_gen; # from the top...
my $count = 0;
my $digits = 1;
while ($digits <= $upto) {
++$count and next if $digits == length $h->();
printf "Digits: %2d - Count: %s\n", $digits++, $count;
$count = 1;
}

View file

@ -0,0 +1,60 @@
(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo/rosetta/humble.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">humble</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">countdigits</span><span style="color: #0000FF;">=</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- if countdigits is false: show first n humble numbers,
-- if countdigits is true: count them up to n digits.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">humble</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)},</span>
<span style="color: #000000;">nexts</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">indices</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> <span style="color: #000000;">nexts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nexts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">digits</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">dead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">tc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">p10</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #0000FF;">((</span><span style="color: #008080;">not</span> <span style="color: #000000;">countdigits</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">countdigits</span> <span style="color: #008080;">and</span> <span style="color: #000000;">digits</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init_set</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mpz_min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nexts</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">humble</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">countdigits</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p10</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">indices</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">dead</span> <span style="color: #008080;">to</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">humble</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">dead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">tc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">count</span>
<span style="color: #000080;font-style:italic;">-- e &= sprintf(", %,d dead",{dead-1})</span>
<span style="color: #000000;">e</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">", total:%,d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tc</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%,12d humble numbers have %d digit%s (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">digits</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nexts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">indices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nexts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">[</span><span style="color: #000000;">indices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]],</span><span style="color: #7060A8;">get_prime</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">countdigits</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">humble</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">ml</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"First %d humble numbers: %s\n\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">humble</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">humble</span><span style="color: #0000FF;">(</span><span style="color: #000000;">50</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">humble</span><span style="color: #0000FF;">(</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<!--

View file

@ -0,0 +1,69 @@
'''Humble numbers'''
from itertools import groupby, islice
from functools import reduce
# humbles :: () -> [Int]
def humbles():
'''A non-finite stream of Humble numbers.
OEIS A002473
'''
hs = set([1])
while True:
nxt = min(hs)
yield nxt
hs.remove(nxt)
hs.update(nxt * x for x in [2, 3, 5, 7])
# 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(10)(
(k, len(list(g))) for k, g in
groupby(len(str(x)) for x in 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 []
# 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))
)
# MAIN ---
if __name__ == '__main__':
main()

View file

@ -0,0 +1,11 @@
' [ 2 3 5 7 ] smoothwith
[ -1 peek [ 10 12 ** ] constant = ]
-1 split drop
dup 50 split drop echo cr cr
12 times
[ dup 0 over size
rot 10 i^ 1+ ** searchwith <
drop split swap size echo
sp i^ 1+ echo
say "-digit humble numbers" cr ]
drop

View file

@ -0,0 +1,44 @@
/*REXX program computes and displays humble numbers, also will display counts of sizes.*/
parse arg n m . /*obtain optional arguments from the CL*/
if n=='' | n=="," then n= 50 /*Not specified? Then use the default.*/
if m=='' | m=="," then m= 60 /* " " " " " " */
numeric digits 1 + max(20, m) /*be able to handle some big numbers. */
$.= 0 /*a count array for X digit humble #s*/
call humble n; list= /*call HUMBLE sub; initialize the list.*/
do j=1 for n; list= list @.j /*append a humble number to the list.*/
end /*j*/
if list\='' then do; say "A list of the first " n ' humble numbers are:'
say strip(list) /*elide the leading blank in the list. */
end
say
call humble -m /*invoke subroutine for counting nums. */
if $.1==0 then exit /*if no counts, then we're all finished*/
total= 0 /*initialize count of humble numbers. */
$.1= $.1 + 1 /*adjust count for absent 1st humble #.*/
say ' The digit counts of humble numbers:'
say ' '
do c=1 while $.c>0; s= left('s', length($.c)>1) /*count needs pluralization?*/
say right( commas($.c), 30) ' have ' right(c, 2) " digit"s
total= total + $.c /* ◄─────────────────────────────────┐ */
end /*k*/ /*bump humble number count (so far)──┘ */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: procedure; arg _; do i=length(_)-3 to 1 by -3; _=insert(',', _, i); end; return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
humble: procedure expose @. $.; parse arg x; if x==0 then return
y= abs(x); a= y; noCount= x>0; if x<0 then y= 999999999
#2= 1; #3= 1; #5= 1; #7= 1 /*define the initial humble constants. */
$.= 0; @.= 0; @.1= 1 /*initialize counts and humble numbers.*/
do h=2 for y-1
@.h= min(2*@.#2,3*@.#3,5*@.#5,7*@.#7) /*pick the minimum of 4 humble numbers.*/
m= @.h /*M: " " " " " " */
if 2*@.#2 == m then #2 = #2 + 1 /*Is number already defined? Use next #*/
if 3*@.#3 == m then #3 = #3 + 1 /* " " " " " " "*/
if 5*@.#5 == m then #5 = #5 + 1 /* " " " " " " "*/
if 7*@.#7 == m then #7 = #7 + 1 /* " " " " " " "*/
if noCount then iterate /*Not counting digits? Then iterate. */
L= length(m); if L>a then leave /*Are we done with counting? Then quit*/
$.L= $.L + 1 /*bump the digit count for this number.*/
end /*h*/ /*the humble numbers are in the @ array*/
return /* " count results " " " $ " */

View file

@ -0,0 +1,43 @@
#lang racket
(define (gen-humble-numbers N (kons #f) (k0 (void)))
(define rv (make-vector N 1))
(define (loop n 2-idx 3-idx 5-idx 7-idx next-2 next-3 next-5 next-7 k)
(if (= n N)
rv
(let ((mn (min next-2 next-3 next-5 next-7)))
(vector-set! rv n mn)
(define (add-1-if-min n x) (if (= mn n) (add1 x) x))
(define (*vr.i-if-min n m i) (if (= mn n) (* m (vector-ref rv i)) n))
(let* ((2-idx (add-1-if-min next-2 2-idx))
(next-2 (*vr.i-if-min next-2 2 2-idx))
(3-idx (add-1-if-min next-3 3-idx))
(next-3 (*vr.i-if-min next-3 3 3-idx))
(5-idx (add-1-if-min next-5 5-idx))
(next-5 (*vr.i-if-min next-5 5 5-idx))
(7-idx (add-1-if-min next-7 7-idx))
(next-7 (*vr.i-if-min next-7 7 7-idx))
(k (and kons (kons mn k))))
(loop (add1 n) 2-idx 3-idx 5-idx 7-idx next-2 next-3 next-5 next-7 k)))))
(loop 1 0 0 0 0 2 3 5 7 (and kons (kons 1 k0))))
(define ((digit-tracker breaker) h last-ten.count)
(let ((last-ten (car last-ten.count)))
(if (< h last-ten)
(cons last-ten (add1 (cdr last-ten.count)))
(begin
(printf "~a humble numbers with ~a digits~%" (cdr last-ten.count) (order-of-magnitude last-ten))
(cons (breaker (* 10 last-ten)) 1)))))
(define (Humble-numbers)
(displayln (gen-humble-numbers 50))
(time
(let/ec break
(void (gen-humble-numbers
100000000
(digit-tracker (λ (o) (if (> (order-of-magnitude o) 100) (break) o)))
'(10 . 0))))))
(module+ main
(Humble-numbers))

View file

@ -0,0 +1,30 @@
sub smooth-numbers (*@list) {
cache my \Smooth := gather {
my %i = (flat @list) Z=> (Smooth.iterator for ^@list);
my %n = (flat @list) Z=> 1 xx *;
loop {
take my $n := %n{*}.min;
for @list -> \k {
%n{k} = %i{k}.pull-one * k if %n{k} == $n;
}
}
}
}
my $humble := smooth-numbers(2,3,5,7);
put $humble[^50];
say '';
my $upto = 50;
my $digits = 1;
my $count;
$humble.map: -> \h {
++$count and next if h.chars == $digits;
printf "Digits: %2d - Count: %s\n", $digits++, $count;
$count = 1;
last if $digits > $upto;
}

View file

@ -0,0 +1,23 @@
load "stdlib.ring"
limit = 10
numList = []
for n2 = 0 to limit
for n3 = 0 to limit
for n5 = 0 to limit
for n7 = 0 to limit
num = pow(2,n2) * pow(3,n3) * pow(5,n5) * pow(7,n7)
add(numList,num)
next
next
next
next
numList = sort(numList)
see "The first 50 Humble numbers: " + nl
for n = 1 to 50
see "" + numList[n] + " "
next

View file

@ -0,0 +1,23 @@
def humble?(i)
while i % 2 == 0; i /= 2 end
while i % 3 == 0; i /= 3 end
while i % 5 == 0; i /= 5 end
while i % 7 == 0; i /= 7 end
i == 1
end
count, num = 0, 0
digits = 10 # max digits for humble numbers
limit = 10 ** digits # max numbers to search through
humble = Array.new(digits + 1, 0)
while (num += 1) < limit
if humble?(num)
humble[num.to_s.size] += 1
print num, " " if count < 50
count += 1
end
end
print "\n\nOf the first #{count} humble numbers:\n"
(1..digits).each { |num| printf("%5d have %2d digits\n", humble[num], num) }

View file

@ -0,0 +1,25 @@
def humble(digits)
h = [1]
x2, x3, x5, x7 = 2, 3, 5, 7
i, j, k, l = 0, 0, 0, 0
n = 0
while n += 1 # ruby => 2.6: (1..).each do |n|
x = [x2, x3, x5, x7].min
break if x.to_s.size > digits
h[n] = x
x2 = 2 * h[i += 1] if x2 == h[n]
x3 = 3 * h[j += 1] if x3 == h[n]
x5 = 5 * h[k += 1] if x5 == h[n]
x7 = 7 * h[l += 1] if x7 == h[n]
end
h
end
digits = 50 # max digits for humble numbers
h = humble(digits) # humble numbers <= digits size
count = h.size # the total humble numbers count
#counts = h.map { |n| n.to_s.size }.tally # hash of digits counts 1..digits: Ruby => 2.7
counts = h.map { |n| n.to_s.size }.group_by(&:itself).transform_values(&:size) # Ruby => 2.4
print "First 50 Humble Numbers: \n"; (0...50).each { |i| print "#{h[i]} " }
print "\n\nOf the first #{count} humble numbers:\n"
(1..digits).each { |num| printf("%6d have %2d digits\n", counts[num], num) }

View file

@ -0,0 +1,29 @@
func smooth_generator(primes) {
var s = primes.len.of { [1] }
{
var n = s.map { .first }.min
{ |i|
s[i].shift if (s[i][0] == n)
s[i] << (n * primes[i])
} * primes.len
n
}
}
with (smooth_generator([2,3,5,7])) {|g|
say 50.of { g.run }.join(' ')
}
say "\nThe digit counts of humble numbers"
say '═'*35
with (smooth_generator([2,3,5,7])) {|g|
for (var(d=1,c=0); d <= 20; ++c) {
var n = g.run
n.len > d || next
say "#{'%10s'%c.commify} have #{'%2d'%d} digit#{[:s,''][d==1]}"
(c, d) = (0, n.len)
}
}

View file

@ -0,0 +1,11 @@
proc humble? x {
foreach f {2 3 5 7} {
while {$x % $f == 0} {set x [expr {$x / $f}]}
}
return [expr {$x == 1}]
}
set t1 {}
for {set i 1} {[llength $t1] < 50} {incr i} {
if [humble? $i] {lappend t1 $i}
}
puts $t1

View file

@ -0,0 +1,12 @@
proc task2 {nmax} {
puts "Distribution of digit length for the first $nmax humble numbers"
set nHumble 0
for {set i 1} {$nHumble < $nmax} {incr i} {
if {[humble? $i]} {
incr nHumble
incr N([string length $i])
}
}
parray N
}
task2 4096

View file

@ -0,0 +1,62 @@
Module Module1
Function IsHumble(i As Long) As Boolean
If i <= 1 Then
Return True
End If
If i Mod 2 = 0 Then
Return IsHumble(i \ 2)
End If
If i Mod 3 = 0 Then
Return IsHumble(i \ 3)
End If
If i Mod 5 = 0 Then
Return IsHumble(i \ 5)
End If
If i Mod 7 = 0 Then
Return IsHumble(i \ 7)
End If
Return False
End Function
Sub Main()
Dim LIMIT = Short.MaxValue
Dim humble As New Dictionary(Of Integer, Integer)
Dim count = 0L
Dim num = 1L
While count < LIMIT
If (IsHumble(num)) Then
Dim str = num.ToString
Dim len = str.Length
If len > 10 Then
Exit While
End If
If humble.ContainsKey(len) Then
humble(len) += 1
Else
humble(len) = 1
End If
If count < 50 Then
Console.Write("{0} ", num)
End If
count += 1
End If
num += 1
End While
Console.WriteLine(vbNewLine)
Console.WriteLine("Of the first {0} humble numbers:", count)
num = 1
While num < humble.Count
If humble.ContainsKey(num) Then
Dim c = humble(num)
Console.WriteLine("{0,5} have {1,2} digits", c, num)
num += 1
Else
Exit While
End If
End While
End Sub
End Module

View file

@ -0,0 +1,62 @@
import "/fmt" for Fmt
import "/math" for Int, Nums
import "/sort" for Find
var humble = Fn.new { |n|
var h = List.filled(n, 0)
h[0] = 1
var next2 = 2
var next3 = 3
var next5 = 5
var next7 = 7
var i = 0
var j = 0
var k = 0
var l = 0
for (m in 1...n) {
h[m] = Nums.min([next2, next3, next5, next7])
if (h[m] == next2) {
i = i + 1
next2 = 2 * h[i]
}
if (h[m] == next3) {
j = j + 1
next3 = 3 * h[j]
}
if (h[m] == next5) {
k = k + 1
next5 = 5 * h[k]
}
if (h[m] == next7) {
l = l + 1
next7 = 7 * h[l]
}
}
return h
}
var n = 43000 // say
var h = humble.call(n)
System.print("The first 50 humble numbers are:")
System.print(h[0..49])
var f = Find.all(h, Int.maxSafe) // binary search
var maxUsed = f[0] ? f[2].min + 1 : f[2].min
var maxDigits = 16 // Int.maxSafe (2^53 -1) has 16 digits
var counts = List.filled(maxDigits + 1, 0)
var digits = 1
var pow10 = 10
for (i in 0...maxUsed) {
while (true) {
if (h[i] >= pow10) {
pow10 = pow10 * 10
digits = digits + 1
} else break
}
counts[digits] = counts[digits] + 1
}
System.print("\nOf the first %(Fmt.dc(0, maxUsed)) humble numbers:")
for (i in 1..maxDigits) {
var s = (i != 1) ? "s" : ""
System.print("%(Fmt.dc(9, counts[i])) have %(Fmt.d(2, i)) digit%(s)")
}

View file

@ -0,0 +1,37 @@
func Humble(N); \Return 'true' if N is a humble number
int N;
[if N = 1 then return true;
if rem(N/2) = 0 then return Humble(N/2);
if rem(N/3) = 0 then return Humble(N/3);
if rem(N/5) = 0 then return Humble(N/5);
if rem(N/7) = 0 then return Humble(N/7);
return false;
];
int N, C, D, P;
[N:= 1; C:= 0;
loop [if Humble(N) then
[C:= C+1;
IntOut(0, N); ChOut(0, ^ );
if C >= 50 then quit;
];
N:= N+1;
];
CrLf(0);
D:= 1; P:= 10; N:= 1; C:= 0;
loop [if Humble(N) then
[if N >= P then
[IntOut(0, D);
Text(0, ": ");
IntOut(0, C);
CrLf(0);
C:= 0;
D:= D+1;
if D > 9 then quit;
P:= P*10;
];
C:= C+1;
];
N:= N+1;
];
]

View file

@ -0,0 +1,18 @@
var [const] BI=Import("zklBigNum"); // libGMP
var one = BI(1), two = BI(2), three = BI(3),
five = BI(5), seven = BI(7);
fcn humble(n){ // --> List of BigInt Humble numbers
h:=List.createLong(n); h.append(one);
next2,next3 := two.copy(), three.copy();
next5,next7 := five.copy(), seven.copy();
reg i=0,j=0,k=0,l=0;
do(n-1){
h.append( hm:=BI(next2.min(next3.min(next5.min(next7)))) );
if(hm==next2) next2.set(two) .mul(h[i+=1]);
if(hm==next3) next3.set(three).mul(h[j+=1]);
if(hm==next5) next5.set(five) .mul(h[k+=1]);
if(hm==next7) next7.set(seven).mul(h[l+=1]);
}
h
}

View file

@ -0,0 +1,14 @@
fcn __main__{
const N = 5 * 1e6; // calculate the first 1 million humble numbers, say
h:=humble(N);
println("The first 50 humble numbers are:\n ",h[0,50].concat(" "));
counts:=Dictionary(); // tally the number of digits in each number
h.apply2('wrap(n){ counts.incV(n.numDigits) });
println("\nOf the first %,d humble numbers:".fmt(h.len()));
println("Digits Count");
foreach n in (counts.keys.apply("toInt").sort()){
println("%2d %,9d".fmt(n,counts[n], n));
}
}