Skip to content

Commit 6355194

Browse files
committed
new file: Math/nth_composite.sf
new file: Math/nth_k-powerfree.sf new file: Math/nth_prime.sf new file: Math/nth_squarefree.sf
1 parent 4886d36 commit 6355194

File tree

7 files changed

+397
-91
lines changed

7 files changed

+397
-91
lines changed

Math/nth_composite.sf

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/ruby
2+
3+
# Daniel "Trizen" Șuteu
4+
# Date: 06 June 2021
5+
# Edit: 07 July 2022
6+
# https://github.com/trizen
7+
8+
# Return the n-th composite number, using binary search and the prime counting function.
9+
10+
# See also:
11+
# https://oeis.org/A002808
12+
13+
func nth_composite(n) {
14+
15+
n == 0 && return 1 # not composite, but...
16+
n <= 0 && return NaN
17+
n == 1 && return 4
18+
19+
# Lower and upper bounds from A002808 (for n >= 4).
20+
var min = int(n + n/log(n) + n/(log(n)**2))
21+
var max = int(n + n/log(n) + (3*n)/(log(n)**2))
22+
23+
if (n < 4) {
24+
min = 4;
25+
max = 8;
26+
}
27+
28+
#~ var k = bsearch_le(min, max, {|k|
29+
#~ (k - prime_count(k) - 1) <=> n
30+
#~ })
31+
32+
var k = 0
33+
var c = 0
34+
35+
loop {
36+
37+
k = (min + max)>>1
38+
c = (k - prime_count(k) - 1)
39+
40+
if (abs(c - n) <= k.iroot(3)) {
41+
break
42+
}
43+
44+
given (c <=> n) {
45+
when (+1) { max = k-1 }
46+
when (-1) { min = k+1 }
47+
else { break }
48+
}
49+
}
50+
51+
if (!k.is_composite) {
52+
--k
53+
}
54+
55+
while (c != n) {
56+
var j = (n <=> c)
57+
k += j
58+
c += j
59+
k += j while !k.is_composite
60+
}
61+
62+
return k
63+
}
64+
65+
for n in (1..10) {
66+
var c = nth_composite(10**n)
67+
assert(c.is_composite)
68+
assert_eq(c.composite_count, 10**n)
69+
assert_eq(10**n -> nth_composite, c)
70+
say "C(10^#{n}) = #{c}"
71+
}
72+
73+
assert_eq(
74+
nth_composite.map(1..100),
75+
100.by { .is_composite }
76+
)
77+
78+
__END__
79+
C(10^1) = 18
80+
C(10^2) = 133
81+
C(10^3) = 1197
82+
C(10^4) = 11374
83+
C(10^5) = 110487
84+
C(10^6) = 1084605
85+
C(10^7) = 10708555
86+
C(10^8) = 106091745
87+
C(10^9) = 1053422339
88+
C(10^10) = 10475688327
89+
C(10^11) = 104287176419
90+
C(10^12) = 1039019056246

Math/nth_composite_number.sf

Lines changed: 0 additions & 57 deletions
This file was deleted.

Math/nth_k-powerfree.sf

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/ruby
2+
3+
# Fast algorithm for computing the n-th squarefree integer.
4+
5+
func nth_powerfree(n,k=2) {
6+
7+
n == 0 && return 0 # not k-powerfree, but...
8+
n <= 0 && return NaN
9+
n == 1 && return 1
10+
11+
var min = 1
12+
var max = 231
13+
14+
# Bounds on squarefree numbers:
15+
# https://mathoverflow.net/questions/66701/bounds-on-squarefree-numbers
16+
17+
if (n >= 144) {
18+
min = int(zeta(k)*n - 5*n.iroot(k))
19+
max = int(zeta(k)*n + 5*n.iroot(k))
20+
}
21+
22+
var v = 0
23+
var c = 0
24+
25+
loop {
26+
v = (min + max)>>1
27+
c = k.powerfree_count(v)
28+
29+
if (abs(c - n) <= v.iroot(k)) {
30+
break
31+
}
32+
33+
given (c <=> n) {
34+
when (+1) { max = v-1 }
35+
when (-1) { min = v+1 }
36+
else { break }
37+
}
38+
}
39+
40+
while (!v.is_powerfree(k)) {
41+
--v
42+
}
43+
44+
while (c != n) {
45+
var j = (n <=> c)
46+
v += j
47+
c += j
48+
v += j while !v.is_powerfree(k)
49+
}
50+
51+
return v
52+
}
53+
54+
for k in (2..5) {
55+
say ":: (10^n)-th #{k}-powerfree numbers:"
56+
for n in (1..10) {
57+
var s = nth_powerfree(10**n, k)
58+
assert(s.is_powerfree(k))
59+
assert_eq(k.powerfree_count(s), 10**n)
60+
#assert_eq(10**n -> nth_powerfree(k), s)
61+
say "S(10^#{n}, #{k}) = #{s}"
62+
}
63+
say ''
64+
}
65+
66+
assert_eq(
67+
{ nth_powerfree(_, 2) }.map(1..100),
68+
100.by { .is_powerfree(2) },
69+
)
70+
71+
assert_eq(
72+
{ nth_powerfree(_, 3) }.map(1..100),
73+
100.by { .is_powerfree(3) }
74+
)
75+
76+
__END__
77+
:: (10^n)-th 2-powerfree numbers:
78+
S(10^1, 2) = 14
79+
S(10^2, 2) = 163
80+
S(10^3, 2) = 1637
81+
S(10^4, 2) = 16446
82+
S(10^5, 2) = 164498
83+
S(10^6, 2) = 1644918
84+
S(10^7, 2) = 16449369
85+
S(10^8, 2) = 164493390
86+
S(10^9, 2) = 1644934081
87+
S(10^10, 2) = 16449340709
88+
89+
:: (10^n)-th 3-powerfree numbers:
90+
S(10^1, 3) = 11
91+
S(10^2, 3) = 118
92+
S(10^3, 3) = 1199
93+
S(10^4, 3) = 12019
94+
S(10^5, 3) = 120203
95+
S(10^6, 3) = 1202057
96+
S(10^7, 3) = 12020570
97+
S(10^8, 3) = 120205685
98+
S(10^9, 3) = 1202056919
99+
S(10^10, 3) = 12020569022
100+
101+
:: (10^n)-th 4-powerfree numbers:
102+
S(10^1, 4) = 10
103+
S(10^2, 4) = 107
104+
S(10^3, 4) = 1081
105+
S(10^4, 4) = 10821
106+
S(10^5, 4) = 108232
107+
S(10^6, 4) = 1082319
108+
S(10^7, 4) = 10823229
109+
S(10^8, 4) = 108232319
110+
S(10^9, 4) = 1082323240
111+
S(10^10, 4) = 10823232339
112+
113+
:: (10^n)-th 5-powerfree numbers:
114+
S(10^1, 5) = 10
115+
S(10^2, 5) = 103
116+
S(10^3, 5) = 1036
117+
S(10^4, 5) = 10367
118+
S(10^5, 5) = 103691
119+
S(10^6, 5) = 1036925
120+
S(10^7, 5) = 10369275
121+
S(10^8, 5) = 103692775
122+
S(10^9, 5) = 1036927751
123+
S(10^10, 5) = 10369277550

Math/nth_prime.sf

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/ruby
2+
3+
# Daniel "Trizen" Șuteu
4+
# Date: 06 June 2021
5+
# Edit: 07 July 2022
6+
# https://github.com/trizen
7+
8+
# Return the n-th prime number, using binary search and the prime counting function.
9+
10+
# See also:
11+
# https://oeis.org/A002808
12+
13+
func nth_prime(n) {
14+
15+
n == 0 && return 1 # not prime, but...
16+
n <= 0 && return NaN
17+
n == 1 && return 2
18+
19+
var min = n.prime_lower
20+
var max = n.prime_upper
21+
22+
#~ var k = bsearch(min, max, {|k|
23+
#~ prime_count(k) <=> n
24+
#~ })
25+
26+
var k = 0
27+
var c = 0
28+
29+
loop {
30+
31+
k = (min + max)>>1
32+
c = prime_count(k)
33+
34+
if (abs(c - n) <= n.iroot(3)) {
35+
break
36+
}
37+
38+
given (c <=> n) {
39+
when (+1) { max = k-1 }
40+
when (-1) { min = k+1 }
41+
else { break }
42+
}
43+
}
44+
45+
while (!k.is_prime) {
46+
--k
47+
}
48+
49+
while (c != n) {
50+
var j = (n <=> c)
51+
k += j
52+
c += j
53+
k += j while !k.is_prime
54+
}
55+
56+
return k
57+
}
58+
59+
for n in (1..10) {
60+
var p = nth_prime(10**n)
61+
assert(p.is_prime)
62+
assert_eq(p.prime_count, 10**n)
63+
assert_eq(10**n -> nth_prime, p)
64+
say "P(10^#{n}) = #{p}"
65+
}
66+
67+
assert_eq(
68+
nth_prime.map(1..100),
69+
100.by { .is_prime }
70+
)
71+
72+
__END__
73+
P(10^1) = 29
74+
P(10^2) = 541
75+
P(10^3) = 7919
76+
P(10^4) = 104729
77+
P(10^5) = 1299709
78+
P(10^6) = 15485863
79+
P(10^7) = 179424673
80+
P(10^8) = 2038074743
81+
P(10^9) = 22801763489
82+
P(10^10) = 252097800623
83+
P(10^11) = 2760727302517
84+
P(10^12) = 29996224275833

Math/nth_prime_number.sf

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)