N-smooth numbers: Difference between revisions
Content added Content deleted
(qualify task requirements [“calculate”] otherwise a few `printf` would be sufficient, →Pascal: standardize [use language as per ISO specifications], resolve {{incorrect}}]) |
|||
Line 23: | Line 23: | ||
;Task: |
;Task: |
||
:* show the first '''25''' n-smooth numbers for '''n=2''' ───► '''n=29''' |
:* calculate and show the first '''25''' n-smooth numbers for '''n=2''' ───► '''n=29''' |
||
:* show three numbers starting with '''3,000''' n-smooth numbers for '''n=3''' ───► '''n=29''' |
:* calculate and show three numbers starting with '''3,000''' n-smooth numbers for '''n=3''' ───► '''n=29''' |
||
:* show twenty numbers starting with '''30,000''' n-smooth numbers for '''n=503''' ───► '''n=521''' (optional) |
:* calculate and show twenty numbers starting with '''30,000''' n-smooth numbers for '''n=503''' ───► '''n=521''' (optional) |
||
Line 2,349: | Line 2,349: | ||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
{{works with|Extended Pascal}} |
|||
<lang Pascal>program nSmoothNumbers(output); |
|||
const |
|||
{{incorrect|Pascal| <br><br> for the 2<sup>nd</sup> part of the task, <br> starting at three thousand, <br> '''n'''-smooth for '''3''' and '''5''' aren't displayed. <br><br>}} |
|||
primeCount = 538; |
|||
{$ifDef __GPC__} {$setLimit=3889} {$endIf} |
|||
cardinalMax = 3888; |
|||
{{works with|Free Pascal}} 64-Bit. |
|||
Using trail-division with the first primes.Takes too long for first 3 after 2999 2,3,5-smooth numbers. |
|||
<lang Pascal>program HammNumb; |
|||
{$IFDEF FPC} |
|||
{$MODE DELPHI} |
|||
{$OPTIMIZATION ON,ALL} |
|||
{$ELSE} |
|||
{$APPTYPE CONSOLE} |
|||
{$ENDIF} |
|||
type |
type |
||
cardinal = 0..cardinalMax; |
|||
tHamNum = record |
|||
cardinals = set of cardinal; |
|||
hampot : array[0..167] of Word; |
|||
cardinalPositive = 1..cardinalMax; |
|||
hampotmax, |
|||
hamNum : NativeUint; |
|||
natural = 1..maxInt; |
|||
end; |
|||
primeIndex = 1..primeCount; |
|||
const |
|||
list = array[primeIndex] of cardinal; |
|||
(2, 3, 5, 7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71 |
|||
,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151 |
|||
,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233 |
|||
,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317 |
|||
,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419 |
|||
,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503 |
|||
,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607 |
|||
,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701 |
|||
,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811 |
|||
,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911 |
|||
,919,929,937,941,947,953,967,971,977,983,991,997); |
|||
var |
var |
||
prime: list; |
|||
HNum:tHamNum; |
|||
{ |
|||
procedure OutHamNum(const HNum:tHamNum); |
|||
\brief performs prime factorization |
|||
\param n the number to factorize |
|||
\return list of exponents for a unique integer factorization using primes |
|||
This function requires the global `prime` variable to be initialized. |
|||
} |
|||
function primeFactorization(n: natural): list; |
|||
var |
var |
||
i: primeIndex; |
|||
{ |
|||
Begin |
|||
Instead of writing `[1: 0; 2: 0; 3: 0; …]`, Extended Pascal permits us |
|||
with Hnum do |
|||
to use an “array completer” for all unspecified values. |
|||
Begin |
|||
} |
|||
write(hamNum:12,' : '); |
|||
result: list value [otherwise 0]; |
|||
For i := 0 to hampotmax-1 do |
|||
begin |
|||
write(primes[i],'^',hampot[i],'*'); |
|||
for i := 1 to primeCount do |
|||
writeln(primes[hampotmax],'^',hampot[hampotmax]); |
|||
begin |
|||
end; |
|||
while n mod prime[i] = 0 do |
|||
begin |
|||
n := n div prime[i]; |
|||
result[i] := result[i] + 1 |
|||
end |
|||
end; |
|||
{ Nullify result if the utilized `prime` list was insufficient. } |
|||
if n <> 1 then |
|||
begin |
|||
{ `array` literals need an explicit data type specification. } |
|||
result := list[otherwise 0] |
|||
end; |
|||
{ |
|||
In a Pascal function definition there must be _one_ assignment to the |
|||
(implicitly) declared variable bearing the same name as of the function. |
|||
This will be returned function result. |
|||
} |
|||
primeFactorization := result |
|||
end; |
end; |
||
{ |
|||
procedure NextHammNum(var HNum:tHamNum;maxP:NativeInt); |
|||
\brief returns whether a number is an n-smooth number |
|||
\param smoothness the maximum permissible prime factor |
|||
\param x the number to check |
|||
\return whether \param x is smoothness-smooth |
|||
} |
|||
function isSmooth( |
|||
protected smoothness: cardinalPositive; |
|||
protected x: natural |
|||
): Boolean; |
|||
{ |
|||
Return set of non-one factors (i.e. non-zero exponent). |
|||
Nesting this function permits most compilers to allocate memory |
|||
for variables only if the function is actually needed. |
|||
} |
|||
function factorizationBases: cardinals; |
|||
var |
|||
exponent: list; |
|||
i: primeIndex; |
|||
result: cardinals value []; |
|||
begin |
|||
exponent := primeFactorization(x); |
|||
for i := 1 to primeCount do |
|||
begin |
|||
if exponent[i] > 0 then |
|||
begin |
|||
result := result + [prime[i]] |
|||
end |
|||
end; |
|||
factorizationBases := result |
|||
end; |
|||
begin |
|||
case smoothness of |
|||
1: |
|||
begin |
|||
{ |
|||
The value `1` actually does not have a prime factorization, yet as per |
|||
task specification “1 (unity) is always included in n‑smooth numbers.” |
|||
} |
|||
isSmooth := x = 1 |
|||
end; |
|||
{ 2‑smooth numbers is an alias for powers of 2 (OEIS sequence A000079) } |
|||
2: |
|||
begin |
|||
isSmooth := 2 pow round(ln(x) / ln(2)) = x |
|||
end |
|||
{ The `otherwise` catch-all-clause is an Extended Pascal extension. } |
|||
otherwise |
|||
begin |
|||
isSmooth := card(factorizationBases - [0..smoothness]) = 0 |
|||
{ |
|||
`card` (“cardinality”) is an Extended Pascal extension. |
|||
Testing `card(M) = 0` is equivalent to `M = []` (empty set). |
|||
} |
|||
end |
|||
end |
|||
end; |
|||
{ === ancillary routines =============================================== } |
|||
{ This is just your regular Eratosthenes prime sieve. } |
|||
procedure sieve(var primes: cardinals); |
|||
var |
var |
||
n: natural; |
|||
q,p,nr,n,pnum,momPrime : NativeUInt; |
|||
i: integer; |
|||
multiples: cardinals; |
|||
begin |
begin |
||
{ `1` is by definition not a prime number } |
|||
n := HNum.hamNum; |
|||
primes := primes - [1]; |
|||
repeat |
|||
inc(n); |
|||
{ find the next non-crossed number } |
|||
nr := n; |
|||
for n := 2 to cardinalMax do |
|||
//check divisibility by first (count=maxP) primes |
|||
begin |
|||
pnum := 0; |
|||
if n in primes then |
|||
repeat |
|||
begin |
|||
momPrime := primes[pnum]; |
|||
multiples := []; |
|||
q := nr div momPrime; |
|||
{ We do _not_ want to remove 1 * n. } |
|||
p := 0; |
|||
i := 2 * n; |
|||
while q*momPrime=nr do |
|||
while i in [n..cardinalMax] do |
|||
Begin |
|||
begin |
|||
inc(p); |
|||
multiples := multiples + [i]; |
|||
nr := q; |
|||
i := i + n |
|||
end; |
|||
HNum.hampot[pnum] := p; |
|||
primes := primes - multiples |
|||
inc(pnum); |
|||
end |
|||
until (nr=1) OR (pnum > maxp) |
|||
end |
|||
//finished ? |
|||
until nr = 1; |
|||
With HNum do |
|||
Begin |
|||
hamNum := n; |
|||
hamPotmax := pnum-1; |
|||
end; |
|||
end; |
end; |
||
{ This procedure transforms a `set` to an `array`. } |
|||
procedure OutXafterYSmooth(X,Y,SmoothIdx: NativeUInt); |
|||
procedure populatePrime; |
|||
var |
var |
||
primes: cardinals value [1..cardinalMax]; |
|||
i: NativeUint; |
|||
n: natural value 1; |
|||
i: primeIndex value 1; |
|||
begin |
begin |
||
sieve(primes); |
|||
EXIT; |
|||
for i := 1 to primeCount do |
|||
HNum.HamNum := 0; |
|||
begin |
|||
dec(Y); |
|||
repeat |
|||
for i := 1 to Y do |
|||
begin |
|||
NextHammNum(HNum,SmoothIdx); |
|||
n := n + 1 |
|||
write('first ',X,' after ',Y,' ',primes[SmoothIdx]:3,'-smooth numbers : '); |
|||
end |
|||
for i := 1 to X do |
|||
until n in primes; |
|||
begin |
|||
NextHammNum(HNum,SmoothIdx); |
|||
prime[i] := n |
|||
write(HNum.HamNum,' '); |
|||
end |
|||
writeln; |
|||
end; |
end; |
||
{ ### MAIN ############################################################# } |
|||
var |
var |
||
i: primeIndex value primeCount; |
|||
j: NativeUint; |
|||
candidate: natural; |
|||
Begin |
|||
count: cardinal; |
|||
j := 0; |
|||
begin |
|||
while primes[j] <= 29 do |
|||
populatePrime; |
|||
Begin |
|||
OutXafterYSmooth(25,1,j); |
|||
{ Show the first 25 n-smooth numbers […] } |
|||
inc(j); |
|||
{ […] only prime [n] are to be used. } |
|||
end; |
|||
while prime[i] > 29 do |
|||
writeln; |
|||
begin |
|||
i := i - 1 |
|||
end; |
|||
{ |
|||
In Pascal, `for` loop limits are evaluated _once_, |
|||
so this is perfectly legal: |
|||
} |
|||
for i := 1 to i do |
|||
begin |
|||
write(prime[i]:4, '-smooth: 1'); |
|||
count := 1; { `1` already listed. } |
|||
candidate := 2; |
|||
while count < 25 do |
|||
begin |
|||
if isSmooth(prime[i], candidate) then |
|||
begin |
|||
write(', ', candidate:1); |
|||
count := count + 1 |
|||
end; |
|||
candidate := candidate + 1 |
|||
end; |
|||
writeLn |
|||
end; |
|||
{ |
|||
Note, in Pascal, the `for`‑loop iteration variable is not modified. |
|||
At this point in the code, `i` (still) has the value after the `while`-loop. |
|||
[This statement is not true, if a `goto` prematurely exited the `for`‑loop.] |
|||
} |
|||
writeLn; |
|||
{ […] show three numbers starting with 3,000 […] } |
|||
for i := 2 to i do |
|||
begin |
|||
write(prime[i]:4, '-smooth:'); |
|||
count := 0; |
|||
candidate := 3000; |
|||
while count < 3 do |
|||
begin |
|||
if isSmooth(prime[i], candidate) then |
|||
begin |
|||
write(' ', candidate:1); |
|||
count := count + 1 |
|||
end; |
|||
candidate := candidate + 1 |
|||
end; |
|||
writeLn |
|||
end; |
|||
end.</lang> |
|||
{{out}} |
|||
<pre style="height:45ex"> 2-smooth: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216 |
|||
3-smooth: 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96, 108, 128, 144, 162, 192 |
|||
5-smooth: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, 54 |
|||
7-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, 28, 30, 32, 35, 36 |
|||
11-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 27, 28, 30, 32 |
|||
13-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28 |
|||
17-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 24, 25, 26, 27 |
|||
19-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26 |
|||
23-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 |
|||
29-smooth: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 |
|||
3-smooth: 3072 3456 3888 |
|||
j := 3; |
|||
5-smooth: 3000 3072 3125 |
|||
while primes[j] <= 29 do |
|||
7-smooth: 3000 3024 3072 |
|||
Begin |
|||
11-smooth: 3000 3024 3025 |
|||
OutXafterYSmooth(3,3000,j); |
|||
13-smooth: 3000 3003 3024 |
|||
inc(j); |
|||
17-smooth: 3000 3003 3024 |
|||
end; |
|||
19-smooth: 3000 3003 3024 |
|||
writeln; |
|||
23-smooth: 3000 3003 3024 |
|||
while primes[j] < 503 do |
|||
29-smooth: 3000 3003 3016</pre> |
|||
inc(j); |
|||
while primes[j] <= 521 do |
|||
Begin |
|||
OutXafterYSmooth(20,30000,j); |
|||
inc(j); |
|||
end; |
|||
writeln; |
|||
End.</lang>{{out}}<pre>first 25 after 0 2-smooth numbers : 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 |
|||
first 25 after 0 3-smooth numbers : 1 2 3 4 6 8 9 12 16 18 24 27 32 36 48 54 64 72 81 96 108 128 144 162 192 |
|||
first 25 after 0 5-smooth numbers : 1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36 40 45 48 50 54 |
|||
first 25 after 0 7-smooth numbers : 1 2 3 4 5 6 7 8 9 10 12 14 15 16 18 20 21 24 25 27 28 30 32 35 36 |
|||
first 25 after 0 11-smooth numbers : 1 2 3 4 5 6 7 8 9 10 11 12 14 15 16 18 20 21 22 24 25 27 28 30 32 |
|||
first 25 after 0 13-smooth numbers : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 20 21 22 24 25 26 27 28 |
|||
first 25 after 0 17-smooth numbers : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 21 22 24 25 26 27 |
|||
first 25 after 0 19-smooth numbers : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 24 25 26 |
|||
first 25 after 0 23-smooth numbers : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|||
first 25 after 0 29-smooth numbers : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|||
first 3 after 2999 7-smooth numbers : 50176000 50331648 50388480 |
|||
first 3 after 2999 11-smooth numbers : 2112880 2116800 2117016 |
|||
first 3 after 2999 13-smooth numbers : 390000 390390 390625 |
|||
first 3 after 2999 17-smooth numbers : 145800 145860 146016 |
|||
first 3 after 2999 19-smooth numbers : 74256 74358 74360 |
|||
first 3 after 2999 23-smooth numbers : 46552 46575 46585 |
|||
first 3 after 2999 29-smooth numbers : 33516 33524 33534 |
|||
first 20 after 29999 503-smooth numbers : 62913 62914 62916 62918 62920 62923 62926 62928 62930 62933 62935 62937 62944 62946 62951 62952 62953 62957 62959 62964 |
|||
first 20 after 29999 509-smooth numbers : 62601 62602 62604 62607 62608 62609 62611 62618 62620 62622 62624 62625 62626 62628 62629 62634 62640 62643 62645 62646 |
|||
first 20 after 29999 521-smooth numbers : 62287 62288 62291 62292 62300 62304 62307 62308 62310 62315 62320 62321 62322 62325 62328 62329 62330 62331 62335 62336 |
|||
real 0m2,665s |
|||
user 0m2,655s |
|||
sys 0m0,003s |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |