# Is it almost-prime?

Sandbox

Definition: A positive integer n is almost-prime, if it can be written in the form n=p^k where p is a prime and k is also a positive integers. In other words, the prime factorization of n contains only the same number.

Input: A positive integer 2<=n<=2^31-1

Output: a truthy value, if n is almost-prime, and a falsy value, if not.

Truthy Test Cases:

2
3
4
8
9
16
25
27
32
49
64
81
1331
2401
4913
6859
279841
531441
1173481
7890481
40353607
7528289


Falsy Test Cases

6
12
36
54
1938
5814
175560
9999999
17294403


Please do not use standard loopholes. This is so the shortest answer in bytes wins!

• To clarify: the truthy and falsy values need not be consistent, right? Commented Aug 26, 2020 at 0:42
• This is A000961 in the OEIS. Commented Aug 26, 2020 at 13:21
• The usual name for this kind of number is "prime power". Commented Aug 26, 2020 at 17:39
• It feels odd to me that you include prime numbers as being "almost prime," but this is still a good challenge! :) Commented Aug 26, 2020 at 18:26
• This should use the terminology "prime power". en.wikipedia.org/wiki/Almost_prime already has a definition.
– qwr
Commented Aug 28, 2020 at 5:27

# Sagemath, 2 bytes

GF


Outputs via exception.

Try it online!

The Sagemath builtin $$\\text{GF}\$$ creates a Galois Field of order $$\n\$$. However, remember that $$\\mathbb{F}_n\$$ is only a field if $$\n = p^k\$$ where $$\p\$$ is a prime and $$\k\$$ a positive integer. Thus the function throws an exception if and only if its input is not a prime power.

• Galois fields was the first thing I thought of, but I had no idea that Sagemath had a builtin for it. Commented Aug 26, 2020 at 14:30
• @DonThousand you should see what you can do with SM, it's support for Elliptic curve math/crypto is fantastic. Commented Aug 26, 2020 at 17:37

# Python 2, 42 bytes

f=lambda n,p=2:n%p and f(n,p+1)or p**n%n<1


Try it online!

Since Python doesn't have any built-ins for primes, we make do with checking divisibility.

We find the smallest prime p that's a factor of n by counting up p=2,3,4,... until n is divisible by p, that is n%p is zero. There, we check that this p is the only prime factor by checking that a high power of p is divisible by n. For this, p**n suffices.

As a program:

43 bytes

n=input()
p=2
while n%p:p+=1
print p**n%n<1


Try it online!

This could be shorter with exit codes if those are allowed.

46 bytes

lambda n:all(n%p for p in range(2,n)if p**n%n)


Try it online!

# Shakespeare Programming Language, 329 bytes

,.Ajax,.Page,.Act I:.Scene I:.[Enter Ajax and Page]
Ajax:Listen tothy.
Page:You cat.
Scene V:.
Page:You is the sum ofYou a cat.
Is the remainder of the quotient betweenI you nicer zero?If soLet usScene V.
Scene X:.
Page:You is the cube ofYou.Is you worse I?If soLet usScene X.
You is the remainder of the quotient betweenYou I.Open heart


Try it online!

Outputs 0 if the input is almost prime, and a positive integer otherwise. I am not sure this is an acceptable output; changing it would cost a few bytes.

Explanation:

• Scene I: Page takes in input (call this n). Initialize Ajax = 1.
• Scene V: Increment Ajax until Ajax is a divisor of Page; call the final value p This gives the smallest divisor of Page, which is guaranteed to be a prime.
• Scene X: Cube Ajax until you end up with a power of p, say p^k which is greater than n. Then n is almost-prime iff n divides p^k.
• You can save a byte by removing the space after "the remainder of", right? Commented Aug 29, 2020 at 1:56
• @HelloGoodbye No, that space is needed, as the name of the function is the_remainder_of_the_quotient_between. If you remove the space in the middle of the name, the function is not applied. Commented Aug 29, 2020 at 5:04
• Right, okay. I'd forgotten about that function Commented Aug 30, 2020 at 17:44

# MATL, 4 bytes

Yf&=

• For almost-primes the output is a matrix containing only 1s, which is truthy.
• Otherwise the output is a matrix containing several 1s and at least one 0, which is falsy.

Try it online! Or verify all test cases, including truthiness/falsihood test.

### How it works

     % Implicit input
Yf   % Prime factors. Gives a vector with the possibly repeated prime factors
&=   % Matrix of all pair-wise equality comparisons
% Implicit output


# Wolfram Language (Mathematica), 11 bytes

PrimePowerQ


Try it online!

@Sisyphus saved 1 byte

# 05AB1E, 2 bytes

ÒË


Try it online!

### Commented:

Ò   -- Are all the primes in the prime decomposition
Ë  -- Equal?

• A pure ASCII alternative: fg - since only 1 is truthy in 05AB1E.
– user96495
Commented Aug 26, 2020 at 2:02

# R, 3632 29 bytes

-3 bytes by outputting a vector of booleans without extracting the first element

!(a=2:(n=scan()))[!n%%a]^n%%n


Try it online!

Outputs a vector of booleans. In R, a vector of booleans is truthy iff the first element is TRUE.

First, find the smallest divisor p of n. We can do this by checking all integers (not only primes), as the smallest divisor of an integer (apart from 1) is always a prime number. Here, let a be all the integers between 2 and n, then p=a[!n%%a][1] is the first element of a which divides n.

Then n is almost prime iff n divides p^n.

This fails for any moderately large input, so here is the previous version which works for most larger inputs:

# R, 36 33 bytes

!log(n<-scan(),(a=2:n)[!n%%a])%%1


Try it online!

Compute the logarithm of n in base p: this is an integer iff n is almost prime.

This will fail due to floating point inaccuracy for certain (but far from all) large-ish inputs, in particular for one test case: $$\4913=17^3\$$.

• Brilliant and 25 bytes less than my own best attempt without peeking... The log trick is super! Commented Aug 26, 2020 at 8:05
• Although a nice approach, I'm afraid it fails for test case 4913 due to floating point inaccuracies (2.9999999999999996 is not an integer). I've just looked in the meta, and apparently you have to work around this if your language supports an accurate decimal type. I don't know R, so I don't know if this applies to it, but I was about to port your approach to Java to golf my about to post answer, but that apparently wouldn't be allowed unless I use java.math.BigDecimal instead of regular doubles.. :/ Commented Aug 26, 2020 at 8:48
• @KevinCruijssen I assumed this was OK, as it would work with a theoretical infinite-precision computer. I am probably not aware of the meta consensus you referred to, could you link to it? Commented Aug 26, 2020 at 9:06
• @RobinRyder Ah, I thought I added a link. Here it is. Commented Aug 26, 2020 at 9:09
• @DominicvanEssen While you were commenting, I made a similar change: I don't need …^(3*n) but simply …^n, which gains 4 bytes (but fails for any moderately large input). Commented Aug 26, 2020 at 9:58

# C (gcc), 43 bytes

f(n,i){for(i=1;n%++i;);n=i<n&&f(n/i)^i?:i;}


Try it online!

Returns p if n is almost-prime, and 1 otherwise.

f(n,i){
for(i=1;n%++i;);    // identify i = the least prime factor of n
n=i<n&&f(n/i)^i     // if n is neither prime nor almost-prime
?                 //  return 1
:i;               // return i
}


# APL (Dyalog Unicode), 7 bytes

⊢∊⍳∘.∧⍳


Try it online!

Uses ⎕IO←0. Returns 0 if the input is almost-prime, 1 otherwise.

### How it works

⊢∊⍳∘.∧⍳    ⍝ Input: integer n ≥ 2
⍳∘.∧⍳    ⍝ Generate a table of LCMs over 0..n-1
⊢∊         ⍝ Does the table contain n?


The LCM of two numbers is equivalent to taking the maximum of powers in their prime factorizations. If n = p^k, any numbers smaller than n cannot have p^k in their prime factorization, so the LCM table does not contain n. Otherwise, we can find a pair of coprime numbers under n that multiplies to n, so the LCM table is guaranteed to contain at least one copy of n.

• Can't you just check whether n divides LCM(1..n-1)?
– Neil
Commented Mar 4, 2021 at 12:21
• @Neil It isn't APL golf-friendly: 0=⊢|1∧/⍤↓⍳, 10 bytes. Commented Mar 4, 2021 at 13:20

# APL (Dyalog Classic), 3331 26 bytes

{⍵∊∊(((⊢~∘.×⍨)1↓⍳)⍵)∘*¨⍳⍵}


-5 bytes from Kevin Cruijssen's suggestion.

Warning: Very, very slow for larger numbers.

## Explanation

{⍵∊∊(((⊢~∘.×⍨)1↓⍳)⍵)∘*¨⍳⍵} ⍵=n in all the following steps
⍳⍵  range from 1 to n
∘*¨    distribute power operator across left and right args
(((⊢~∘.×⍨)1↓⍳)⍵)       list of primes till n
∊                       flatten the right arg(monadic ∊)
⍵∊                        is n present in the primes^(1..n)?


Try it online!

• I'm not entirely sure, but I think you can drop the *0.5 and just use a range or 1 to n? Commented Aug 26, 2020 at 7:46
• It is way too slow with that but yeah, sure. Commented Aug 26, 2020 at 7:52
• Well, codegolf is all about saving bytes, so compilation warnings, code standards, and performance are all irrelevant in code-golfing. Even if the performance would go from $O(1)$ to $O(n^n)$, if we can save even a single byte it's worth it, haha. ;) But if TIO would be to slow to run, you could leave the *0.5 in the TIO and mention it's only used to speed up the online code. (PS: The 0.5 could have been golfed to .5 if it was indeed required.) Commented Aug 26, 2020 at 7:55

# J, 9 8 bytes

1=#@=@q:


Try it online!

-1 byte thanks to xash

Tests if the self-classify = of the prime factors q: has length # equal to one 1=

## Setanta, 61 59 bytes

gniomh(n){p:=2nuair-a n%p p+=1nuair-a n>1 n/=p toradh n==1}


Try it here

Notes:

• The proper keyword is gníomh, but Setanta allows spelling it without the accents so I did so to shave off a byte.
• What an interesting language! Makes me want to go try to learn Irish again, and Setanta, for that matter! Commented Aug 26, 2020 at 16:51
• We usually count bytes in characters, since the size of a byte depends on the machine's hardware. Commented Mar 29, 2023 at 17:25
• í (with the acute) is 2 bytes in UTF-8 while i is only one.
– bb94
Commented Jul 18, 2023 at 1:57

# Pyth, 4 bytes

!t{P


Try it online!

Explanation:

P - List of prime factors
{ - Remove duplicate elements
t - Removes first element
! - Would return True if remaining list is empty, otherwise False


-1 byte, thanks to hakr14

• I have absolutely no idea what I'm doing, but does this work? Commented Aug 26, 2020 at 3:48
• @UnrelatedString that does, but I am not sure if im allowed to do that since it returns 0 (falsy value) for right cases and a truthy value for the others (which isn't fixed either). Commented Aug 26, 2020 at 3:51
• Well, in that case, !s.+PQ is still a byte shorter. Commented Aug 26, 2020 at 3:53
• Q can be omitted at the end, Pyth will fill missing variables with it (or the first lambda variable if inside a lambda) Commented Feb 28, 2021 at 6:57

# JavaScript (ES6), 43 bytes

## Without BigInts

Returns a Boolean value.

f=(n,k=1)=>n%1?!~~n:f(n<0?n/k:n%++k?n:-n,k)


Try it online!

A recursive function that first looks for the smallest divisor $$\k>1\$$ of $$\n\$$ and then divides $$\-n\$$ by $$\k\$$ until it's not an integer anymore. (The only reason why we invert the sign of $$\n\$$ when $$\k\$$ is found is to distinguish between the two steps of the algorithm.)

If $$\n\$$ is almost-prime, the final result is $$\-\dfrac{1}{k}>-1\$$. So we end up with $$\\lceil n\rceil=0\$$.

If $$\n\$$ is not almost-prime, there exists some $$\q>k\$$ coprime with $$\k\$$ such that $$\n=q\times k^{m}\$$. In that case, the final result is $$\-\dfrac{q}{k}<-1\$$. So we end up with $$\\lceil n\rceil<0\$$.

# JavaScript (ES11), 33 bytes

## With BigInts

With BigInts, using @xnor's approach is probably the shortest way to go.

Returns a Boolean value.

f=(n,k=1n)=>n%++k?f(n,k):k**n%n<1


Try it online!

# Regex (ECMAScript), 3533 32 bytes

-2 bytes thanks to H.PWiz; the explanation for why this worked was more complicated
-1 bytes by returning to the original algorithm (with its simple explanation), by actually constructing values of $$\a\$$ not divisible by $$\b\$$ (32 bytes) instead of asserting $$\a\$$ is not divisible by $$\b\$$ (35 bytes); this is slower, but not exponentially so

^(?!(((x+)x+)(?=\2+$)\2*\3)\1+$)


Try it online!

The 35 byte version was written in 2014 by teukon and me.

This works by asserting that there do not exist any $$\a\$$ and $$\b\$$, both proper divisors of $$\n\$$ where $$\a>b\$$, for which $$\a\$$ is not divisible by $$\b\$$.

This will always be true when $$\n\$$ is of the form $$\p^k\$$ (a prime power), because we will have $$\a=p^c\$$ and $$\b=p^d\$$ where $$\k > c > d \ge 0\$$, thus $$\a\$$ will always be divisible by $$\b\$$.

But if $$\n\$$ is not of the form $$\p^k\$$, there will always be at least one counterexample $$\a,b\$$ such that $$\a\$$ is not divisible by $$\b\$$. Trivially we can choose two different prime factors of $$\n\$$, and they will not be mutually divisible.

This algorithm is similar to that used by Original Original Original VI's answer.

# For the purpose of these comments, the input number will be referred to as N.
^(?!              # Assert that the following cannot match
(             # Capture \1 to be the following:
((x+)x+)  # Cycle through all values of \3 and \2 such that \2 > \3 > 1
(?=\2+$) # such that \2 is a proper divisor of N \2*\3 # Cycle through all values of \1 > \2 that aren't divisible # by \2, by letting \1 = \2 * A + \3 where A >= 0 ) \1+$          # where \1 is a proper divisor of N
)


Bonus: Here is a 28 (27🐌) byte regex that matches numbers of the form $$\p^k\$$ where $$\0 \le k \le 2\$$:
^(?!((x+)x+)(?!\1*\2+$)\1+$), exponential slowdown 🐌 version: ^(?!((x+)+)(?!\1*\2+$)\1+$)
((x+)+) is equivalent to (x+)x* but exponentially slower)

Try it online!

This is interesting because if I'd set out to implement that function intentionally, I would have come up with something like ^(?=(x?x+?)\1*$)((?=(x+)(\3+$))\4)?\1$ (38 bytes), which is 10 bytes longer. It was inspired by the algorithm used by Bubbler's APL answer. The full prime power version of that would be: ^(?!((x+)(?=\2+$)x+)(?!\1*\2+$)\1+$) - ECMAScript, 36 bytes
^(?!((x+)x+)\B(?>\1*?(?<=^\2+))$) - .NET, 33 bytes ^(?!((x+)+)\B(?>\1*?(?<=^\2+))$) - .NET, 32 bytes, 🐌 exponential slowdown

And user41805's APL answer ported to regex is:
^(?!(xx+)\1*(?=\1*$)x(xx+)\2*$(?<=^\2+)) - ECMAScript 2018, 40 bytes
^(?!(?*(xx+)\1*$)(xx+)\2*(?=\2*$)x\1*$) - ECMAScript + (?*), 39 bytes The algorithm used by 10+ of the other answers (that all the prime factors are the same / there is only one prime factor), ported to regex is: ^(?=(xx+?)\1*$)(?!(\1x+)(?<!^\3+(xx+))\2*$) - ECMAScript 2018, 43 bytes # Retina 0.8.2, 4139 38 bytes .+$*
^(?!(((1+)1+)(?=\2+$)\2*\3)\1+$)


Try it online!

• How about ^(?!((x+)(?=\2*$)x+)(?!\2*$)\1+$)? Commented Mar 4, 2021 at 21:55 • @H.PWiz Thanks! It's more complicated to explain, but that often seems to be the case with better golfs. I still have a backlog of ones to explain from both you and Grimmy! Commented Mar 5, 2021 at 1:54 # GAP 4.7, 31 bytes n->Length(Set(FactorsInt(n)))<2 This is a lambda. For example, the statement Filtered([2..81], n->Length(Set(FactorsInt(n)))<2 ); yields the list [ 2, 3, 4, 5, 7, 8, 9, 11, 13, 16, 17, 19, 23, 25, 27, 29, 31, 32, 37, 41, 43, 47, 49, 53, 59, 61, 64, 67, 71, 73, 79, 81 ]. Try it online! • Please link your answers to Try It Online or any other interpreter so they can be verified properly. Commented Aug 26, 2020 at 5:49 # Factor, 35 bytes : f ( n -- ? ) factors all-equal? ;  Try it online! • @petStorm Here it is :) Thanks! Commented Aug 26, 2020 at 11:13 • Save 13 bytes by ditching the named function. Try it online! Commented Mar 31, 2021 at 9:53 • @chunes Thanks! I didn't know it's allowed when I posted it. I have at least dozen more submission using this form. Commented Mar 31, 2021 at 10:09 # Haskell, 36 bytes f n=mod(until((<1).mod n)(+1)2^n)n<1  Try it online! 36 bytes f n=and[mod(gcd d n^n)n<2|d<-[1..n]]  Try it online! 39 bytes f n=all((elem[1,n]).gcd n.(^n))[2..n]  Try it online! 39 bytes f n=mod n(n-sum[1|1<-gcd n<$>[1..n]])<1


Try it online!

40 bytes

f n=and[mod(p^n)n<1|p<-[2..n],mod n p<1]


Try it online!

# Io, 48 bytes

method(i,c :=2;while(i%c>0,c=c+1);i log(c)%1==0)


Try it online!

## Explanation

method(i,            // Take an input
c := 2           // Set counter to 2
while(i%c>0,     // While the input doesn't divide counter:
c=c+1        //     Increment counter
)
i log(c)%1==0    // Is the decimal part of input log counter equal to 0?
)


# Assembly (MIPS, SPIM), 238 bytes, 6 * 23 = 138 assembled bytes

main:li$v0,5 syscall move$t3,$v0 li$a0,0
li$t2,2 w:bgt$t2,$t3,d div$t3,$t2 mfhi$t0
bnez$t0,e add$a0,$a0,1 s:div$t3,$t2 mfhi$t0
bnez$t0,e div$t3,$t3,$t2
b s
e:add$t2,$t2,1
b w
d:move$t0,$a0
li$a0,0 bne$t0,1,p
add$a0,$a0,1
p:li$v0,1 syscall  Try it online! • You can save bytes if you use$2 through $9, rather than named registers. Commented Sep 20, 2020 at 8:27 # Brachylog, 2 bytes Are all prime factors equal? ḋ=  Try it online! # APL (Dyalog Unicode) 17.0, 7 bytes ⍸2⌊/⊢∨⍳  Try it online! Uses a different approach from Bubbler's answer, but only works for Dyalog 17.X. Errors with a domain error on non-prime powers, and doesn't error on truthy inputs. The train is decomposed as the following ┌─┬─────────────────┐ │⍸│┌─┬─────┬───────┐│ │ ││ │┌─┬─┐│┌─┬─┬─┐││ │ ││2││⌊│/│││⊢│∨│⍳│││ │ ││ │└─┴─┘│└─┴─┴─┘││ │ │└─┴─────┴───────┘│ └─┴─────────────────┘  First a range from 1 to the right argument is created using ⍳.  (⍳) 10 1 2 3 4 5 6 7 8 9 10  Then each value in this list is GCDed ∨ with the right argument ⊢.  (⊢∨⍳) 10 1 2 1 2 5 2 1 2 1 10  Then the pairwise minimum is taken, with the pairs overlapping, so 2⌊/1 3 2 is equivalent to (1⌊3)(3⌊2).  (2⌊/⊢∨⍳) 10 1 1 1 2 2 1 1 1 1  Monadic ⍸ in Dyalog 17.0 is a function that finds the indices of truthy values given a binary array, but this function of it is irrelevant for this solution. If the input is not a prime power, it will have at least one number greater than 1 when the above is performed (proof below). Otherwise if it is a prime power, the above will result in a list with only 1s. So applying ⍸ on a non-prime power will cause the function to error because its argument is not a binary array, whereas on a prime power it won't error because the argument would binary consisting only of 1s. In Dyalog 18.0 ⍸ has been extended to also accept non-binary arrays, so the above won't work. Instead, using 'unique' ∪ in place of ⍸ will return the 1-length vector consisting only of 1 for truthy values, and a longer vector for falsey values. Bubbler gave the following proof as to why 2⌊/⊢∨⍳ does not give a vector of 1s for falsey values. Consider the Diophantine equation $$\p_1a-p_2b=1\$$, where $$\p_1\$$ and $$\p_2\$$ are distinct prime factors of a non-prime tower $$\N\$$ and $$\a,b>0\$$. This equation has solutions, a proof of which can be found in the following Wikipedia article. What this equation means is that you will have a situation where a multiple of $$\p_1\$$ occurs as the number immediately following a multiple of $$\p_2\$$. Since each prime factor divides the input $$\N\$$, their multiple, when GCDed with the input, will result in a value greater than 1. The fact that these multiples are less than $$\N\$$ is left as an exercise to the reader. So the two multiples of prime numbers following one another and that these multiples are less than $$\N\$$ mean that you have a situation where 2⌊/⊢∨⍳ will have a number greater than 1 in it. This situation does not occur for prime powers because given any two prime factors $$\p^m\$$ and $$\p^n\$$ where $$\n>m\$$, there will never be a situation where $$\p^na-p^mb=1\$$ because that would imply $$\p(p^{n-1}a-p^{m-1}b)=1\$$, i.e. that $$\p\$$ divides 1 which is false. # Java, 69 64 bytes n->{int f=0,t=1;for(;n%++t>0;);for(;n>1;n/=t)f|=n%t;return f<1;}  -5 bytes thanks to @Deadcode. Try it online. Explanation: n->{ // Method with integer parameter and boolean return-type int f=0, // Flag-integer f, starting at 0 t=1; // Temp integer t, starting at 1 for(;n%++t>0;);// Increase t by 1 before every iteration with ++t, // And continue looping until the input n is divisible by t for(;n>1; // Then start and continue a second loop as long as n is not 0 or 1: n/=t) // After every iteration: divide n by t f|= // Bitwise-OR the flag by: n%t; // n modulo-t return f<1;} // After both loops, return whether the flag is still 0  If we would be allowed to ignore floating point inaccuracies, a port of @RobinRyder's R answer would be 64 bytes as well: n->{int m=1;for(;n%++m>0;);return Math.log(n)/Math.log(m)%1==0;}  Try it online. Explanation: n->{ // Method with integer parameter and boolean return-type int m=1; // Minimum divisor integer m, starting at 1 for(;n%++m>0;); // Increase m by 1 before every iteration with ++m // And continue looping until the input n is divisible by m return Math.log(n)/Math.log(m) // Calculate log_m(n) %1==0;} // And return whether it has no decimal values after the comma  But unfortunately this approach fails for test case 4913 which would become 2.9999999999999996 instead of 3.0 due to floating point inaccuracies (it succeeds for all other test cases). A potential fix would be 71 bytes: n->{int m=1;for(;n%++m>0;);return(Math.log(n)/Math.log(m)+1e9)%1<1e-8;}  Try it online. # Retina 0.8.2, 50 43 bytes .+$*
^(?=(11+?)\1*$)((?=(1+)(\3+$))\4)*\1$ Try it online! Link includes faster test cases. Originally based on @Deadcode's answer to Match strings whose length is a fourth power, but saved 7 bytes thanks to @Deadcode by improving the basic algorithm. Explanation: .+$*


Convert the input to unary.

^(?=(11+?)\1*$)  Start by matching the smallest factor p of n. (p is necessarily prime, of course.) (?=(1+)(\3+$))


Find ns largest proper factor m, which is equivalent to n divided by its smallest prime factor q (which will be equal to p on the first pass).

\4


The factorisation also captures n-m, which is subtracted from the current value of n, effectively dividing n by q for the next pass of the loop.

(...)*\1$ Repeat this division by the smallest prime factor until n becomes p, which is only possible if n is a power of p. • -7 bytes while keeping the same algorithm. You only need to verify that \1 is still the smallest prime factor at the end, not at each iteration of the loop: Try it online! BTW, in contrast with my answer, this one intrinsically doesn't treat 1 as a prime power – which can actually be useful. Commented Mar 29, 2023 at 7:33 • @Deadcode Strictly speaking it doesn't check that p is the smallest prime factor at the end, since the loop would otherwise be capable of iterating again. – Neil Commented Mar 29, 2023 at 9:09 # MathGolf, 10 bytes ╒g¶mÉk╒#─╧  Port of @Razetime's APL (Dyalog Classic) answer, so make sure to upvote him as well! Try it online. Explanation: ╒ # Push a list in the range [1, (implicit) input-integer) g # Filter it by: ¶ # Check if it's a prime m # Map each prime to, É # using the following three operations: k╒ # Push a list in the range [1, input-integer) again # # Take the current prime to the power of each value in this list ─ # After the map, flatten the list of lists ╧ # And check if this list contains the (implicit) input-integer # (after which the entire stack joined together is output implicitly)  # Japt, 6 bytes I feel like this should be 1 or 2 bytes shorter ... k ä¶ ×  Try it - includes all test cases # Jelly, 3 bytes ÆfE  Try it online! # APL (Dyalog Unicode), 8 bytes ∨/1~⍨⊢∨⍳  Try it online! Outputs 1 if it isn't almost-prime, some other positive integer otherwise. ∨/1~⍨⊢∨⍳ ⊢∨⍳ ⍝ All divisors 1~⍨ ⍝ Remove 1 ∨/ ⍝ GCD  # Pyt, 4 bytes ϼŁ1=  Try it online! ϼ Implicit input; get unique ϼrime factors Ł Łength of array 1= equals 1?; implicit print  # Vyxal, 18 16 13 11 bytes Thanks to The Thonnu for -7 bytes ƛ?$Ḋ$æ∧;∑1=  Run it Explanation: ƛ ; # map over the input with this code: ? # get input$         # swap
Ḋ        # divisible?
\$       # swap
æ      # is the item prime?
∧     # logical and

∑   # sum
1= # is 1?

• Might help to use the register (£/¥) rather than named variables (←x) Commented Mar 29, 2023 at 16:52
• Also, the range and duplicates are implicit: Try it online or verify more test cases Commented Mar 29, 2023 at 17:37
• @TheThonnu How does Vyxal know that those operations are implicit? Commented Mar 29, 2023 at 17:49
• When you loop over a number, it implicitly casts to a range. Also, when there is nothing left on the stack, the loop variable is used of you're in a loop, and the input is used otherwise. Commented Mar 29, 2023 at 17:57
• Ok, enough golfing. Commented Mar 29, 2023 at 18:05