# 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? Aug 26 '20 at 0:42
• This is A000961 in the OEIS. Aug 26 '20 at 13:21
• The usual name for this kind of number is "prime power". Aug 26 '20 at 17:39
• It feels odd to me that you include prime numbers as being "almost prime," but this is still a good challenge! :) Aug 26 '20 at 18:26
• This should use the terminology "prime power". en.wikipedia.org/wiki/Almost_prime already has a definition.
– qwr
Aug 28 '20 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. Aug 26 '20 at 14:30
• @DonThousand you should see what you can do with SM, it's support for Elliptic curve math/crypto is fantastic. Aug 26 '20 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? Aug 29 '20 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. Aug 29 '20 at 5:04
• Right, okay. I'd forgotten about that function Aug 30 '20 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

# 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] 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! Aug 26 '20 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.. :/ Aug 26 '20 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? Aug 26 '20 at 9:06
• @RobinRyder Ah, I thought I added a link. Here it is. Aug 26 '20 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). Aug 26 '20 at 9:58

# 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
Aug 26 '20 at 2:02

# 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
Mar 4 at 12:21
• @Neil It isn't APL golf-friendly: 0=⊢|1∧/⍤↓⍳, 10 bytes. Mar 4 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? Aug 26 '20 at 7:46
• It is way too slow with that but yeah, sure. Aug 26 '20 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.) Aug 26 '20 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! Aug 26 '20 at 16:51

# 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? Aug 26 '20 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). Aug 26 '20 at 3:51
• Well, in that case, !s.+PQ is still a byte shorter. Aug 26 '20 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) Feb 28 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+$)? Mar 4 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! Mar 5 at 1:54 # Factor, 35 bytes : f ( n -- ? ) factors all-equal? ;  Try it online! • @petStorm Here it is :) Thanks! Aug 26 '20 at 11:13 • Save 13 bytes by ditching the named function. Try it online! Mar 31 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. Mar 31 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!

# Retina 0.8.2, 50 bytes

.+
$* ^(?=(11+?)\1*$)((?=\1+$)(?=(1+)(\3+)$)\4)+1$ Try it online! Link includes faster test cases. Based on @Deadcode's answer to Match strings whose length is a fourth power. Explanation: .+$*


Convert the input to unary.

^(?=(11+?)\1*$)  Start by matching the smallest factor $$\ p \$$ of $$\ n \$$. ($$\ p \$$ is necessarily prime, of course.) (?=\1+$)(?=(1+)(\3+)$)  While $$\ p | \frac n { p^i } \$$, find $$\ \frac n { p^i } \$$'s largest proper factor, which is necessarily $$\ \frac n { p^{i+1} } \$$. \4  The factorisation also captures $$\ (p - 1) \frac n { p^{i+1} } \$$, which is subtracted from $$\ \frac n { p^i } \$$, leaving $$\ \frac n { p^{i+1} } \$$ for the next pass through the loop. (...)+1$


Repeat the division by $$\ p \$$ as many times as possible, then check that $$\ \frac n { p^k } = 1 \$$.

# 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. Sep 20 '20 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;}


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.

# 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. Aug 26 '20 at 5:49

# 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


# Burlesque, 6 bytes

rifCsm


Try it online!

Explanation:

ri      # Read integer from input
fC    # Find its prime factorisation
sm  # Are all values the same?


# Zsh, 25 bytes

>factor
dir <->|grep \


Try it online!

Outputs via exit code - 1 is a prime power, 0 isn't.

• factor - factorise the input
• > - create a file named each word in that output (effectively uniquifies)
• <-> - match any file that is just a number (eliminates the file called input: which comes from the output of factor)
• dir - list those files separated by spaces (as opposed to ls which separates by newlines)
• |grep \  - search for a space in that output (which means there were at least 2 matching files and therefore more than 1 distinct factor)