Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
3
Task/Humble-numbers/00-META.yaml
Normal file
3
Task/Humble-numbers/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Humble_numbers
|
||||
note: Prime Numbers
|
||||
32
Task/Humble-numbers/00-TASK.txt
Normal file
32
Task/Humble-numbers/00-TASK.txt
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Humble numbers are positive integers which have no prime factors <big> > </big> '''7'''.
|
||||
|
||||
|
||||
Humble numbers are also called ''7-smooth numbers'', and sometimes called ''highly composite'',
|
||||
<br>although this conflicts with another meaning of ''highly composite numbers''.
|
||||
|
||||
|
||||
|
||||
Another way to express the above is:
|
||||
|
||||
<big><big> humble = 2<sup>i</sup> × 3<sup>j</sup> × 5<sup>k</sup> × 7<sup>m</sup> </big></big>
|
||||
|
||||
where <big> i, j, k, m <big>≥</big> 0 </big>
|
||||
|
||||
|
||||
;Task:
|
||||
:* show the first '''50''' humble numbers (in a horizontal list)
|
||||
:* show the number of humble numbers that have '''x''' decimal digits for all '''x's''' up to '''n''' (inclusive).
|
||||
:* show (as many as feasible or reasonable for above) on separate lines
|
||||
:* show all output here on this page
|
||||
|
||||
|
||||
;Related tasks:
|
||||
:* [[Hamming numbers]]
|
||||
|
||||
|
||||
;References:
|
||||
:* [[wp:Smooth_number#Definition_smooth_numbers|Wikipedia: Smooth numbers]], see the 2<sup>nd</sup> paragraph.
|
||||
:* [[oeis:A002473|OEIS A002473: humble numbers]]
|
||||
:* [http://www.informatik.uni-ulm.de/acm/Locals/1996/number.sol University of Ulm, The first 5842 terms of humble numbers]
|
||||
<br><br>
|
||||
|
||||
30
Task/Humble-numbers/11l/humble-numbers.11l
Normal file
30
Task/Humble-numbers/11l/humble-numbers.11l
Normal 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))
|
||||
45
Task/Humble-numbers/ALGOL-68/humble-numbers.alg
Normal file
45
Task/Humble-numbers/ALGOL-68/humble-numbers.alg
Normal 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
|
||||
65
Task/Humble-numbers/ALGOL-W/humble-numbers.alg
Normal file
65
Task/Humble-numbers/ALGOL-W/humble-numbers.alg
Normal 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.
|
||||
31
Task/Humble-numbers/AWK/humble-numbers.awk
Normal file
31
Task/Humble-numbers/AWK/humble-numbers.awk
Normal 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)
|
||||
}
|
||||
59
Task/Humble-numbers/Action-/humble-numbers.action
Normal file
59
Task/Humble-numbers/Action-/humble-numbers.action
Normal 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
|
||||
66
Task/Humble-numbers/Ada/humble-numbers.ada
Normal file
66
Task/Humble-numbers/Ada/humble-numbers.ada
Normal 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;
|
||||
60
Task/Humble-numbers/AutoHotkey/humble-numbers.ahk
Normal file
60
Task/Humble-numbers/AutoHotkey/humble-numbers.ahk
Normal 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
|
||||
}
|
||||
60
Task/Humble-numbers/C++/humble-numbers-1.cpp
Normal file
60
Task/Humble-numbers/C++/humble-numbers-1.cpp
Normal 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;
|
||||
}
|
||||
38
Task/Humble-numbers/C++/humble-numbers-2.cpp
Normal file
38
Task/Humble-numbers/C++/humble-numbers-2.cpp
Normal 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());
|
||||
}
|
||||
50
Task/Humble-numbers/C-sharp/humble-numbers-1.cs
Normal file
50
Task/Humble-numbers/C-sharp/humble-numbers-1.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Task/Humble-numbers/C-sharp/humble-numbers-2.cs
Normal file
42
Task/Humble-numbers/C-sharp/humble-numbers-2.cs
Normal 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)));
|
||||
}
|
||||
}
|
||||
42
Task/Humble-numbers/C-sharp/humble-numbers-3.cs
Normal file
42
Task/Humble-numbers/C-sharp/humble-numbers-3.cs
Normal 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
|
||||
}
|
||||
}
|
||||
48
Task/Humble-numbers/C/humble-numbers.c
Normal file
48
Task/Humble-numbers/C/humble-numbers.c
Normal 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;
|
||||
}
|
||||
24
Task/Humble-numbers/Crystal/humble-numbers-1.crystal
Normal file
24
Task/Humble-numbers/Crystal/humble-numbers-1.crystal
Normal 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) }
|
||||
25
Task/Humble-numbers/Crystal/humble-numbers-2.crystal
Normal file
25
Task/Humble-numbers/Crystal/humble-numbers-2.crystal
Normal 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) }
|
||||
42
Task/Humble-numbers/D/humble-numbers.d
Normal file
42
Task/Humble-numbers/D/humble-numbers.d
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
183
Task/Humble-numbers/Elm/humble-numbers.elm
Normal file
183
Task/Humble-numbers/Elm/humble-numbers.elm
Normal 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)
|
||||
}
|
||||
12
Task/Humble-numbers/F-Sharp/humble-numbers-1.fs
Normal file
12
Task/Humble-numbers/F-Sharp/humble-numbers-1.fs
Normal 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))))}
|
||||
1
Task/Humble-numbers/F-Sharp/humble-numbers-2.fs
Normal file
1
Task/Humble-numbers/F-Sharp/humble-numbers-2.fs
Normal file
|
|
@ -0,0 +1 @@
|
|||
humble |> Seq.take 50 |> Seq.iter (printf "%d ");printfn ""
|
||||
1
Task/Humble-numbers/F-Sharp/humble-numbers-3.fs
Normal file
1
Task/Humble-numbers/F-Sharp/humble-numbers-3.fs
Normal 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
|
||||
78
Task/Humble-numbers/F-Sharp/humble-numbers-4.fs
Normal file
78
Task/Humble-numbers/F-Sharp/humble-numbers-4.fs
Normal 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)
|
||||
93
Task/Humble-numbers/F-Sharp/humble-numbers-5.fs
Normal file
93
Task/Humble-numbers/F-Sharp/humble-numbers-5.fs
Normal 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)
|
||||
59
Task/Humble-numbers/Factor/humble-numbers.factor
Normal file
59
Task/Humble-numbers/Factor/humble-numbers.factor
Normal 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
|
||||
44
Task/Humble-numbers/FreeBASIC/humble-numbers.basic
Normal file
44
Task/Humble-numbers/FreeBASIC/humble-numbers.basic
Normal 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
|
||||
95
Task/Humble-numbers/Go/humble-numbers.go
Normal file
95
Task/Humble-numbers/Go/humble-numbers.go
Normal 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)
|
||||
}
|
||||
}
|
||||
27
Task/Humble-numbers/Haskell/humble-numbers-1.hs
Normal file
27
Task/Humble-numbers/Haskell/humble-numbers-1.hs
Normal 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 ++)
|
||||
93
Task/Humble-numbers/Haskell/humble-numbers-2.hs
Normal file
93
Task/Humble-numbers/Haskell/humble-numbers-2.hs
Normal 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
|
||||
95
Task/Humble-numbers/Haskell/humble-numbers-3.hs
Normal file
95
Task/Humble-numbers/Haskell/humble-numbers-3.hs
Normal 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
|
||||
8
Task/Humble-numbers/J/humble-numbers-1.j
Normal file
8
Task/Humble-numbers/J/humble-numbers-1.j
Normal 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.
|
||||
)
|
||||
9
Task/Humble-numbers/J/humble-numbers-2.j
Normal file
9
Task/Humble-numbers/J/humble-numbers-2.j
Normal 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'
|
||||
63
Task/Humble-numbers/Java/humble-numbers.java
Normal file
63
Task/Humble-numbers/Java/humble-numbers.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
235
Task/Humble-numbers/JavaScript/humble-numbers.js
Normal file
235
Task/Humble-numbers/JavaScript/humble-numbers.js
Normal 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();
|
||||
})();
|
||||
31
Task/Humble-numbers/Jq/humble-numbers-1.jq
Normal file
31
Task/Humble-numbers/Jq/humble-numbers-1.jq
Normal 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)
|
||||
24
Task/Humble-numbers/Jq/humble-numbers-2.jq
Normal file
24
Task/Humble-numbers/Jq/humble-numbers-2.jq
Normal 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)
|
||||
42
Task/Humble-numbers/Julia/humble-numbers.julia
Normal file
42
Task/Humble-numbers/Julia/humble-numbers.julia
Normal 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
|
||||
40
Task/Humble-numbers/Kotlin/humble-numbers.kotlin
Normal file
40
Task/Humble-numbers/Kotlin/humble-numbers.kotlin
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Task/Humble-numbers/Lua/humble-numbers.lua
Normal file
53
Task/Humble-numbers/Lua/humble-numbers.lua
Normal 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()
|
||||
10
Task/Humble-numbers/Mathematica/humble-numbers.math
Normal file
10
Task/Humble-numbers/Mathematica/humble-numbers.math
Normal 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
|
||||
58
Task/Humble-numbers/Nim/humble-numbers-1.nim
Normal file
58
Task/Humble-numbers/Nim/humble-numbers-1.nim
Normal 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)
|
||||
89
Task/Humble-numbers/Nim/humble-numbers-2.nim
Normal file
89
Task/Humble-numbers/Nim/humble-numbers-2.nim
Normal 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."
|
||||
91
Task/Humble-numbers/Nim/humble-numbers-3.nim
Normal file
91
Task/Humble-numbers/Nim/humble-numbers-3.nim
Normal 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."
|
||||
76
Task/Humble-numbers/PL-M/humble-numbers.plm
Normal file
76
Task/Humble-numbers/PL-M/humble-numbers.plm
Normal 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
|
||||
379
Task/Humble-numbers/Pascal/humble-numbers.pas
Normal file
379
Task/Humble-numbers/Pascal/humble-numbers.pas
Normal 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.
|
||||
39
Task/Humble-numbers/Perl/humble-numbers.pl
Normal file
39
Task/Humble-numbers/Perl/humble-numbers.pl
Normal 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;
|
||||
}
|
||||
60
Task/Humble-numbers/Phix/humble-numbers.phix
Normal file
60
Task/Humble-numbers/Phix/humble-numbers.phix
Normal 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>
|
||||
<!--
|
||||
69
Task/Humble-numbers/Python/humble-numbers.py
Normal file
69
Task/Humble-numbers/Python/humble-numbers.py
Normal 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()
|
||||
11
Task/Humble-numbers/Quackery/humble-numbers.quackery
Normal file
11
Task/Humble-numbers/Quackery/humble-numbers.quackery
Normal 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
|
||||
44
Task/Humble-numbers/REXX/humble-numbers.rexx
Normal file
44
Task/Humble-numbers/REXX/humble-numbers.rexx
Normal 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 " " " $ " */
|
||||
43
Task/Humble-numbers/Racket/humble-numbers.rkt
Normal file
43
Task/Humble-numbers/Racket/humble-numbers.rkt
Normal 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))
|
||||
30
Task/Humble-numbers/Raku/humble-numbers.raku
Normal file
30
Task/Humble-numbers/Raku/humble-numbers.raku
Normal 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;
|
||||
}
|
||||
23
Task/Humble-numbers/Ring/humble-numbers.ring
Normal file
23
Task/Humble-numbers/Ring/humble-numbers.ring
Normal 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
|
||||
23
Task/Humble-numbers/Ruby/humble-numbers-1.rb
Normal file
23
Task/Humble-numbers/Ruby/humble-numbers-1.rb
Normal 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) }
|
||||
25
Task/Humble-numbers/Ruby/humble-numbers-2.rb
Normal file
25
Task/Humble-numbers/Ruby/humble-numbers-2.rb
Normal 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) }
|
||||
29
Task/Humble-numbers/Sidef/humble-numbers.sidef
Normal file
29
Task/Humble-numbers/Sidef/humble-numbers.sidef
Normal 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)
|
||||
}
|
||||
}
|
||||
11
Task/Humble-numbers/Tcl/humble-numbers-1.tcl
Normal file
11
Task/Humble-numbers/Tcl/humble-numbers-1.tcl
Normal 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
|
||||
12
Task/Humble-numbers/Tcl/humble-numbers-2.tcl
Normal file
12
Task/Humble-numbers/Tcl/humble-numbers-2.tcl
Normal 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
|
||||
62
Task/Humble-numbers/Visual-Basic-.NET/humble-numbers.vb
Normal file
62
Task/Humble-numbers/Visual-Basic-.NET/humble-numbers.vb
Normal 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
|
||||
62
Task/Humble-numbers/Wren/humble-numbers.wren
Normal file
62
Task/Humble-numbers/Wren/humble-numbers.wren
Normal 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)")
|
||||
}
|
||||
37
Task/Humble-numbers/XPL0/humble-numbers.xpl0
Normal file
37
Task/Humble-numbers/XPL0/humble-numbers.xpl0
Normal 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;
|
||||
];
|
||||
]
|
||||
18
Task/Humble-numbers/Zkl/humble-numbers-1.zkl
Normal file
18
Task/Humble-numbers/Zkl/humble-numbers-1.zkl
Normal 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
|
||||
}
|
||||
14
Task/Humble-numbers/Zkl/humble-numbers-2.zkl
Normal file
14
Task/Humble-numbers/Zkl/humble-numbers-2.zkl
Normal 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));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue