Semiprime
You are encouraged to solve this task according to the task description, using any language you may know.
Semiprime numbers are natural numbers that are products of exactly two (possibly equal) prime numbers.
Semiprimes are also known as:
- semi-primes
- biprimes
- bi-primes
- 2-almost primes
- or simply: P2
- Example
1679 = 23 × 73
(This particular number was chosen as the length of the Arecibo message).
- Task
Write a function determining whether a given number is semiprime.
- See also
- The Wikipedia article: semiprime.
- The Wikipedia article: almost prime.
- The OEIS sequence: A001358: semiprimes which has a shorter definition: the product of two primes.
11l
F is_semiprime(=c)
V a = 2
V b = 0
L b < 3 & c != 1
I c % a == 0
c /= a
b++
E
a++
R b == 2
print((1..100).filter(n -> is_semiprime(n)))
- Output:
[4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
360 Assembly
* Semiprime 14/03/2017
SEMIPRIM CSECT
USING SEMIPRIM,R13 base register
B 72(R15) skip savearea
DC 17F'0' savearea
STM R14,R12,12(R13) save previous context
ST R13,4(R15) link backward
ST R15,8(R13) link forward
LR R13,R15 set addressability
LA R10,PG pgi=0
LA R8,0 m=0
L R6,=F'2' i=2
DO WHILE=(C,R6,LE,=F'100') do i=2 to 100
ST R6,N n=i
LA R9,0 f=0
LA R7,2 j=2
LOOPJ EQU * do j=2 while f<2 and j*j<=n
C R9,=F'2' if f<2
BNL EXITJ then exit do j
LR R5,R7 j
MR R4,R7 *j
C R5,N if j*j<=n
BH EXITJ then exit do j
LOOPK EQU * do while n mod j=0
L R4,N n
SRDA R4,32 ~
DR R4,R7 /j
LTR R4,R4 if n mod <>0
BNZ EXITK then exit do j
ST R5,N n=n/j
LA R9,1(R9) f=f+1
B LOOPK enddo k
EXITK LA R7,1(R7) j++
B LOOPJ enddo j
EXITJ L R4,N n
IF C,R4,GT,=F'1' THEN if n>1 then
LA R2,1 g=1
ELSE , else
LA R2,0 g=0
ENDIF , endif
AR R2,R9 +f
IF C,R2,EQ,=F'2' THEN if f+(n>1)=2 then
XDECO R6,XDEC edit i
MVC 0(5,R10),XDEC+7 output i
LA R10,5(R10) pgi=pgi+10
LA R8,1(R8) m=m+1
LR R4,R8 m
SRDA R4,32 ~
D R4,=F'16' m/16
IF LTR,R4,Z,R4 THEN if m mod 16=0 then
XPRNT PG,L'PG print buffer
MVC PG,=CL80' ' clear buffer
LA R10,PG pgi=0
ENDIF , endif
ENDIF , endif
LA R6,1(R6) i++
ENDDO , enddo i
XPRNT PG,L'PG print buffer
MVC PG,=CL80'..... semiprimes' init buffer
XDECO R8,XDEC edit m
MVC PG(5),XDEC+7 output m
XPRNT PG,L'PG print buffer
L R13,4(0,R13) restore previous savearea pointer
LM R14,R12,12(R13) restore previous context
XR R15,R15 rc=0
BR R14 exit
N DS F n
PG DC CL80' ' buffer
XDEC DS CL12 temp
YREGS
END SEMIPRIM
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 34 semiprimes
Action!
BYTE FUNC IsSemiPrime(INT n)
INT a,b
a=2 b=0
WHILE b<3 AND n#1
DO
IF n MOD a=0 THEN
n==/a b==+1
ELSE
a==+1
FI
OD
IF b=2 THEN
RETURN(1)
FI
RETURN(0)
PROC Main()
INT i
PrintE("Semiprimes:")
FOR i=1 TO 500
DO
IF IsSemiPrime(i) THEN
PrintI(i) Put(32)
FI
OD
RETURN
- Output:
Screenshot from Atari 8-bit computer
Semiprimes: 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 106 111 115 118 119 121 122 123 129 133 134 141 142 143 145 146 155 158 159 161 166 169 177 178 183 185 187 194 201 202 203 205 206 209 213 214 215 217 218 219 221 226 235 237 247 249 253 254 259 262 265 267 274 278 287 289 291 295 298 299 301 302 303 305 309 314 319 321 323 326 327 329 334 335 339 341 346 355 358 361 362 365 371 377 381 382 386 391 393 394 395 398 403 407 411 413 415 417 422 427 437 445 446 447 451 453 454 458 466 469 471 473 478 481 482 485 489 493 497
Ada
This imports the package Prime_Numbers from Prime decomposition#Ada.
with Prime_Numbers, Ada.Text_IO;
procedure Test_Semiprime is
package Integer_Numbers is new
Prime_Numbers (Natural, 0, 1, 2);
use Integer_Numbers;
begin
for N in 1 .. 100 loop
if Decompose(N)'Length = 2 then -- N is a semiprime;
Ada.Text_IO.Put(Integer'Image(Integer(N)));
end if;
end loop;
Ada.Text_IO.New_Line;
for N in 1675 .. 1680 loop
if Decompose(N)'Length = 2 then -- N is a semiprime;
Ada.Text_IO.Put(Integer'Image(Integer(N)));
end if;
end loop;
end Test_Semiprime;
It outputs all semiprimes below 100 and all semiprimes between 1675 and 1680:
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 1678 1679
Note that
1675 = 5 * 5 * 67, 1676 = 2 * 2 * 419, 1677 = 3 * 13 * 43, 1678 = 2 * 839, 1679 = 23 * 73, 1680 = 2 * 2 * 2 * 2 * 3 * 5 * 7,
so the result printed is actually correct.
ALGOL 68
# returns TRUE if n is semi-prime, FALSE otherwise #
# n is semi prime if it has exactly two prime factors #
PROC is semiprime = ( INT n )BOOL:
BEGIN
# We only need to consider factors between 2 and #
# sqrt( n ) inclusive. If there is only one of these #
# then it must be a prime factor and so the number #
# is semi prime #
INT factor count := 0;
FOR factor FROM 2 TO ENTIER sqrt( ABS n )
WHILE IF n MOD factor = 0 THEN
factor count +:= 1;
# check the factor isn't a repeated factor #
IF n /= factor * factor THEN
# the factor isn't the square root #
INT other factor = n OVER factor;
IF other factor MOD factor = 0 THEN
# have a repeated factor #
factor count +:= 1
FI
FI
FI;
factor count < 2
DO SKIP OD;
factor count = 1
END # is semiprime # ;
# determine the first few semi primes #
print( ( "semi primes below 100: " ) );
FOR i TO 99 DO
IF is semi prime( i ) THEN print( ( whole( i, 0 ), " " ) ) FI
OD;
print( ( newline ) );
print( ( "semi primes below between 1670 and 1690: " ) );
FOR i FROM 1670 TO 1690 DO
IF is semi prime( i ) THEN print( ( whole( i, 0 ), " " ) ) FI
OD;
print( ( newline ) )
- Output:
semi primes below 100: 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 semi primes below between 1670 and 1690: 1671 1673 1678 1679 1681 1685 1687 1689
ALGOL W
begin % find some semi-primes - numbers with exactly 2 prime factors %
logical procedure isSemiPrime( integer value v ) ;
begin
integer a, b, c;
a := 2; b := 0; c := v;
while b < 3 and c > 1 do begin
if c rem a = 0 then begin
c := c div a;
b := b + 1
end
else a := a + 1;
end while_b_lt_3_and_c_ne_1 ;
b = 2
end isSemiPrime ;
for x := 2 until 99 do begin
if isSemiPrime( x ) then writeon( i_w := 1, s_w := 0, x, " " )
end for_x
end.
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Arturo
semiPrime?: function [x][
2 = size factors.prime x
]
print select 1..100 => semiPrime?
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
AutoHotkey
SetBatchLines -1
k := 1
loop, 100
{
m := semiprime(k)
StringSplit, m_m, m, -
if ( m_m1 = "yes" )
list .= k . " "
k++
}
MsgBox % list
list :=
;===================================================================================================================================
k := 1675
loop, 5
{
m := semiprime(k)
StringSplit, m_m, m, -
if ( m_m1 = "yes" )
list1 .= semiprime(k) . "`n"
else
list1 .= semiprime(k) . "`n"
k++
}
MsgBox % list1
list1 :=
;===================================================================================================================================
; The function==========================================================================================================================
semiprime(k)
{
start := floor(sqrt(k))
loop, % floor(sqrt(k)) - 1
{
if ( mod(k, start) = 0 )
new .= floor(start) . "*" . floor(k//start) . ","
start--
}
StringSplit, index, new, `,
if ( index0 = 2 )
{
StringTrimRight, new, new, 1
StringSplit, 2_ind, new, *
if (mod(2_ind2, 2_ind1) = 0) && ( 2_ind1 != 2_ind2 )
new := "N0- " . k . " - " . new
else
new := "yes- " . k . " - " . new
}
else
new := "N0- " . k . " - " . new
return new
}
;=================================================================================================================================================
esc::Exitapp
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 N0- 1675 - 25*67,5*335, N0- 1676 - 4*419,2*838, N0- 1677 - 39*43,13*129,3*559, yes- 1678 - 2*839 yes- 1679 - 23*73
AWK
# syntax: GAWK -f SEMIPRIME.AWK
BEGIN {
main(0,100)
main(1675,1680)
exit(0)
}
function main(lo,hi, i) {
printf("%d-%d:",lo,hi)
for (i=lo; i<=hi; i++) {
if (is_semiprime(i)) {
printf(" %d",i)
}
}
printf("\n")
}
function is_semiprime(n, i,nf) {
nf = 0
for (i=2; i<=n; i++) {
while (n % i == 0) {
if (nf == 2) {
return(0)
}
nf++
n /= i
}
}
return(nf == 2)
}
- Output:
0-100: 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 1675-1680: 1678 1679
BASIC
ASIC
REM Semiprime
PRINT "Enter an integer ";
INPUT N
N = ABS(N)
Count = 0
IF N >= 2 THEN
FOR Factor = 2 TO N
NModFactor = N MOD Factor
WHILE NModFactor = 0
Count = Count + 1
N = N / Factor
NModFactor = N MOD Factor
WEND
NEXT Factor
ENDIF
IF Count = 2 THEN
PRINT "It is a semiprime."
ELSE
PRINT "It is not a semiprime."
ENDIF
END
- Output:
Enter an integer ?60 It is not a semiprime.
Enter an integer ?33 It is a semiprime.
BASIC256
function semiprime$ (n)
a = 2
c = 0
while c < 3 and n > 1
if (n mod a) = 0 then
n = n / a
c = c + 1
else
a = a + 1
end if
end while
if c = 2 then return "True"
return "False"
end function
for i = 0 to 64
print i, semiprime$(i)
next i
end
Chipmunk Basic
100 rem Semiprime
110 cls
120 for i = 0 to 64
130 print using "## ";i semiprime$(i)
140 next i
150 end
160 sub semiprime$(n)
170 a = 2
180 c = 0
190 do while c < 3 and n > 1
200 if n mod a = 0 then n = n/a : c = c+1 else a = a+1
210 loop
220 if c = 2 then semiprime$ = "True" else semiprime$ = "False"
230 end sub
FreeBASIC
function semiprime( n as uinteger ) as boolean
dim as uinteger a = 2, c = 0
while c < 3 andalso n > 1
if n mod a = 0 then
n /= a
c += 1
else
a += 1
end if
wend
if c = 2 then return true
return false
end function
for i as uinteger = 0 to 64
print i, semiprime(i)
next i
GW-BASIC
10 INPUT "Enter a number: ", N
20 N=ABS(N)
30 C = 0
40 IF N < 3 THEN GOTO 80
50 F = 2
60 IF N MOD F = 0 THEN C = C + 1 : N = N / F ELSE F = F + 1
70 IF N > 1 THEN GOTO 60
80 IF C=2 THEN PRINT "It's a semiprime." ELSE PRINT "It is not a semiprime."
Minimal BASIC
10 REM Semiprime
20 PRINT "Enter an integer";
30 INPUT N
40 LET N = ABS(N)
50 LET C = 0
60 IF N < 2 THEN 130
70 FOR F = 2 TO N
80 IF INT(N/F)*F <> N THEN 120
90 LET C = C+1
100 LET N = N/F
110 GOTO 80
120 NEXT F
130 IF C <> 2 THEN 160
140 PRINT "It is a semiprime."
150 GOTO 170
160 PRINT "It is not a semiprime."
170 END
Palo Alto Tiny BASIC
10 REM SEMIPRIME
20 INPUT "ENTER AN INTEGER"N
30 LET N=ABS(N)
40 LET C=0
50 IF N<2 GOTO 90
60 FOR F=2 TO N
70 IF (N/F)*F=N LET C=C+1,N=N/F;GOTO 70
80 NEXT F
90 IF C=2 PRINT "IT IS A SEMIPRIME.";STOP
100 PRINT "IT IS NOT A SEMIPRIME.";STOP
- Output:
2 runs.
ENTER AN INTEGER:60 IT IS NOT A SEMIPRIME.
ENTER AN INTEGER:33 IT IS A SEMIPRIME.
PureBasic
Procedure.s semiprime(n.i)
a.i = 2
c.i = 0
While c < 3 And n > 1
If (n % a) = 0
n / a
c + 1
Else
a + 1
EndIf
Wend
If c = 2
ProcedureReturn "True" ;#True
EndIf
ProcedureReturn "False" ;#False
EndProcedure
OpenConsole()
For i.i = 0 To 64
PrintN(Str(i) + #TAB$ + semiprime(i))
Next i
PrintN(#CRLF$ + "--- terminado, pulsa RETURN---"): Input()
CloseConsole()
End
Run BASIC
function semiprime$(n)
a = 2
c = 0
while c < 3 and n > 1
if n mod a = 0 then
n = n / a
c = c + 1
else
a = a + 1
end if
wend
if c = 2 then semiprime$ = "True" else semiprime$ = "False"
end function
for i = 0 to 64
print i; chr$(9); semiprime$(i)
next i
Tiny BASIC
10 REM Semiprime
20 PRINT "Enter an integer"
30 INPUT N
40 IF N < 0 THEN LET N = -N
50 IF N < 2 THEN GOTO 120
60 LET C = 0
70 LET F = 2
80 IF (N / F) * F = N THEN GOTO 150
90 LET F = F + 1
100 IF F > N THEN GOTO 120
110 GOTO 80
120 IF C = 2 THEN PRINT "It is a semiprime."
130 IF C <> 2 THEN PRINT "It is not a semiprime."
140 END
150 LET C = C + 1
160 LET N = N / F
170 GOTO 80
- Output:
2 runs.
Enter an integer ? 60 It is not a semiprime.
Enter an integer ? 33 It is a semiprime.
True BASIC
FUNCTION semiprime$ (n)
LET a = 2
LET c = 0
DO WHILE c < 3 AND n > 1
IF REMAINDER(n, a) = 0 THEN
LET n = n / a
LET c = c + 1
ELSE
LET a = a + 1
END IF
LOOP
IF c = 2 THEN LET semiprime$ = "True" ELSE LET semiprime$ = "False"
END FUNCTION
FOR i = 0 TO 64
PRINT i, semiprime$(i)
NEXT i
END
Yabasic
sub semiprime$ (n)
a = 2
c = 0
while c < 3 and n > 1
if mod(n, a) = 0 then
n = n / a
c = c + 1
else
a = a + 1
end if
wend
if c = 2 then return "True" : fi
return "False"
end sub
for i = 0 to 64
print i, chr$(9), semiprime$(i)
next i
end
Bracmat
When Bracmat is asked to take the square (or any other) root of a number, it does so by first finding the number's prime factors. It can do that for numbers up to 2^32 or 2^64 (depending on compiler and processor).
semiprime=
m n a b
. 2^-64:?m
& 2*!m:?n
& !arg^!m
: (#%?a^!m*#%?b^!m|#%?a^!n&!a:?b)
& (!a.!b);
Test with numbers < 2^63:
2^63:?u
& whl
' ( -1+!u:>2:?u
& ( semiprime$!u:?R&out$(!u ":" !R)
|
)
);
Output:
9223372036854775797 : (3.3074457345618258599) 9223372036854775777 : (584911.15768846947407) 9223372036854775771 : (19.485440633518672409) 9223372036854775753 : (266416229.34620158357) 9223372036854775727 : (11113.829962389710679) 9223372036854775717 : (59.156328339607708063) 9223372036854775715 : (5.1844674407370955143) 9223372036854775703 : (9648151.955973018753) 9223372036854775694 : (2.4611686018427387847) 9223372036854775691 : (37.249280325320399343) 9223372036854775687 : (1303.7078566413549329) 9223372036854775685 : (5.1844674407370955137) 9223372036854775673 : (175934777.52424950849) 9223372036854775634 : (2.4611686018427387817) 9223372036854775633 : (421741.21869754273013) 9223372036854775627 : (6277.1469391753521551) 9223372036854775609 : (172153.53576597775553) 9223372036854775601 : (1045692671.8820346831) 9223372036854775589 : (563.16382543582335303) 9223372036854775577 : (267017141.34542246997) 9223372036854775574 : (2.4611686018427387787) 9223372036854775571 : (1951.4727510013764621) 9223372036854775537 : (47.196241958230952671) 9223372036854775531 : (1677122561.5499521771) 9223372036854775522 : (2.4611686018427387761) 9223372036854775511 : (29305709.314729530579) 9223372036854775502 : (2.4611686018427387751) 9223372036854775489 : (9413717.979780041917) 9223372036854775474 : (2.4611686018427387737) 9223372036854775466 : (2.4611686018427387733) 9223372036854775461 : (3.3074457345618258487) 9223372036854775451 : (545369243.16912160257) 9223372036854775439 : (11380717.810438572267) 9223372036854775418 : (2.4611686018427387709) 9223372036854775411 : (1420967.6490912200533) 9223372036854775409 : (15060911.612404657119) 9223372036854775407 : (3.3074457345618258469) 9223372036854775402 : (2.4611686018427387701) 9223372036854775389 : (3.3074457345618258463) 9223372036854775385 : (5.1844674407370955077) 9223372036854775383 : (3.3074457345618258461) 9223372036854775381 : (683.13504205031998207) 9223372036854775379 : (43.214497024112901753) 9223372036854775357 : (17.542551296285575021) 9223372036854775355 : (5.1844674407370955071) ^CTerminate batch job (Y/N)? Y
C
#include <stdio.h>
int semiprime(int n)
{
int p, f = 0;
for (p = 2; f < 2 && p*p <= n; p++)
while (0 == n % p)
n /= p, f++;
return f + (n > 1) == 2;
}
int main(void)
{
int i;
for (i = 2; i < 100; i++)
if (semiprime(i)) printf(" %d", i);
putchar('\n');
return 0;
}
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
C#
static void Main(string[] args)
{
//test some numbers
for (int i = 0; i < 50; i++)
{
Console.WriteLine("{0}\t{1} ", i,isSemiPrime(i));
}
Console.ReadLine();
}
//returns true or false depending if input was considered semiprime
private static bool isSemiPrime(int c)
{
int a = 2, b = 0;
while (b < 3 && c != 1)
{
if ((c % a) == 0)
{
c /= a;
b++;
}
else
{
a++;
};
}
return b == 2;
}
- Output:
0 False 1 False 2 False 3 False 4 True 5 False 6 True 7 False 8 False 9 True 10 True 11 False 12 False 13 False 14 True 15 True 16 False 17 False 18 False 19 False 20 False 21 True 22 True 23 False 24 False 25 True 26 True 27 False 28 False 29 False 30 False 31 False 32 False 33 True 34 True 35 True 36 False 37 False 38 True 39 True 40 False 41 False 42 False 43 False 44 False 45 False 46 True 47 False 48 False 49 True
C++
#include <iostream>
bool isSemiPrime( int c )
{
int a = 2, b = 0;
while( b < 3 && c != 1 )
{
if( !( c % a ) )
{ c /= a; b++; }
else a++;
}
return b == 2;
}
int main( int argc, char* argv[] )
{
for( int x = 2; x < 100; x++ )
if( isSemiPrime( x ) )
std::cout << x << " ";
return 0;
}
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Clojure
(ns example
(:gen-class))
(defn semi-prime? [n]
(loop [a 2
b 0
c n]
(cond
(> b 2) false
(<= c 1) (= b 2)
(= 0 (rem c a)) (recur a (inc b) (int (/ c a)))
:else (recur (inc a) b c))))
(println (filter semi-prime? (range 1 100)))
- Output:
(4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95)
Common Lisp
(defun semiprimep (n &optional (a 2))
(cond ((> a (isqrt n)) nil)
((zerop (rem n a)) (and (primep a) (primep (/ n a))))
(t (semiprimep n (+ a 1)))))
(defun primep (n &optional (a 2))
(cond ((> a (isqrt n)) t)
((zerop (rem n a)) nil)
(t (primep n (+ a 1)))))
Example Usage:
CL-USER> (semiprimep 1234567) T CL-USER> (semiprimep 9876543) NIL
Crystal
def semiprime(n)
nf = 0
(2..n).each do |i|
while n % i == 0
return false if nf == 2
nf += 1
n /= i
end
end
nf == 2
end
(1675..1681).each { |n| puts "#{n} -> #{semiprime(n)}" }
- Output:
1675 -> false 1676 -> false 1677 -> false 1678 -> true 1679 -> true 1680 -> false 1681 -> true
Faster version using 'factor' function from [U|Li]nux Core Utilities library.
def semiprime(n)
`factor #{n}`.split(' ').size == 3
end
n = 0xffffffffffffffff_u64 # 2**64 - 1 = 18446744073709551615
(n-50..n).each { |n| puts "#{n} -> #{semiprime(n)}" }
- Output:
18446744073709551565 -> false 18446744073709551566 -> true 18446744073709551567 -> false 18446744073709551568 -> false 18446744073709551569 -> false 18446744073709551570 -> false 18446744073709551571 -> false 18446744073709551572 -> false 18446744073709551573 -> false 18446744073709551574 -> false 18446744073709551575 -> false 18446744073709551576 -> false 18446744073709551577 -> true 18446744073709551578 -> false 18446744073709551579 -> false 18446744073709551580 -> false 18446744073709551581 -> false 18446744073709551582 -> false 18446744073709551583 -> false 18446744073709551584 -> false 18446744073709551585 -> false 18446744073709551586 -> false 18446744073709551587 -> false 18446744073709551588 -> false 18446744073709551589 -> false 18446744073709551590 -> false 18446744073709551591 -> false 18446744073709551592 -> false 18446744073709551593 -> false 18446744073709551594 -> false 18446744073709551595 -> false 18446744073709551596 -> false 18446744073709551597 -> true 18446744073709551598 -> false 18446744073709551599 -> false 18446744073709551600 -> false 18446744073709551601 -> true 18446744073709551602 -> false 18446744073709551603 -> false 18446744073709551604 -> false 18446744073709551605 -> false 18446744073709551606 -> false 18446744073709551607 -> false 18446744073709551608 -> false 18446744073709551609 -> false 18446744073709551610 -> false 18446744073709551611 -> false 18446744073709551612 -> false 18446744073709551613 -> false 18446744073709551614 -> false 18446744073709551615 -> false
D
bool semiprime(long n) pure nothrow @safe @nogc {
auto nf = 0;
foreach (immutable i; 2 .. n + 1) {
while (n % i == 0) {
if (nf == 2)
return false;
nf++;
n /= i;
}
}
return nf == 2;
}
void main() {
import std.stdio;
foreach (immutable n; 1675 .. 1681)
writeln(n, " -> ", n.semiprime);
}
- Output:
1675 -> false 1676 -> false 1677 -> false 1678 -> true 1679 -> true 1680 -> false
DCL
Given a file primes.txt is the list of primes up to the sqrt(2^31-1), i.e. 46337;
$ p1 = f$integer( p1 )
$ if p1 .lt. 2
$ then
$ write sys$output "out of range 2 thru 2^31-1"
$ exit
$ endif
$
$ close /nolog primes
$ on control_y then $ goto clean
$ open primes primes.txt
$
$ loop1:
$ read /end_of_file = prime primes prime
$ prime = f$integer( prime )
$ loop2:
$ t = p1 / prime
$ if t * prime .eq. p1
$ then
$ if f$type( factorization ) .eqs. ""
$ then
$ factorization = f$string( prime )
$ else
$ factorization = factorization + "*" + f$string( prime )
$ endif
$ if t .eq. 1 then $ goto done
$ p1 = t
$ goto loop2
$ else
$ goto loop1
$ endif
$ prime:
$ if f$type( factorization ) .eqs. ""
$ then
$ factorization = f$string( p1 )
$ else
$ factorization = factorization + "*" + f$string( p1 )
$ endif
$ done:
$ show symbol factorization
$ if f$locate( "*", factorization ) .eq. f$length( factorization )
$ then
$ write sys$output "so, it is prime"
$ else
$ if f$element( 2, "*", factorization ) .eqs. "*" then $ write sys$output "so, it is semiprime"
$ endif
$
$ clean:
$ close primes
- Output:
$ @factor 6 FACTORIZATION = "2*3" so, it is semiprime $ @factor 11 FACTORIZATION = "11" so, it is prime $ @factor 2147483646 FACTORIZATION = "2*3*3*7*11*31*151*331"
Delphi
{This function would normally be in a library, but it shown here for clarity}
procedure GetAllFactors(N: Integer;var IA: TIntegerDynArray);
{Make a list of all irreducible factor of N}
var I: integer;
begin
SetLength(IA,1);
IA[0]:=1;
for I:=2 to N do
while (N mod I)=0 do
begin
SetLength(IA,Length(IA)+1);
IA[High(IA)]:=I;
N:=N div I;
end;
end;
function IsSemiprime(N: integer): boolean;
{Test if number is semiprime}
var IA: TIntegerDynArray;
begin
{Get all factors of N}
GetAllFactors(N,IA);
Result:=False;
{Since 1 is factor, ignore it}
if Length(IA)<>3 then exit;
Result:=IsPrime(IA[1]) and IsPrime(IA[2]);
end;
procedure Semiprimes(Memo: TMemo);
var I,Cnt: integer;
var S: string;
begin
Cnt:=0;
S:='';
{Test first 100 number to see if they are semiprime}
for I:=0 to 100-1 do
if IsSemiprime(I) then
begin
Inc(Cnt);
S:=S+Format('%4d',[I]);
if (Cnt mod 10)= 0 then S:=S+CRLF;
end;
Memo.Lines.Add(S);
Memo.Lines.Add('Count='+IntToStr(Cnt));
end;
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 Count=34 Elapsed Time: 5.182 ms.
EasyLang
fastfunc factor num .
i = 2
while i <= sqrt num
if num mod i = 0
return i
.
i += 1
.
return 1
.
func semiprime n .
f1 = factor n
if f1 = 1
return 0
.
f2 = n div f1
if factor f1 = 1 and factor f2 = 1
return 1
.
return 0
.
for i = 1 to 1000
if semiprime i = 1
write i & " "
.
.
EchoLisp
(lib 'math)
(define (semi-prime? n)
(= (length (prime-factors n)) 2))
(for ((i 100))
(when (semi-prime? i) (write i)))
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
(lib 'bigint)
(define N (* (random-prime 10000000) (random-prime 10000000)))
→ 6764578882969
(semi-prime? N)
→ #t
;; a pair n,n+1 of semi-primes
(prime-factors 100000000041)
→ (3 33333333347)
(prime-factors 100000000042)
→ (2 50000000021)
Elixir
defmodule Prime do
def semiprime?(n), do: length(decomposition(n)) == 2
def decomposition(n), do: decomposition(n, 2, [])
defp decomposition(n, k, acc) when n < k*k, do: Enum.reverse(acc, [n])
defp decomposition(n, k, acc) when rem(n, k) == 0, do: decomposition(div(n, k), k, [k | acc])
defp decomposition(n, k, acc), do: decomposition(n, k+1, acc)
end
IO.inspect Enum.filter(1..100, &Prime.semiprime?(&1))
Enum.each(1675..1680, fn n ->
:io.format "~w -> ~w\t~s~n", [n, Prime.semiprime?(n), Prime.decomposition(n)|>Enum.join(" x ")]
end)
- Output:
[4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95] 1675 -> false 5 x 5 x 67 1676 -> false 2 x 2 x 419 1677 -> false 3 x 13 x 43 1678 -> true 2 x 839 1679 -> true 23 x 73 1680 -> false 2 x 2 x 2 x 2 x 3 x 5 x 7
Erlang
Another using prime factors from Prime_decomposition#Erlang :
-module(factors).
-export([factors/1,kthfactor/2]).
factors(N) ->
factors(N,2,[]).
factors(1,_,Acc) -> Acc;
factors(N,K,Acc) when N rem K == 0 ->
factors(N div K,K, [K|Acc]);
factors(N,K,Acc) ->
factors(N,K+1,Acc).
% is integer N factorable into M primes?
kthfactor(N,M) ->
case length(factors(N)) of M ->
factors(N);
_ ->
false end.
{out}
17> factors:kthfactor(1679,2). [73,23] 18> factors:kthfactor(1679,4). false 23> FS = [{X,factors:kthfactor(X,2)} || X <- lists:seq(50,500), factors:kthfactor(X,2) =/= false]. [{51,[17,3]}, {55,[11,5]}, {57,[19,3]}, {58,[29,2]}, {62,[31,2]}, {65,[13,5]}, {69,[23,3]}, {74,[37,2]}, {77,[11,7]}, {82,[41,2]}, {85,[17,5]}, {86,[43,2]}, {87,[29,3]}, {91,[13,7]}, {93,[31,3]}, {94,[47,2]}, {95,[19,5]}, {106,[53,2]}, {111,[37,3]}, {115,[23,5]}, {118,[59,2]}, {119,[17,7]}, {121,"\v\v"}, {122,[61,2]}, {123,[41,3]}, {129,[43|...]}, {133,[...]}, {134,...}, {...}|...]
Note, there is some junk character data in the output since we 'usually' have to filter for char sequences (it's not a bug, it's a feature!).
ERRE
PROGRAM SEMIPRIME_NUMBER
!VAR I%
PROCEDURE SEMIPRIME(N%->RESULT%)
LOCAL F%,P%
P%=2
LOOP
EXIT IF NOT(F%<2 AND P%*P%<=N%)
WHILE (N% MOD P%)=0 DO
N%=N% DIV P%
F%+=1
END WHILE
P%+=1
END LOOP
RESULT%=F%-(N%>1)=2
END PROCEDURE
BEGIN
PRINT(CHR$(12);) !CLS
FOR I%=2 TO 100 DO
SEMIPRIME(I%->RESULT%)
IF RESULT% THEN PRINT(I%;) END IF
END FOR
PRINT
END PROGRAM
Output is the same of "C" version.
Euler
begin new isSemiPrime; new x; label xLoop; isSemiPrime <- ` formal v; begin new a; new b; new c; label again; a <- 2; b <- 0; c <- v; again: if b < 3 and c > 1 then begin if c mod a = 0 then begin c <- c % a; b <- b + 1 end else a <- a + 1; goto again end else 0; b = 2 end ' ; x <- 1; xLoop: if [ x <- x + 1 ] < 100 then begin if isSemiPrime( x ) then out x else 0; goto xLoop end else 0 end $
- Output:
NUMBER 4 NUMBER 6 NUMBER 9 NUMBER 10 ... NUMBER 91 NUMBER 93 NUMBER 94 NUMBER 95
F#
let isSemiprime (n: int) =
let rec loop currentN candidateFactor numberOfFactors =
if numberOfFactors > 2 then numberOfFactors
elif currentN = candidateFactor then numberOfFactors+1
elif currentN % candidateFactor = 0 then loop (currentN/candidateFactor) candidateFactor (numberOfFactors+1)
else loop currentN (candidateFactor+1) numberOfFactors
if n < 2 then false else 2 = loop n 2 0
seq { 1 .. 100 } |> Seq.choose (fun n -> if isSemiprime n then Some(n) else None)
|> Seq.toList |> printfn "%A"
seq { 1675 .. 1680 }
|> Seq.choose (fun n -> if isSemiprime n then Some(n) else None)
|> Seq.toList
|> printfn "%A"
- Output:
[4; 6; 9; 10; 14; 15; 21; 22; 25; 26; 33; 34; 35; 38; 39; 46; 49; 51; 55; 57; 58; 62; 65; 69; 74; 77; 82; 85; 86; 87; 91; 93; 94; 95] [1678; 1679]
Factor
USING: io kernel math.primes.factors prettyprint sequences ;
: semiprime? ( n -- ? ) factors length 2 = ;
Displaying the semiprimes under 100:
100 <iota> [ semiprime? ] filter [ bl ] [ pprint ] interleave nl
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Forth
: semiprime?
0 swap dup 2 do
begin dup i mod 0= while i / swap 1+ swap repeat
over 1 > over i dup * < or if leave then
loop 1 > abs + 2 =
;
: test 100 2 do i semiprime? if i . then loop cr ;
- Output:
test 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 ok
Frink
isSemiprime[n] := length[factorFlat[n]] == 2
Go
package main
import "fmt"
func semiprime(n int) bool {
nf := 0
for i := 2; i <= n; i++ {
for n%i == 0 {
if nf == 2 {
return false
}
nf++
n /= i
}
}
return nf == 2
}
func main() {
for v := 1675; v <= 1680; v++ {
fmt.Println(v, "->", semiprime(v))
}
}
- Output:
1675 -> false 1676 -> false 1677 -> false 1678 -> true 1679 -> true 1680 -> false
Haskell
isSemiprime :: Int -> Bool
isSemiprime n = (length factors) == 2 && (product factors) == n ||
(length factors) == 1 && (head factors) ^ 2 == n
where factors = primeFactors n
Alternative (and faster) implementation using pattern matching:
isSemiprime :: Int -> Bool
isSemiprime n = case (primeFactors n) of
[f1, f2] -> f1 * f2 == n
otherwise -> False
Icon and Unicon
Works in both languages:
link "factors"
procedure main(A)
every nf := semiprime(n := !A) do write(n," = ",nf[1]," * ",nf[2])
end
procedure semiprime(n) # Succeeds and produces the factors only if n is semiprime.
return (2 = *(nf := factors(n)), nf)
end
- Output:
->semiprime 1676 1677 1678 1679 1680 1678 = 2 * 839 1679 = 23 * 73 ->
J
Implementation:
isSemiPrime=: 2 = #@q: ::0:"0
Example use: find all semiprimes less than 100:
I. isSemiPrime i.100
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Description: factor the number and count the primes in the factorization, is it 2?
Java
Inspired by: #Ada
Like the Ada example here, this borrows from Prime decomposition and shows the semiprimes below 100 and from 1675 to 1680.
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class SemiPrime{
private static final BigInteger TWO = BigInteger.valueOf(2);
public static List<BigInteger> primeDecomp(BigInteger a){
// impossible for values lower than 2
if(a.compareTo(TWO) < 0){
return null;
}
//quickly handle even values
List<BigInteger> result = new ArrayList<BigInteger>();
while(a.and(BigInteger.ONE).equals(BigInteger.ZERO)){
a = a.shiftRight(1);
result.add(TWO);
}
//left with odd values
if(!a.equals(BigInteger.ONE)){
BigInteger b = BigInteger.valueOf(3);
while(b.compareTo(a) < 0){
if(b.isProbablePrime(10)){
BigInteger[] dr = a.divideAndRemainder(b);
if(dr[1].equals(BigInteger.ZERO)){
result.add(b);
a = dr[0];
}
}
b = b.add(TWO);
}
result.add(b); //b will always be prime here...
}
return result;
}
public static boolean isSemi(BigInteger x){
List<BigInteger> decomp = primeDecomp(x);
return decomp != null && decomp.size() == 2;
}
public static void main(String[] args){
for(int i = 2; i <= 100; i++){
if(isSemi(BigInteger.valueOf(i))){
System.out.print(i + " ");
}
}
System.out.println();
for(int i = 1675; i <= 1680; i++){
if(isSemi(BigInteger.valueOf(i))){
System.out.print(i + " ");
}
}
}
}
- Output:
4 6 9 10 14 15 21 22 25 26 27 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 81 82 85 86 87 91 93 94 95 1678 1679
jq
Works with gojq, the Go implementation of jq
def is_semiprime:
{i: 2, n: ., nf: 0}
| until( .i > .n or .result;
until(.n % .i != 0 or .result;
if .nf == 2 then .result = 0
else .nf += 1
| .n /= .i
end)
| .i += 1)
| if .result == 0 then false else .nf == 2 end;
Examples
(1679, 1680) | "\(.) => \(is_semiprime)"
- Output:
1679 => true 1680 => false
Julia
using Primes
issemiprime(n::Integer) = sum(values(factor(n))) == 2
@show filter(issemiprime, 1:100)
- Output:
filter(issemiprime, 1:100) = [4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
Kotlin
// version 1.1.2
fun isSemiPrime(n: Int): Boolean {
var nf = 0
var nn = n
for (i in 2..nn)
while (nn % i == 0) {
if (nf == 2) return false
nf++
nn /= i
}
return nf == 2
}
fun main(args: Array<String>) {
for (v in 1675..1680)
println("$v ${if (isSemiPrime(v)) "is" else "isn't"} semi-prime")
}
- Output:
1675 isn't semi-prime 1676 isn't semi-prime 1677 isn't semi-prime 1678 is semi-prime 1679 is semi-prime 1680 isn't semi-prime
Ksh
#!/bin/ksh
# Semiprime - As translated from C
# # Variables:
#
# # Functions:
#
# Function _issemiprime(p2) - return 1 if p2 semiprime, 0 if not
#
function _issemiprime {
typeset _p2 ; integer _p2=$1
typeset _p _f ; integer _p _f=0
for ((_p=2; (_f<2 && _p*_p<=_p2); _p++)); do
while (( _p2 % _p == 0 )); do
(( _p2 /= _p ))
(( _f++ ))
done
done
return $(( _f + (_p2 > 1) == 2 ))
}
######
# main #
######
integer i
for ((i=2; i<100; i++)); do
_issemiprime ${i}
(( $? )) && printf " %d" ${i}
done
echo
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Lambdatalk
{def factors
{def factors.r
{lambda {:n :i}
{if {> :i :n}
then
else {if {= {% :n :i} 0}
then :i {factors.r {/ :n :i} :i}
else {factors.r :n {+ :i 1}} }}}}
{lambda {:n}
{A.new {factors.r :n 2} }}}
-> factors
{factors 491} -> [491] // prime
{factors 492} -> [2,2,3,41]
{factors 493} -> [17,29] // semiprime
{factors 494} -> [2,13,19]
{factors 495} -> [3,3,5,11]
{factors 496} -> [2,2,2,2,31]
{factors 497} -> [7,71] // semiprime
{factors 498} -> [2,3,83]
{factors 499} -> [499] // prime
{factors 500} -> [2,2,5,5,5]
{S.replace \s by space in
{S.map {lambda {:i}
{let { {:i :i} {:f {factors :i}}
} {if {= {A.length :f} 2}
then :i={A.first :f}*{A.last :f}
else}} }
{S.serie 1 100}}}
->
4 = 2*2
6 = 2*3
9 = 3*3
10 = 2*5
14 = 2*7
15 = 3*5
21 = 3*7
22 = 2*11
25 = 5*5
26 = 2*13
33 = 3*11
34 = 2*17
35 = 5*7
38 = 2*19
39 = 3*13
46 = 2*23
49 = 7*7
51 = 3*17
55 = 5*11
57 = 3*19
58 = 2*29
62 = 2*31
65 = 5*13
69 = 3*23
74 = 2*37
77 = 7*11
82 = 2*41
85 = 5*17
86 = 2*43
87 = 3*29
91 = 7*13
93 = 3*31
94 = 2*47
95 = 5*19
Lingo
on isSemiPrime (n)
div = 2
cnt = 0
repeat while cnt < 3 and n <> 1
if n mod div = 0 then
n = n / div
cnt = cnt + 1
else
div = div + 1
end if
end repeat
return cnt=2
end
res = []
repeat with i = 1 to 100
if isSemiPrime(i) then res.add(i)
end repeat
put res
- Output:
-- [4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
Lua
function semiprime (n)
local divisor, count = 2, 0
while count < 3 and n ~= 1 do
if n % divisor == 0 then
n = n / divisor
count = count + 1
else
divisor = divisor + 1
end
end
return count == 2
end
for n = 1675, 1680 do
print(n, semiprime(n))
end
- Output:
1675 false 1676 false 1677 false 1678 true 1679 true 1680 false
Maple
SemiPrimes := proc( n )
local fact;
fact := NumberTheory:-Divisors( n ) minus {1, n};
if numelems( fact ) in {1,2} and not( member( 'false', isprime ~ ( fact ) ) ) then
return n;
else
return NULL;
end if;
end proc:
{ seq( SemiPrimes( i ), i = 1..100 ) };
Output:
{ 4,6,9,10,14,15,21,22,25,26,33,34,35,38,39,46,49,51,55,57,58,62,65,69,74,77,82,85,86,87,91,93,94,95 }
Mathematica /Wolfram Language
semiPrimeQ[n_Integer] := Module[{factors, numfactors},
factors = FactorInteger[n] // Transpose;
numfactors = factors[[2]] // Total ;
numfactors == 2
]
Example use: find all semiprimes less than 100:
semiPrimeQ[#] & /@ Range[100];
Position[%, True] // Flatten
- Output:
{4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95}
Maxima
/* The first part consider the cases of squares of primes, the second part the remaining cases */
semiprimep(n):=if integerp(sqrt(n)) and primep(sqrt(n)) then true else lambda([x],length(ifactors(x))=2 and unique(map(second,ifactors(x)))=[1])(n)$
/* Example */
sublist(makelist(i,i,100),semiprimep);
- Output:
[4,6,9,10,14,15,21,22,25,26,33,34,35,38,39,46,49,51,55,57,58,62,65,69,74,77,82,85,86,87,91,93,94,95]
MiniScript
isSemiprime = function(num)
divisor = 2
primes = 0
while primes < 3 and num != 1
if num % divisor == 0 then
num = num / divisor;
primes = primes + 1
else
divisor = divisor + 1
end if
end while
return primes == 2
end function
print "Semiprimes up to 100:"
results = []
for i in range(2, 100)
if isSemiprime(i) then results.push i
end for
print results
- Output:
Semiprimes up to 100: [4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
NewLisp
;;; Practically identical to the EchoLisp solution
(define (semiprime? n)
(= (length (factor n)) 2))
;
;;; Example (sadly factor doesn't accept bigints)
(println (filter semiprime? (sequence 2 100)))
(setq x 9223372036854775807)
(while (not (semiprime? x)) (-- x))
(println "Biggest semiprime reachable: " x " = " ((factor x) 0) " x " ((factor x) 1))
- Output:
(4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95) Biggest semiprime reachable: 9223372036854775797 = 3 x 3074457345618258599
Nim
proc isSemiPrime(k: int): bool =
var
i = 2
count = 0
x = k
while i <= x and count < 3:
if x mod i == 0:
x = x div i
inc count
else:
inc i
result = count == 2
for k in 1675..1680:
echo k, (if k.isSemiPrime(): " is" else: " isn’t"), " semi-prime"
- Output:
1675 isn't semi-prime 1676 isn't semi-prime 1677 isn't semi-prime 1678 is semi-prime 1679 is semi-prime 1680 isn't semi-prime
Objeck
class SemiPrime {
function : Main(args : String[]) ~ Nil {
for(i := 0; i < 100; i+=1;) {
if(SemiPrime(i)) {
"{$i} "->Print();
};
};
IO.Console->PrintLine();
}
function : native : SemiPrime(n : Int) ~ Bool {
nf := 0;
for(i := 2; i <= n; i+=1;) {
while(n%i = 0) {
if(nf = 2) {
return false;
};
nf+=1;
n /= i;
};
};
return nf = 2;
}
}
Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Oforth
func: semiprime(n)
| i |
0 2 n sqrt asInteger for: i [ while(n i /mod swap 0 &=) [ ->n 1+ ] drop ]
n 1 > ifTrue: [ 1+ ] 2 == ;
- Output:
100 seq filter(#semiprime) println [4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
PARI/GP
issemi(n)=bigomega(n)==2
A faster version might use trial division and primality testing:
issemi(n)={
forprime(p=2,97,if(n%p==0, return(isprime(n/p))));
if(isprime(n), return(0));
bigomega(n)==2
};
To get faster, partial factorization can be used. At this time GP does not have access to meaningful partial factorization (though it can get it to some extent through flags on factorint
), so this version is in PARI:
long
issemiprime(GEN n)
{
if (typ(n) != t_INT)
pari_err_TYPE("issemiprime", n);
if (signe(n) <= 0)
return 0;
ulong nn = itou_or_0(n);
if (nn)
return uissemiprime(nn);
pari_sp ltop = avma;
if (!mpodd(n)) {
long ret = mod4(n) && isprime(shifti(n, -1));
avma = ltop;
return ret;
}
long p;
forprime_t primepointer;
u_forprime_init(&primepointer, 3, 997);
while ((p = u_forprime_next(&primepointer))) {
if (dvdis(n, p)) {
long ret = isprime(diviuexact(n, p));
avma = ltop;
return ret;
}
}
if (isprime(n))
return 0;
if (DEBUGLEVEL > 3)
pari_printf("issemi: Number is a composite with no small prime factors; using general factoring mechanisms.");
GEN fac = Z_factor_until(n, shifti(n, -1)); /* Find a nontrivial factor -- returns just the factored part */
GEN expo = gel(fac, 2);
GEN pr = gel(fac, 1);
long len = glength(expo);
if (len > 2) {
avma = ltop;
return 0;
}
if (len == 2) {
if (cmpis(gel(expo, 1), 1) > 0 || cmpis(gel(expo, 2), 1) > 0) {
avma = ltop;
return 0;
}
GEN P = gel(pr, 1);
GEN Q = gel(pr, 2);
long ret = isprime(P) && isprime(Q) && equalii(mulii(P, Q), n);
avma = ltop;
return ret;
}
if (len == 1) {
long e = itos(gel(expo, 1));
if (e == 2) {
GEN P = gel(pr, 1);
long ret = isprime(P) && equalii(sqri(P), n);
avma = ltop;
return ret;
} else if (e > 2) {
avma = ltop;
return 0;
}
GEN P = gel(pr, 1);
long ret = isprime(P) && isprime(diviiexact(n, P));
avma = ltop;
return ret;
}
pari_err_BUG(pari_sprintf("Z_factor_until returned an unexpected value %Ps at n = %Ps, exiting...", fac, n));
avma = ltop;
return 0; /* never used */
}
Pascal
program SemiPrime;
{$IFDEF FPC}
{$Mode objfpc}// compiler switch to use result
{$ELSE}
{$APPTYPE CONSOLE} // for Delphi
{$ENDIF}
uses
primTrial;
function isSemiprime(n: longWord;doWrite:boolean): boolean;
var
fac1 : LongWord;
begin
//a simple isAlmostPrime(n,2) would do without output;
fac1 := SmallFactor(n);
IF fac1 < n then
Begin
n := n div fac1;
result := SmallFactor(n) = n;
if result AND doWrite then
write(fac1:10,'*',n:11)
end
else
result := false;
end;
var
i,k : longWord;
BEGIN
For i := 2 to 97 do
IF isSemiPrime(i,false) then
write(i:3);
writeln;
//test for big numbers
k := 4000*1000*1000;
i := k-100;
repeat
IF isSemiPrime(i,true) then
writeln(' = ',i:10);
inc(i);
until i> k;
END.
- output
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 71* 56338027 = 3999999917 42307* 94547 = 3999999929 59* 67796609 = 3999999931 5* 799999987 = 3999999935 2* 1999999973 = 3999999946 11* 363636359 = 3999999949 103* 38834951 = 3999999953 12007* 333139 = 3999999973 7* 571428569 = 3999999983 5* 799999999 = 3999999995
Perl
With late versions of the ntheory module, we can use is_semiprime to get answers for 64-bit numbers in single microseconds.
use ntheory "is_semiprime";
for ([1..100], [1675..1681], [2,4,99,100,1679,5030,32768,1234567,9876543,900660121]) {
print join(" ",grep { is_semiprime($_) } @$_),"\n";
}
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 1678 1679 1681 4 1679 1234567 900660121
One can also use factor in scalar context, which gives the number of factors (like bigomega in Pari/GP and PrimeOmega in Mathematica). This skips some optimizations but at these small sizes it doesn't matter.
use ntheory "factor";
print join(" ", grep { scalar factor($_) == 2 } 1..100),"\n";
While is_semiprime is the fastest way, we can do some of its pre-tests by hand, such as:
use ntheory qw/factor is_prime trial_factor/;
sub issemi {
my $n = shift;
if ((my @p = trial_factor($n,500)) > 1) {
return 0 if @p > 2;
return !!is_prime($p[1]) if @p == 2;
}
2 == factor($n);
}
Phix
function semiprime(integer n) return length(prime_factors(n,true))==2 end function pp(filter(tagset(100)&tagset(1680,1675),semiprime),{pp_IntCh,false})
- Output:
{4,6,9,10,14,15,21,22,25,26,33,34,35,38,39,46,49,51,55,57,58,62,65,69,74,77, 82,85,86,87,91,93,94,95,1678,1679}
PHP
<?php
// Semiprime
function primeFactorsCount($n)
{
$n = abs($n);
$count = 0; // Result
if ($n >= 2)
for ($factor = 2; $factor <= $n; $factor++)
while ($n % $factor == 0) {
$count++;
$n /= $factor;
}
return $count;
}
echo "Enter an integer: ",
$n = (int)fgets(STDIN);
echo (primeFactorsCount($n) == 2 ?
"It is a semiprime.\n" : "It is not a semiprime.\n");
?>
- Output:
Enter an integer: 60 It is not a semiprime.
Enter an integer: 33 It is a semiprime.
PicoLisp
(de factor (N)
(make
(let
(D 2
L (1 2 2 . (4 2 4 2 4 6 2 6 .))
M (sqrt N) )
(while (>= M D)
(if (=0 (% N D))
(setq M
(sqrt (setq N (/ N (link D)))) )
(inc 'D (pop 'L)) ) )
(link N) ) ) )
(println
(filter
'((X)
(let L (factor X)
(and (cdr L) (not (cddr L))) ) )
(conc (range 1 100) (range 1675 1680)) ) )
(bye)
- Output:
(4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 1678 1679)
PL/0
PL/0 does not handle strings. So, the program waits for entering a number, and then displays 1 if the number is a semiprime, 0 otherwise.
var n, count, factor;
begin
? n;
if n < 0 then n := -n;
count := 0;
if n >= 2 then
begin
factor := 2;
while factor <= n do
begin
while (n / factor) * factor = n do
begin
count := count + 1; n := n / factor
end;
factor := factor + 1
end;
end;
if count = 2 then ! 1;
if count <> 2 then ! 0
end.
PL/I
*process source attributes xref nest or(!);
/*--------------------------------------------------------------------
* 22.02.2014 Walter Pachl using the is_prime code from
* PL/I 'prime decomposition'
* 23.02. WP start test for second prime with 2 or first prime found
*-------------------------------------------------------------------*/
spb: Proc options(main);
Dcl a(10) Bin Fixed(31)
Init(900660121,2,4,1679,1234567,32768,99,9876543,100,5040);
Dcl (x,n,nf,i,j) Bin Fixed(31) Init(0);
Dcl f(3) Bin Fixed(31);
Dcl txt Char(30) Var;
Dcl bit Bit(1);
Do i=1 To hbound(a);
bit=is_semiprime(a(i));
Select(nf);
When(0,1) txt=' is prime';
When(2) txt=' is semiprime '!!factors(a(i));
Otherwise txt=' is NOT semiprime '!!factors(a(i));
End;
Put Edit(a(i),bit,txt)(Skip,f(10),x(1),b(1),a);
End;
is_semiprime: Proc(x) Returns(bit(1));
/*--------------------------------------------------------------------
* Returns '1'b if x is semiprime, '0'b otherwise
* in addition
* it sets f(1) and f(2) to the first (or only) prime factor(s)
*-------------------------------------------------------------------*/
Dcl x Bin Fixed(31);
nf=0;
f=0;
x=a(i);
n=x;
f(1)=2;
loop:
Do While(nf<=2 & n>1);
If is_prime(n) Then Do;
Call mem(n);
Leave loop;
End;
Else Do;
loop2:
Do j=f(1) By 1 While(j*j<=n);
If is_prime(j)&mod(n,j)=0 Then Do;
Call mem(j);
n=n/j;
Leave loop2;
End;
End;
End;
End;
Return(nf=2);
End;
is_prime: Proc(n) Returns(bit(1));
Dcl n Bin Fixed(31);
Dcl i Bin Fixed(31);
If n < 2 Then Return('0'b);
If n = 2 Then Return('1'b);
If mod(n,2)=0 Then Return('0'b);
Do i = 3 by 2 While(i*i<=n);
If mod(n,i)=0 Then Return('0'b);
End;
Return('1'b);
End is_prime;
mem: Proc(x);
Dcl x Bin Fixed(31);
nf+=1;
f(nf)=x;
End;
factors: Proc(x) Returns(Char(150) Var);
Dcl x Bin Fixed(31);
Dcl (res,net) Char(150) Var Init('');
Dcl (i,f3) Bin Fixed(31);
res=f(1)!!'*'!!f(2);
f3=x/(f(1)*f(2));
If f3>1 Then
res=res!!'*'!!f3;
Do i=1 To length(res);
If substr(res,i,1)>' ' Then
net=net!!substr(res,i,1);
End;
Return(net);
End;
End spb;
Output:
900660121 1 is semiprime 30011*30011 2 0 is prime 4 1 is semiprime 2*2 1679 1 is semiprime 23*73 1234567 1 is semiprime 127*9721 32768 0 is NOT semiprime 2*2*8192 99 0 is NOT semiprime 3*3*11 9876543 0 is NOT semiprime 3*227*14503 100 0 is NOT semiprime 2*2*25 5040 0 is NOT semiprime 2*2*1260
PL/M
... under CP/M (or an emulator)
100H: /* FIND SOME SEMI-PRIMES - NUMBERS WITH EXACTLY 2 PRIME FACTORS */
/* CP/M BDOS SYSTEM CALL AND I/O ROUTINES */
BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END;
PR$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
PR$NL: PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END;
PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH */
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 PR$STRING( .N$STR( W ) );
END PR$NUMBER;
/* TASK */
/* RETURNS TRUE IF V IS SEMI-PRIME, FALSE OTHERWISE */
IS$SEMI$PRIME: PROCEDURE( V )BYTE;
DECLARE V ADDRESS;
DECLARE ( A, B, C ) ADDRESS;
A = 2; B = 0; C = V;
DO WHILE B < 3 AND C > 1;
IF C MOD A = 0 THEN DO;
C = C / A;
B = B + 1;
END;
ELSE A = A + 1;
END;
RETURN B = 2;
END IS$SEMI$PRIME;
DECLARE X ADDRESS;
DO X = 2 TO 99;
IF IS$SEMI$PRIME( X ) THEN DO;
CALL PR$NUMBER( X );
CALL PR$CHAR( ' ' );
END;
END;
EOF
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
PowerShell
function isPrime ($n) {
if ($n -le 1) {$false}
elseif (($n -eq 2) -or ($n -eq 3)) {$true}
else{
$m = [Math]::Floor([Math]::Sqrt($n))
(@(2..$m | where {($_ -lt $n) -and ($n % $_ -eq 0) }).Count -eq 0)
}
}
function semiprime ($n) {
if($n -gt 3) {
$lim = [Math]::Floor($n/2)+1
$i = 2
while(($i -lt $lim) -and ($n%$i -ne 0)){ $i += 1}
if($i -eq $lim){@()}
elseif(-not (isPrime ($n/$i))){@()}
else{@($i,($n/$i))}
} else {@()}
}
$OFS = " x "
"1679: $(semiprime 1679)"
"87: $(semiprime 87)"
"25: $(semiprime 25)"
"12: $(semiprime 12)"
"6: $(semiprime 6)"
$OFS = " "
"semiprime from 1 to 100: $(1..100 | where {semiprime $_})"
Output:
1679: 23 x 73 87: 3 x 29 25: 5 x 5 12: 6: 2 x 3 semiprime from 1 to 100: 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Prolog
works with swi-prolog
factors(N, FList):-
factors(N, 2, 0, FList).
factors(1, _, _Count, []).
factors(_, _, Count, []):- Count > 1. % break on 2 factors reached
factors(N, Start, Count, [Fac|FList]):-
N1 is floor(sqrt(N)),
between(Start, N1, Fac),
N mod Fac =:= 0,!,
N2 is N div Fac,
Count1 is Count + 1,
factors(N2, Fac, Count1, FList).
factors(N, _, _, [N]):- N >= 2.
semiPrimeList(Limit, List):-
findall(N, semiPrimes(2, Limit, N), List).
semiPrimes(Start, Limit, N):-
between(Start, Limit, N),
factors(N, [F1, F2]),
N =:= F1 * F2. % correct factors break
do:- semiPrimeList(100, SemiPrimes),
writeln(SemiPrimes),
findall(N, semiPrimes(1675, 1685, N), SemiPrimes2),
writeln(SemiPrimes2).
- Output:
?- do. [4,6,9,10,14,15,21,22,25,26,33,34,35,38,39,46,49,51,55,57,58,62,65,69,74,77,82,85,86,87,91,93,94,95] [1678,1679,1681,1685] true.
PROMAL
;;; find some semiprimes - numbers with two prime factors
PROGRAM semiPrimes
INCLUDE library
FUNC BYTE isSemiPrime
ARG WORD n
WORD f
WORD factorCount
BYTE result
BEGIN
f = 2
factorCount = 0
WHILE factorCount < 3 AND n > 1
WHILE n % f = 0
factorCount = factorCount + 1
n = n / f
f = f + 1
IF factorCOunt = 2
result = 1
ELSE
result = 0
RETURN result
END
WORD n
BEGIN
OUTPUT "Semiprimes under 100:#C "
FOR n = 1 TO 99
IF isSemiPrime( n )
OUTPUT " #W", n
OUTPUT "#CSemiprimes between 1670 and 1690:#C "
FOR n = 1670 TO 1690
IF isSemiPrime( n )
OUTPUT " #W", n
END
- Output:
Semiprimes under 100: 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 Semiprimes between 1670 and 1690: 1671 1673 1678 1679 1681 1685 1687 1689
Python
This imports Prime decomposition#Python
from prime_decomposition import decompose
def semiprime(n):
d = decompose(n)
try:
return next(d) * next(d) == n
except StopIteration:
return False
- Output:
From Idle:
>>> semiprime(1679)
True
>>> [n for n in range(1,101) if semiprime(n)]
[4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
>>>
Quackery
primefactors
is defined at Prime decomposition.
[ primefactors size 2 = ] is semiprime ( n --> b )
say "Semiprimes less than 100:" cr
100 times [ i^ semiprime if [ i^ echo sp ] ]
- Output:
Semiprimes less than 100: 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
Racket
The first implementation considers all pairs of factors multiplying up to the given number and determines if any of them is a pair of primes.
#lang racket
(require math)
(define (pair-factorize n)
"Return all two-number factorizations of a number"
(let ([up-limit (integer-sqrt n)])
(map (λ (x) (list x (/ n x)))
(filter (λ (x) (<= x up-limit)) (divisors n)))))
(define (semiprime n)
"Determine if a number is semiprime i.e. a product of two primes.
Check if any pair of complete factors consists of primes."
(for/or ((pair (pair-factorize n)))
(for/and ((el pair))
(prime? el))))
The alternative implementation operates directly on the list of prime factors and their multiplicities. It is approximately 1.6 times faster than the first one (according to some simple tests of mine).
#lang racket
(require math)
(define (semiprime n)
"Alternative implementation.
Check if there are two prime factors whose product is the argument
or if there is a single prime factor whose square is the argument"
(let ([prime-factors (factorize n)])
(or (and (= (length prime-factors) 1)
(= (expt (caar prime-factors) (cadar prime-factors)) n))
(and (= (length prime-factors) 2)
(= (foldl (λ (x y) (* (car x) y)) 1 prime-factors) n)))))
Raku
(formerly Perl 6) Here is a naive, grossly inefficient implementation.
sub is-semiprime (Int $n --> Bool) {
not $n.is-prime and
.is-prime given
$n div first $n %% *, flat grep &is-prime, 2 .. *;
}
use Test;
my @primes = flat grep &is-prime, 2 .. 100;
for ^5 {
nok is-semiprime([*] my @f1 = @primes.roll(1)), ~@f1;
ok is-semiprime([*] my @f2 = @primes.roll(2)), ~@f2;
nok is-semiprime([*] my @f3 = @primes.roll(3)), ~@f3;
nok is-semiprime([*] my @f4 = @primes.roll(4)), ~@f4;
}
- Output:
ok 1 - 17 ok 2 - 47 23 ok 3 - 23 37 41 ok 4 - 53 37 67 47 ok 5 - 5 ok 6 - 73 43 ok 7 - 13 53 71 ok 8 - 7 79 37 71 ok 9 - 41 ok 10 - 71 37 ok 11 - 37 53 43 ok 12 - 3 2 47 67 ok 13 - 17 ok 14 - 41 61 ok 15 - 71 31 79 ok 16 - 97 17 73 17 ok 17 - 61 ok 18 - 73 47 ok 19 - 13 19 5 ok 20 - 37 97 11 31
More efficient example
Here is a more verbose, but MUCH more efficient implementation. Demonstrating using it to find an infinite list of semiprimes and to check a range of integers to find the semiprimes.
sub is-semiprime ( Int $n where * > 0 ) {
return False if $n.is-prime;
my $factor = find-factor( $n );
return True if $factor.is-prime && ( $n div $factor ).is-prime;
False;
}
sub find-factor ( Int $n, $constant = 1 ) {
my $x = 2;
my $rho = 1;
my $factor = 1;
while $factor == 1 {
$rho *= 2;
my $fixed = $x;
for ^$rho {
$x = ( $x * $x + $constant ) % $n;
$factor = ( $x - $fixed ) gcd $n;
last if 1 < $factor;
}
}
$factor = find-factor( $n, $constant + 1 ) if $n == $factor;
$factor;
}
INIT my $start = now;
# Infinite list of semiprimes
constant @semiprimes = lazy gather for 4 .. * { .take if .&is-semiprime };
# Show the semiprimes < 100
say 'Semiprimes less than 100:';
say @semiprimes[^ @semiprimes.first: * > 100, :k ], "\n";
# Check individual integers, or in this case, a range
my $s = 2⁹⁷ - 1;
say "Is $_ semiprime?: ", .&is-semiprime for $s .. $s + 30;
say 'elapsed seconds: ', now - $start;
- Output:
Semiprimes less than 100: (4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95) Is 158456325028528675187087900671 semiprime?: True Is 158456325028528675187087900672 semiprime?: False Is 158456325028528675187087900673 semiprime?: False Is 158456325028528675187087900674 semiprime?: False Is 158456325028528675187087900675 semiprime?: False Is 158456325028528675187087900676 semiprime?: False Is 158456325028528675187087900677 semiprime?: False Is 158456325028528675187087900678 semiprime?: False Is 158456325028528675187087900679 semiprime?: False Is 158456325028528675187087900680 semiprime?: False Is 158456325028528675187087900681 semiprime?: False Is 158456325028528675187087900682 semiprime?: False Is 158456325028528675187087900683 semiprime?: False Is 158456325028528675187087900684 semiprime?: False Is 158456325028528675187087900685 semiprime?: False Is 158456325028528675187087900686 semiprime?: False Is 158456325028528675187087900687 semiprime?: False Is 158456325028528675187087900688 semiprime?: False Is 158456325028528675187087900689 semiprime?: False Is 158456325028528675187087900690 semiprime?: False Is 158456325028528675187087900691 semiprime?: False Is 158456325028528675187087900692 semiprime?: False Is 158456325028528675187087900693 semiprime?: False Is 158456325028528675187087900694 semiprime?: False Is 158456325028528675187087900695 semiprime?: False Is 158456325028528675187087900696 semiprime?: False Is 158456325028528675187087900697 semiprime?: False Is 158456325028528675187087900698 semiprime?: False Is 158456325028528675187087900699 semiprime?: False Is 158456325028528675187087900700 semiprime?: False Is 158456325028528675187087900701 semiprime?: True elapsed seconds: 0.0574433
REXX
version 1
/* REXX ---------------------------------------------------------------
* 20.02.2014 Walter Pachl relying on 'prime decomposition'
* 21.02.2014 WP Clarification: I copied the algorithm created by
* Gerard Schildberger under the task referred to above
* 21.02.2014 WP Make sure that factr is not called illegally
*--------------------------------------------------------------------*/
Call test 4
Call test 9
Call test 10
Call test 12
Call test 1679
Exit
test:
Parse Arg z
If is_semiprime(z) Then Say z 'is semiprime' fl
Else Say z 'is NOT semiprime' fl
Return
is_semiprime:
Parse Arg z
If z<1 | datatype(z,'W')=0 Then Do
Say 'Argument ('z') must be a natural number (1, 2, 3, ...)'
fl=''
End
Else
fl=factr(z)
Return words(fl)=2
/*----------------------------------FACTR subroutine-----------------*/
factr: procedure; parse arg x 1 z,list /*sets X&Z to arg1, LIST=''. */
if x==1 then return '' /*handle the special case of X=1.*/
j=2; call .factr /*factor for the only even prime.*/
j=3; call .factr /*factor for the 1st odd prime.*/
j=5; call .factr /*factor for the 2nd odd prime.*/
j=7; call .factr /*factor for the 3rd odd prime.*/
j=11; call .factr /*factor for the 4th odd prime.*/
j=13; call .factr /*factor for the 5th odd prime.*/
j=17; call .factr /*factor for the 6th odd prime.*/
/* [?] could be optimized more.*/
/* [?] J in loop starts at 17+2*/
do y=0 by 2; j=j+2+y//4 /*insure J isn't divisible by 3. */
if right(j,1)==5 then iterate /*fast check for divisible by 5. */
if j*j>z then leave /*are we higher than the v of Z ?*/
if j>Z then leave /*are we higher than value of Z ?*/
call .factr /*invoke .FACTR for some factors.*/
end /*y*/ /* [?] only tests up to the v X.*/
/* [?] LIST has a leading blank.*/
if z==1 then return list /*if residual=unity, don't append*/
return list z /*return list, append residual. */
/*-------------------------------.FACTR internal subroutine----------*/
.factr: do while z//j==0 /*keep dividing until we can't. */
list=list j /*add number to the list (J). */
z=z%j /*% (percent) is integer divide.*/
end /*while z··· */ /* // ?---remainder integer ÷.*/
return /*finished, now return to invoker*/
Output
4 is semiprime 2 2 9 is semiprime 3 3 10 is semiprime 2 5 12 is NOT semiprime 2 2 3 1679 is semiprime 23 73
version 2
The method used is to examine integers, skipping primes.
If it's composite (the 1st factor is prime), then check if the 2nd factor is prime. If so, the number is a semiprime.
The isPrime function could be optimized by utilizing an integer square root function instead of testing if j*j>x for every divisor.
/*REXX program determines if any integer (or a range of integers) is/are semiprime. */
parse arg bot top . /*obtain optional arguments from the CL*/
if bot=='' | bot=="," then bot=random() /*None given? User wants us to guess.*/
if top=='' | top=="," then top=bot /*maybe define a range of numbers. */
tell= top=>0 | top==bot /*should results be shown to the term? */
w=max(length(bot), length(top)) + 5 /*obtain the maximum width of numbers. */
numeric digits max(9, w) /*ensure there're enough decimal digits*/
#=0 /*initialize number of semiprimes found*/
do n=bot to abs(top) /*show results for a range of numbers. */
?=isSemiPrime(n); #=#+? /*Is N a semiprime?; Maybe bump counter*/
if tell then say right(n,w) right(word("isn't" 'is', ?+1), 6) 'semiprime.'
end /*n*/
say
if bot\==top then say 'found ' # " semiprimes."
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
isPrime: procedure; parse arg x; if x<2 then return 0 /*number too low?*/
if wordpos(x, '2 3 5 7 11 13 17 19 23')\==0 then return 1 /*it's low prime.*/
if x//2==0 then return 0; if x//3==0 then return 0 /*÷ by 2; ÷ by 3?*/
do j=5 by 6 until j*j>x; if x//j==0 then return 0 /*not a prime. */
if x//(j+2)==0 then return 0 /* " " " */
end /*j*/
return 1 /*indicate that X is a prime number. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
isSemiPrime: procedure; parse arg x; if x<4 then return 0
do i=2 for 2; if x//i==0 then if isPrime(x%i) then return 1
else return 0
end /*i*/
/* ___ */
do j=5 by 6; if j*j>x then return 0 /* > √ x ?*/
do k=j by 2 for 2; if x//k==0 then if isPrime(x%k) then return 1
else return 0
end /*k*/ /* [↑] see if 2nd factor is prime or ¬*/
end /*j*/ /* [↑] J is never a multiple of three.*/
- output when using the input of: -1 106
(Shown at 5/6 size.)
-1 isn't semiprime. 0 isn't semiprime. 1 isn't semiprime. 2 isn't semiprime. 3 isn't semiprime. 4 is semiprime. 5 isn't semiprime. 6 is semiprime. 7 isn't semiprime. 8 isn't semiprime. 9 is semiprime. 10 is semiprime. 11 isn't semiprime. 12 isn't semiprime. 13 isn't semiprime. 14 is semiprime. 15 is semiprime. 16 isn't semiprime. 17 isn't semiprime. 18 isn't semiprime. 19 isn't semiprime. 20 isn't semiprime. 21 is semiprime. 22 is semiprime. 23 isn't semiprime. 24 isn't semiprime. 25 is semiprime. 26 is semiprime. 27 isn't semiprime. 28 isn't semiprime. 29 isn't semiprime. 30 isn't semiprime. 31 isn't semiprime. 32 isn't semiprime. 33 is semiprime. 34 is semiprime. 35 is semiprime. 36 isn't semiprime. 37 isn't semiprime. 38 is semiprime. 39 is semiprime. 40 isn't semiprime. 41 isn't semiprime. 42 isn't semiprime. 43 isn't semiprime. 44 isn't semiprime. 45 isn't semiprime. 46 is semiprime. 47 isn't semiprime. 48 isn't semiprime. 49 is semiprime. 50 isn't semiprime. 51 is semiprime. 52 isn't semiprime. 53 isn't semiprime. 54 isn't semiprime. 55 is semiprime. 56 isn't semiprime. 57 is semiprime. 58 is semiprime. 59 isn't semiprime. 60 isn't semiprime. 61 isn't semiprime. 62 is semiprime. 63 isn't semiprime. 64 isn't semiprime. 65 is semiprime. 66 isn't semiprime. 67 isn't semiprime. 68 isn't semiprime. 69 is semiprime. 70 isn't semiprime. 71 isn't semiprime. 72 isn't semiprime. 73 isn't semiprime. 74 is semiprime. 75 isn't semiprime. 76 isn't semiprime. 77 is semiprime. 78 isn't semiprime. 79 isn't semiprime. 80 isn't semiprime. 81 isn't semiprime. 82 is semiprime. 83 isn't semiprime. 84 isn't semiprime. 85 is semiprime. 86 is semiprime. 87 is semiprime. 88 isn't semiprime. 89 isn't semiprime. 90 isn't semiprime. 91 is semiprime. 92 isn't semiprime. 93 is semiprime. 94 is semiprime. 95 is semiprime. 96 isn't semiprime. 97 isn't semiprime. 98 isn't semiprime. 99 isn't semiprime. 100 isn't semiprime. 101 isn't semiprime. 102 isn't semiprime. 103 isn't semiprime. 104 isn't semiprime. 105 isn't semiprime. 106 is semiprime. found 35 semiprimes.
- output when using the input of: 99888111555 99888111600
(Shown at 5/6 size.)
99888111555 isn't semiprime. 99888111556 isn't semiprime. 99888111557 isn't semiprime. 99888111558 isn't semiprime. 99888111559 isn't semiprime. 99888111560 isn't semiprime. 99888111561 isn't semiprime. 99888111562 isn't semiprime. 99888111563 is semiprime. 99888111564 isn't semiprime. 99888111565 isn't semiprime. 99888111566 is semiprime. 99888111567 isn't semiprime. 99888111568 isn't semiprime. 99888111569 is semiprime. 99888111570 isn't semiprime. 99888111571 isn't semiprime. 99888111572 isn't semiprime. 99888111573 isn't semiprime. 99888111574 is semiprime. 99888111575 isn't semiprime. 99888111576 isn't semiprime. 99888111577 isn't semiprime. 99888111578 is semiprime. 99888111579 isn't semiprime. 99888111580 isn't semiprime. 99888111581 isn't semiprime. 99888111582 isn't semiprime. 99888111583 isn't semiprime. 99888111584 isn't semiprime. 99888111585 isn't semiprime. 99888111586 isn't semiprime. 99888111587 isn't semiprime. 99888111588 isn't semiprime. 99888111589 isn't semiprime. 99888111590 isn't semiprime. 99888111591 is semiprime. 99888111592 isn't semiprime. 99888111593 is semiprime. 99888111594 isn't semiprime. 99888111595 isn't semiprime. 99888111596 isn't semiprime. 99888111597 isn't semiprime. 99888111598 isn't semiprime. 99888111599 isn't semiprime. 99888111600 isn't semiprime. found 7 semiprimes.
version 3, with memoization
This REXX version is overt 20% faster than version 2 (when in the millions range).
If the 2nd argument (top) is negative (it's absolute value is used), individual numbers in the range aren't shown, but the count of semiprimes found is shown.
It gets its speed increase by the use of memoization of the prime numbers found, an unrolled primality (division) check, and other speed improvements.
/*REXX program determines if any integer (or a range of integers) is/are semiprime. */
parse arg bot top . /*obtain optional arguments from the CL*/
if bot=='' | bot=="," then bot=random() /*None given? User wants us to guess.*/
if top=='' | top=="," then top=bot /*maybe define a range of numbers. */
tell= bot=>0 & top=>0 /*should results be shown to the term? */
w=max(length(bot), length(top)) /*obtain the maximum width of numbers. */
!.=; !.2=1; !.3=1; !.5=1; !.7=1; !.11=1; !.13=1; !.17=1; !.19=1; !.23=1; !.29=1; !.31=1
numeric digits max(9, w) /*ensure there're enough decimal digits*/
#=0 /*initialize number of semiprimes found*/
do n=abs(bot) to abs(top) /*show results for a range of numbers. */
?=isSemiPrime(n); #=#+? /*Is N a semiprime?; Maybe bump counter*/
if tell then say right(n,w) right(word("isn't" 'is', ?+1), 6) 'semiprime.'
end /*n*/
say
if bot\==top then say 'found ' # " semiprimes."
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
isPrime: procedure expose !.; parse arg x; if x<2 then return 0 /*number too low?*/
if !.x==1 then return 1 /*a known prime. */
if x// 2==0 then return 0; if x//3==0 then return 0 /*÷ by 2;÷by 3?*/
parse var x '' -1 _; if _==5 then return 0 /*last digit a 5?*/
if x// 7==0 then return 0; if x//11==0 then return 0 /*÷ by 7;÷by 11?*/
if x//13==0 then return 0; if x//17==0 then return 0 /*÷ by 13;÷by 17?*/
if x//19==0 then return 0; if x//23==0 then return 0 /*÷ by 19;÷by 23?*/
do j=29 by 6 until j*j>x; if x//j==0 then return 0 /*not a prime. */
if x//(j+2)==0 then return 0 /* " " " */
end /*j*/
!.x=1; return 1 /*indicate that X is a prime number. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
isSemiPrime: procedure expose !.; parse arg x; if x<4 then return 0
do i=2 for 2; if x//i==0 then if isPrime(x%i) then return 1
else return 0
end /*i*/
/* ___ */
do j=5 by 6 until j*j>x /* > √ x ?*/
do k=j by 2 for 2; if x//k==0 then if isPrime(x%k) then return 1
else return 0
end /*k*/ /* [↑] see if 2nd factor is prime or ¬*/
end /*j*/ /* [↑] J is never a multiple of three.*/
return 0
- output is identical to the previous REXX version.
Summary Versions 1-3
Version 1 relies on factorization, Versions 2 and 3 on primality tests. Both methods are based on trial division, and become slow for big semiprimes.
To show this, Versions 1-3 ran with some numbers taken from Ruby, with timings for each semiprime check shown. Results are (ooRexx):
Version 1 4722366482869645213649 isn't semiprime. (3.988 seconds) 4722366482869645213650 isn't semiprime. (0.004 seconds) 4722366482869645213651 is semiprime. (11.443 seconds) 4722366482869645213652 isn't semiprime. (12.992 seconds) 4722366482869645213653 isn't semiprime. (148.297 seconds) Version 2 4722366482869645213645 isn't semiprime. (0.000 seconds) 4722366482869645213646 isn't semiprime. (0.000 seconds) 4722366482869645213647 isn't semiprime. (0.001 seconds) 4722366482869645213648 isn't semiprime. (0.000 seconds) 4722366482869645213649 isn't semiprime. (0.060 seconds) 4722366482869645213650 isn't semiprime. (0.000 seconds) 4722366482869645213651 is semiprime. (16.645 seconds) 4722366482869645213652 isn't semiprime. (0.000 seconds) 4722366482869645213653 isn't semiprime. (0.000 seconds) 4722366482869645213654 isn't semiprime. (0.001 seconds) 4722366482869645213655 isn't semiprime. (0.000 seconds) 4722366482869645213656 isn't semiprime. (0.000 seconds) 4722366482869645213657 isn't semiprime. (0.000 seconds) 4722366482869645213658 isn't semiprime. (0.000 seconds) 4722366482869645213659 isn't semiprime. (0.000 seconds) 4722366482869645213660 isn't semiprime. (0.000 seconds) 4722366482869645213661 isn't semiprime. (0.000 seconds) 4722366482869645213662 isn't semiprime. (0.000 seconds) 4722366482869645213663 is semiprime. (141.108 seconds) 4722366482869645213664 isn't semiprime. (0.000 seconds) 4722366482869645213665 isn't semiprime. (0.000 seconds) 4722366482869645213666 isn't semiprime. (0.000 seconds) 4722366482869645213667 isn't semiprime. (0.000 seconds) 4722366482869645213668 isn't semiprime. (0.000 seconds) 4722366482869645213669 isn't semiprime. (5.653 seconds) 4722366482869645213670 isn't semiprime. (0.000 seconds) 4722366482869645213671 isn't semiprime. (0.000 seconds) 4722366482869645213672 isn't semiprime. (0.000 seconds) Version 3 4722366482869645213645 isn't semiprime. (0.000 seconds) 4722366482869645213646 isn't semiprime. (0.000 seconds) 4722366482869645213647 isn't semiprime. (0.001 seconds) 4722366482869645213648 isn't semiprime. (0.000 seconds) 4722366482869645213649 isn't semiprime. (0.051 seconds) 4722366482869645213650 isn't semiprime. (0.000 seconds) 4722366482869645213651 is semiprime. (15.360 seconds) 4722366482869645213652 isn't semiprime. (0.000 seconds) 4722366482869645213653 isn't semiprime. (0.000 seconds) 4722366482869645213654 isn't semiprime. (0.000 seconds) 4722366482869645213655 isn't semiprime. (0.000 seconds) 4722366482869645213656 isn't semiprime. (0.000 seconds) 4722366482869645213657 isn't semiprime. (0.000 seconds) 4722366482869645213658 isn't semiprime. (0.000 seconds) 4722366482869645213659 isn't semiprime. (0.000 seconds) 4722366482869645213660 isn't semiprime. (0.000 seconds) 4722366482869645213661 isn't semiprime. (0.000 seconds) 4722366482869645213662 isn't semiprime. (0.000 seconds) 4722366482869645213663 is semiprime. (134.290 seconds) 4722366482869645213664 isn't semiprime. (0.000 seconds) 4722366482869645213665 isn't semiprime. (0.000 seconds) 4722366482869645213666 isn't semiprime. (0.000 seconds) 4722366482869645213667 isn't semiprime. (0.000 seconds) 4722366482869645213668 isn't semiprime. (0.000 seconds) 4722366482869645213669 isn't semiprime. (5.163 seconds) 4722366482869645213670 isn't semiprime. (0.000 seconds) 4722366482869645213671 isn't semiprime. (0.000 seconds) 4722366482869645213672 isn't semiprime. (0.000 seconds)
The versions 2-3 using a primality test perform better. So the idea is to incorporate a good test: Miller-Rabin (Miller–Rabin_primality_test#REXX).
Version 4
Libraries: How to use
Library: Numbers
Library: Functions
Library: Settings
Library: Abend
/*REXX program determines if any integer (or a range of integers) is/are semiprime. */
/*REXX program determines if any integer (or a range of integers) is/are semiprime. */
include Settings
say version; say 'Semi Primes'; say
parse arg bot top . /*obtain optional arguments from the CL*/
if bot=='' | bot=="," then bot=Random() /*None givenqq User wants us to guess.*/
if top=='' | top=="," then top=bot /*maybe define a range of numbers. */
tell= (top>0) /*should results be shown to the termqq */
w=Max(Length(bot), Length(top)) /*obtain the maximum width of numbers. */
numeric digits Max(9, w) /*ensure there're enough decimal digits*/
hh=0 /*initialize Number of semiprimes found*/
do n=Abs(bot) to Abs(top) /*show results for a range of numbers. */
qq=IsSemiPrime(n); hh=hh+qq /*Is N a semiprimeqq; Maybe bump counter*/
if tell then say Right(n,w) Right(Word("isn't" 'is', qq+1), 6) 'Semiprime.' '('Format(Time('e'),,3) 'seconds)'
call Time('r')
end /*n*/
say
if bot\==top then say 'found ' hh " semiprimes."
say Format(Time('e'),,3) ' seconds'
exit /*stick a fork in it, we're all done. */
IsSemiprime:
/* Is a number semi prime? function */
procedure expose glob.
arg x
/* Low semiprimes */
s = '4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95'
/* Fast values */
if x < 101 then do
if Wordpos(x,s) = 0 then
return 0
else
return 1
end
/* Wheeled scan */
do i = 2 for 2
if x//i = 0 then
if Prime(x%i) then
return 1
else
return 0
end
do i = 5 by 6 until i*i > x
do j = i by 2 for 2
if x//j==0 then
if Prime(x%j) then
return 1
else
return 0
end
end
return 0
include Functions
include Numbers
include Abend
Result:
REXX-Regina_3.9.6(MT) 5.00 29 Apr 2024 Semi primes 4722366482869645213645 isn't semiprime. (0.001 seconds) 4722366482869645213646 isn't semiprime. (0.000 seconds) 4722366482869645213647 isn't semiprime. (0.001 seconds) 4722366482869645213648 isn't semiprime. (0.000 seconds) 4722366482869645213649 isn't semiprime. (0.000 seconds) 4722366482869645213650 isn't semiprime. (0.000 seconds) 4722366482869645213651 is semiprime. (0.279 seconds) 4722366482869645213652 isn't semiprime. (0.000 seconds) 4722366482869645213653 isn't semiprime. (0.000 seconds) 4722366482869645213654 isn't semiprime. (0.001 seconds) 4722366482869645213655 isn't semiprime. (0.000 seconds) 4722366482869645213656 isn't semiprime. (0.000 seconds) 4722366482869645213657 isn't semiprime. (0.000 seconds) 4722366482869645213658 isn't semiprime. (0.001 seconds) 4722366482869645213659 isn't semiprime. (0.000 seconds) 4722366482869645213660 isn't semiprime. (0.000 seconds) 4722366482869645213661 isn't semiprime. (0.000 seconds) 4722366482869645213662 isn't semiprime. (0.000 seconds) 4722366482869645213663 is semiprime. (0.006 seconds) 4722366482869645213664 isn't semiprime. (0.000 seconds) 4722366482869645213665 isn't semiprime. (0.000 seconds) 4722366482869645213666 isn't semiprime. (0.001 seconds) 4722366482869645213667 isn't semiprime. (0.000 seconds) 4722366482869645213668 isn't semiprime. (0.000 seconds) 4722366482869645213669 isn't semiprime. (0.001 seconds) 4722366482869645213670 isn't semiprime. (0.000 seconds) 4722366482869645213671 isn't semiprime. (0.000 seconds) 4722366482869645213672 isn't semiprime. (0.000 seconds)
This is much, much faster! Trial division is mostly ok, but explodes sometimes. Miller-Rabin is more stable and suitable for bigger numbers. However, also Version 4 is not perfect: on number 4722366482869645213673 all versions fail.
Why? Because 4722 366482 869645 213673 = 33816 682061 × 139646 062093, two big prime factors. This is too much for REXX...
If the first factor is small and the second prime, than Version 4 is fast, i.e. 9 223372 036854 775797 = 3 × 3 074457 345618 258599. So you have to be lucky!
Ring
prime = 1679
decomp(prime)
func decomp nr
x = ""
sum = 0
for i = 1 to nr
if isPrime(i) and nr % i = 0
sum = sum + 1
x = x + string(i) + " * " ok
if i = nr and sum = 2
x2 = substr(x,1,(len(x)-2))
see string(nr) + " = " + x2 + "is semiprime" + nl
but i = nr and sum != 2 see string(nr) + " is not semiprime" + nl ok
next
func isPrime n
if n < 2 return false ok
if n < 4 return true ok
if n % 2 = 0 and n != 2 return false ok
for d = 3 to sqrt(n) step 2
if n % d = 0 return false ok
next
return true
RPL
PDIV
is defined at Prime decomposition
≪ PDIV SIZE 2 == ≫ 'SPR1?' STO ≪ { } 1 100 FOR n IF n SPR1? THEN n + END NEXT ≫ EVAL
- Output:
1: { 4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 }
Ruby
require 'prime'
# 75.prime_division # Returns the factorization.75 divides by 3 once and by 5 twice => [[3, 1], [5, 2]]
class Integer
def semi_prime?
prime_division.sum(&:last) == 2
end
end
p 1679.semi_prime? # true
p ( 1..100 ).select( &:semi_prime? )
# [4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55, 57, 58, 62, 65, 69, 74, 77, 82, 85, 86, 87, 91, 93, 94, 95]
Faster version using 'factor' function from [U|Li]nux Core Utilities library.
def semiprime(n)
`factor #{n}`.split.size == 3
end
n = 2**72 - 1 #4722366482869645213695
(n-50..n).each { |n| puts "#{n} -> #{semiprime(n)}" }
- Output:
4722366482869645213645 -> false 4722366482869645213646 -> false 4722366482869645213647 -> false 4722366482869645213648 -> false 4722366482869645213649 -> false 4722366482869645213650 -> false 4722366482869645213651 -> true 4722366482869645213652 -> false 4722366482869645213653 -> false 4722366482869645213654 -> false 4722366482869645213655 -> false 4722366482869645213656 -> false 4722366482869645213657 -> false 4722366482869645213658 -> false 4722366482869645213659 -> false 4722366482869645213660 -> false 4722366482869645213661 -> false 4722366482869645213662 -> false 4722366482869645213663 -> true 4722366482869645213664 -> false 4722366482869645213665 -> false 4722366482869645213666 -> false 4722366482869645213667 -> false 4722366482869645213668 -> false 4722366482869645213669 -> false 4722366482869645213670 -> false 4722366482869645213671 -> false 4722366482869645213672 -> false 4722366482869645213673 -> true 4722366482869645213674 -> false 4722366482869645213675 -> false 4722366482869645213676 -> false 4722366482869645213677 -> false 4722366482869645213678 -> false 4722366482869645213679 -> false 4722366482869645213680 -> false 4722366482869645213681 -> false 4722366482869645213682 -> false 4722366482869645213683 -> false 4722366482869645213684 -> false 4722366482869645213685 -> false 4722366482869645213686 -> false 4722366482869645213687 -> false 4722366482869645213688 -> false 4722366482869645213689 -> true 4722366482869645213690 -> false 4722366482869645213691 -> false 4722366482869645213692 -> false 4722366482869645213693 -> false 4722366482869645213694 -> false 4722366482869645213695 -> false
Rust
extern crate primal;
fn isqrt(n: usize) -> usize {
(n as f64).sqrt() as usize
}
fn is_semiprime(mut n: usize) -> bool {
let root = isqrt(n) + 1;
let primes1 = primal::Sieve::new(root);
let mut count = 0;
for i in primes1.primes_from(2).take_while(|&x| x < root) {
while n % i == 0 {
n /= i;
count += 1;
}
if n == 1 {
break;
}
}
if n != 1 {
count += 1;
}
count == 2
}
#[test]
fn test1() {
assert_eq!((2..10).filter(|&n| is_semiprime(n)).count(), 3);
}
#[test]
fn test2() {
assert_eq!((2..100).filter(|&n| is_semiprime(n)).count(), 34);
}
#[test]
fn test3() {
assert_eq!((2..1_000).filter(|&n| is_semiprime(n)).count(), 299);
}
#[test]
fn test4() {
assert_eq!((2..10_000).filter(|&n| is_semiprime(n)).count(), 2_625);
}
#[test]
fn test5() {
assert_eq!((2..100_000).filter(|&n| is_semiprime(n)).count(), 23_378);
}
#[test]
fn test6() {
assert_eq!((2..1_000_000).filter(|&n| is_semiprime(n)).count(), 210_035);
}
functional version of is_semiprime:
fn is_semiprime(n: usize) -> bool {
fn iter(x: usize, start: usize, count: usize) -> usize {
if count > 2 {return count} // break for semi_prime
let limit = (x as f64).sqrt().ceil() as usize;
match (start..=limit).skip_while(|i| x % i > 0).next() {
Some(v) => iter(x / v, v, count + 1),
None => if x < 2 { count }
else { count + 1 }
}
}
iter(n, 2, 0) == 2
}
- Output:
running 6 tests test test1 ... ok test test2 ... ok test test3 ... ok test test4 ... ok test test5 ... ok test test6 ... ok test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Scala
object Semiprime extends App {
def isSP(n: Int): Boolean = {
var nf: Int = 0
var l = n
for (i <- 2 to l/2) {
while (l % i == 0) {
if (nf == 2) return false
nf +=1
l /= i
}
}
nf == 2
}
(2 to 100) filter {isSP(_) == true} foreach {i => print("%d ".format(i))}
println
1675 to 1681 foreach {i => println(i+" -> "+isSP(i))}
}
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95 1675 -> false 1676 -> false 1677 -> false 1678 -> true 1679 -> true 1680 -> false 1681 -> true
Seed7
$ include "seed7_05.s7i";
const func boolean: semiPrime (in var integer: n) is func
result
var boolean: isSemiPrime is TRUE;
local
var integer: p is 2;
var integer: f is 0;
begin
while f < 2 and p**2 <= n do
while n rem p = 0 do
n := n div p;
incr(f);
end while;
incr(p);
end while;
isSemiPrime := f + ord(n > 1) = 2;
end func;
const proc: main is func
local
var integer: v is 0;
begin
for v range 1675 to 1680 do
writeln(v <& " -> " <& semiPrime(v));
end for;
end func;
- Output:
1675 -> FALSE 1676 -> FALSE 1677 -> FALSE 1678 -> TRUE 1679 -> TRUE 1680 -> FALSE
Sidef
Built-in:
say is_semiprime(2**128 + 1) #=> true
say is_semiprime(2**256 - 1) #=> false
User-defined function, with trial division up to a given bound B:
func is_semiprime(n, B=1e4) {
with (n.trial_factor(B)) { |f|
return false if (f.len > 2)
return f.all { .is_prime } if (f.len == 2)
}
n.factor.len == 2
}
say [2,4,99,100,1679,32768,1234567,9876543,900660121].grep(is_semiprime)
- Output:
[4, 1679, 1234567, 900660121]
Swift
import Foundation
func primes(n: Int) -> AnyGenerator<Int> {
var (seive, i) = ([Int](0..<n), 1)
let lim = Int(sqrt(Double(n)))
return anyGenerator {
while ++i < n {
if seive[i] != 0 {
if i <= lim {
for notPrime in stride(from: i*i, to: n, by: i) {
seive[notPrime] = 0
}
}
return i
}
}
return nil
}
}
func isSemiPrime(n: Int) -> Bool {
let g = primes(n)
while let first = g.next() {
if n % first == 0 {
if first * first == n {
return true
} else {
while let second = g.next() {
if first * second == n { return true }
}
}
}
}
return false
}
Tcl
package require math::numtheory
proc isSemiprime n {
if {!($n & 1)} {
return [::math::numtheory::isprime [expr {$n >> 1}]]
}
for {set i 3} {$i*$i < $n} {incr i 2} {
if {$n / $i * $i != $n && [::math::numtheory::isprime $i]} {
if {[::math::numtheory::isprime [expr {$n/$i}]]} {
return 1
}
}
}
return 0
}
for {set n 1675} {$n <= 1680} {incr n} {
puts -nonewline "$n is ... "
if {[isSemiprime $n]} {
puts "a semiprime"
} else {
puts "NOT a semiprime"
}
}
- Output:
1675 is ... a semiprime 1676 is ... NOT a semiprime 1677 is ... a semiprime 1678 is ... a semiprime 1679 is ... a semiprime 1680 is ... NOT a semiprime
TypeScript
// Semiprime
function primeFactorsCount(n: number): number {
n = Math.abs(n);
var count = 0; // Result
if (n >= 2)
for (factor = 2; factor <= n; factor++)
while n % factor == 0) {
count++;
n /= factor;
}
return count;
}
const readline = require('readline').createInterface({
input: process.stdin, output: process.stdout
});
readline.question('Enter an integer: ', sn => {
var n = parseInt(sn);
console.log(primeFactorsCount(n) == 2 ?
"It is a semiprime." : "It is not a semiprime.");
readline.close();
});
- Output:
Enter an integer: 33 It is a semiprime.
Enter an integer: 60 It is not a semiprime.
Wren
var semiprime = Fn.new { |n|
if (n < 3) return false
var nf = 0
for (i in 2..n) {
while (n%i == 0) {
if (nf == 2) return false
nf = nf + 1
n = (n/i).floor
}
}
return nf == 2
}
for (v in 1675..1680) {
System.print("%(v) -> %(semiprime.call(v) ? "is" : "is not") semi-prime")
}
- Output:
1675 -> isn't semi-prime 1676 -> isn't semi-prime 1677 -> isn't semi-prime 1678 -> is semi-prime 1679 -> is semi-prime 1680 -> isn't semi-prime
XPL0
func Semiprime(N); \Return 'true' if N is semiprime
int N, F, C;
[C:= 0; F:= 2;
repeat if rem(N/F) = 0 then
[C:= C+1;
N:= N/F;
]
else F:= F+1;
until F > N;
return C = 2;
];
int N;
[for N:= 1 to 100 do
if Semiprime(N) then
[IntOut(0, N); ChOut(0, ^ )];
]
- Output:
4 6 9 10 14 15 21 22 25 26 33 34 35 38 39 46 49 51 55 57 58 62 65 69 74 77 82 85 86 87 91 93 94 95
zkl
fcn semiprime(n){
reg f = 0;
p:=2; while(f < 2 and p*p <= n){
while(0 == n % p){ n /= p; f+=1; }
p+=1;
}
return(f + (n > 1) == 2);
}
- Output:
[1675 .. 1681].filter(semiprime).println(); L(1678,1679,1681)
- Programming Tasks
- Prime Numbers
- 11l
- 360 Assembly
- Action!
- Ada
- ALGOL 68
- ALGOL W
- Arturo
- AutoHotkey
- AWK
- BASIC
- ASIC
- BASIC256
- Chipmunk Basic
- FreeBASIC
- GW-BASIC
- Minimal BASIC
- Palo Alto Tiny BASIC
- PureBasic
- Run BASIC
- Tiny BASIC
- True BASIC
- Yabasic
- Bracmat
- C
- C sharp
- C++
- Clojure
- Common Lisp
- Crystal
- D
- DCL
- Delphi
- SysUtils,StdCtrls
- EasyLang
- EchoLisp
- Elixir
- Erlang
- ERRE
- Euler
- F Sharp
- Factor
- Forth
- Frink
- Go
- Haskell
- Data.Numbers.Primes
- Icon
- Unicon
- J
- Java
- Jq
- Julia
- Kotlin
- Ksh
- Lambdatalk
- Lingo
- Lua
- Maple
- Mathematica
- Wolfram Language
- Maxima
- MiniScript
- NewLisp
- Nim
- Objeck
- Oforth
- PARI/GP
- Pascal
- PrimTrial
- Perl
- Ntheory
- Phix
- PHP
- PicoLisp
- PL/0
- PL/I
- PL/M
- PowerShell
- Prolog
- PROMAL
- Python
- Quackery
- Racket
- Raku
- REXX
- Ring
- RPL
- Ruby
- Rust
- Scala
- Seed7
- Sidef
- Swift
- Tcl
- Tcllib
- TypeScript
- Wren
- XPL0
- Zkl