# 素数検定式

30

あなたの目標は、特定の数nが最小バイトで素数であるかどうかを判断することです。しかし、あなたのコードは、単一でなければならないのPython 2のみからなる数字で表現

• オペレーター
• 入力変数 n
• 整数定数
• 括弧

ループなし、割り当てなし、組み込み関数なし、上記のリストのみ。はい、可能です。

オペレーター

Python 2のすべての演算子のリストを次に示します。算術演算子、ビット演算子、論理演算子が含まれます。

+    adddition
-    minus or unary negation
*    multiplication
**   exponentiation, only with non-negative exponent
/    floor division
%    modulo
<<   bit shift left
>>   bit shift right
&    bitwise and
|    bitwise or
^    bitwise xor
~    bitwise not
<    less than
>    greater than
<=   less than or equals
>=   greater than or equals
==   equals
!=   does not equal


すべての中間値は整数です（または暗黙的に0と1に等しいFalse / True）。指数は負の指数では使用できません。これは浮動小数点数を生成する可能性があるためです。/Python 3とは異なり、フロア分割//は必要ないことに注意してください。

Pythonに精通していなくても、演算子はかなり直感的でなければなりません。参照演算子の優先順位については、この表、このセクションおよび以下の文法の詳細な仕様について。TIOでPython 2を実行できます

I / O

コードは式であるため、スニペットになり、入力値がとして格納されていることを期待し、n必要な出力を評価します。

あなたのコードはn、システムの制限を別にして、arbitrarily意的に機能する必要があります。Pythonの整数型は無制限なので、演算子に制限はありません。ただし、コードの実行には時間がかかる場合があります。

たぶんこれにはpythonタグが必要ですか？
fəˈnɛtɪk

35

# 43バイト

(4**n+1)**n%4**n**2/n&2**(2*n*n+n)/-~2**n<1

オンラインでお試しください！

この方法は、デニスの2番目の（削除された）答えに似ていますが、この答えは正しいと簡単に証明できます。

# 証明

### 長い形式

ましょうその基地持つ数であり表現を、すなわち、、および "に数字であります位置」をベース表現で。$\left[{a}_{n},\dots ,{a}_{1},{a}_{0}{\right]}_{b}$$[a_n,\dots,a_1,a_0]_b$$b$$b$${a}_{n}{b}^{n}+\cdots +{a}_{1}{b}^{1}+{a}_{0}{b}^{0}$$a_nb^n+\dots+a_1b^1+a_0b^0$${a}_{i}$$a_i$$i$$i$$b$$b$

• $\mathtt{\text{2**(2*n*n+n)/-~2**n}}=⌊\frac{{2}^{\left(2n+1\right)n}}{1+{2}^{n}}⌋=⌊\frac{{4}^{{n}^{2}}×{2}^{n}}{1+{2}^{n}}⌋=⌊\frac{\left({4}^{{n}^{2}}-1\right)×{2}^{n}}{1+{2}^{n}}+\frac{{2}^{n}}{1+{2}^{n}}⌋$$\texttt{2**(2*n*n+n)/-~2**n} =\lfloor{2^{(2n+1)n}\over1+2^n}\rfloor =\lfloor{4^{n^2}\times 2^n\over1+2^n}\rfloor =\lfloor{{(4^{n^2}-1)\times 2^n\over1+2^n} +{2^n\over1+2^n}}\rfloor$

なぜなら（とs）が整数であり、${2}^{n}×\frac{{4}^{{n}^{2}}-1}{1+{2}^{n}}={2}^{n}\left({2}^{n}-1\right)×\frac{\left({4}^{n}{\right)}^{n}-1}{{4}^{n}-1}=\left[{2}^{n}-1,0,{2}^{n}-1,0,{2}^{n}-1,0{\right]}_{{2}^{n}}$$2^n\times{4^{n^2}-1\over1+2^n} =2^n(2^n-1)\times{(4^n)^n-1\over4^n-1} =[2^n-1,0,2^n-1,0,2^n-1,0]_{2^n}$$n$$n$ ${2}^{n}-1$$2^n-1$、 =$⌊\frac{{2}^{n}}{1+{2}^{n}}⌋=0$$\lfloor{2^n\over1+2^n}\rfloor=0$2**(2*n*n+n)/-~2**n$\left[{2}^{n}-1,0,{2}^{n}-1,0,{2}^{n}-1,0{\right]}_{{2}^{n}}$$[2^n-1,0,2^n-1,0,2^n-1,0]_{2^n}$

$\begin{array}{rl}\mathtt{\text{(4**n+1)**n}}& =\left({4}^{n}+1{\right)}^{n}\\ & =\left(\genfrac{}{}{0}{}{n}{0}\right){4}^{0n}+\left(\genfrac{}{}{0}{}{n}{1}\right){4}^{1n}+\cdots +\left(\genfrac{}{}{0}{}{n}{n}\right){4}^{{n}^{2}}\\ & ={\left[\left(\genfrac{}{}{0}{}{n}{n}\right),0,\dots ,0,\left(\genfrac{}{}{0}{}{n}{1}\right),0,\left(\genfrac{}{}{0}{}{n}{0}\right)\right]}_{{2}^{n}}\end{array}$

なので、数値を最後の桁に切り捨てます-${4}^{{n}^{2}}=\left({2}^{n}{\right)}^{2n}$$4^{n^2}=(2^n)^{2n}$%4**n**2$2n$$2n$（1）ですが、他のすべての二項係数が含まれます。$\left(\genfrac{}{}{0}{}{n}{n}\right)$$\binom nn$

について/n

• If $n$$n$ is a prime, the result will be ${\left[\left(\genfrac{}{}{0}{}{n}{n-1}\right)/n,0,\dots ,0,\left(\genfrac{}{}{0}{}{n}{1}\right)/n,0,0\right]}_{{2}^{n}}$$\left[\binom n{n-1}/n,0,\dots,0,\binom n1/n,0,0\right]_{2^n}$. All digits at odd position are zero.

• If $n$$n$ is not a prime:

Let $a$$a$ be the largest integer such that $n\nmid \left(\genfrac{}{}{0}{}{n}{a}\right)$$n\nmid\binom na$ ($n>a>0$$n>a>0$). Rewrite the dividend as

${\left[\left(\genfrac{}{}{0}{}{n}{n-1}\right),0,\left(\genfrac{}{}{0}{}{n}{n-2}\right),0,\dots ,\left(\genfrac{}{}{0}{}{n}{a+1}\right),0,0,0,\dots ,0,0,0\right]}_{{2}^{n}}+{\left[\left(\genfrac{}{}{0}{}{n}{a}\right),0,\left(\genfrac{}{}{0}{}{n}{a-1}\right),0,\dots ,\left(\genfrac{}{}{0}{}{n}{0}\right)\right]}_{{2}^{n}}$$\left[\binom n{n-1},0,\binom n{n-2},0,\dots,\binom n{a+1}, 0,0,0,\dots,0,0,0\right]_{2^n} + \left[\binom na,0,\binom n{a-1},0,\dots,\binom n0\right]_{2^n}$

The first summand has all digits divisible by $n$$n$, and the digit at position $2a-1$$2a-1$ zero.

The second summand has its most significant digit (at position $2a$$2a$) not divisible by $n$$n$ and (the base) ${2}^{n}>n$$2^n>n$, so the quotient when dividing that by $n$$n$ would have the digit at position $2a-1$$2a-1$ nonzero.

Therefore, the final result ((4**n+1)**n%4**n**2/n) should have the digit (base ${2}^{n}$$2^n$, of course) at position $2a+1$$2a+1$ nonzero.

Finally, the bitwise AND (&) performs a vectorized bitwise AND on the digits in base ${2}^{n}$$2^n$ (because the base is a power of 2), and because $a\mathtt{\text{&}}0=0,a\mathtt{\text{&}}\left({2}^{n}-1\right)=a$$a\texttt &0=0,a\texttt&(2^n-1)=a$ for all $0\le a<{2}^{n}$$0\le a<2^n$, (4**n+1)**n%4**n**2/n&2**(2*n*n+n)/-~2**n is zero iff (4**n+1)**n%4**n**2/n has all digits in first $n$$n$ odd positions zero - which is equivalent to $n$$n$ being prime.

2
Would (4**n+1)**n%2**n**2/n&2**n**2/-~2**n<1 work?
Dennis

11
If it's easy to prove correct, could you include the proof in the answer? We have MathJax now, so it's relatively easy to make proofs legible, and I can't see an obvious reason for the division by n not to cause unwanted interactions between the digits base 4**n.
Peter Taylor

3
"I have discovered a truly remarkable proof of this answer which this comment is too small to contain..."
Digital Trauma

1
Suggestions for shortening the proof are welcome.
user202729

1
Nicely done! This is the same solution I had come up with. I found a couple of bytes can be cut with (4**n+1)**n%4**n**2/n<<n&4**n**2/-~2**n<1. I'm curious if this challenge is possible without bitwise operators.
xnor

6

# Python 2, 56 bytes

n**(n*n-n)/(((2**n**n+1)**n**n>>n**n*~-n)%2**n**n)%n>n-2

Try it online!

This is a proof-of-concept that this challenge is doable with only arithmetic operators, in particular without bitwise |, &, or ^. The code uses bitwise and comparison operators only for golfing, and they can easily be replaced with arithmetic equivalents.

However, the solution is extremely slow, and I haven't been able to run $n=6$$n=6$, thanks to two-level exponents like ${2}^{{n}^{n}}$$2^{n^n}$.

The main idea is to make an expression for the factorial $n!$$n!$, which lets us do a Wilson's Theorem primality test $\left(n-1\right)!\mathrm{%}n>n-2$$(n-1)! \mathbin{\%} n > n-2$ where $\mathrm{%}$$\mathbin{\%}$ is the modulo operator.

We can make an expression for the binomial coefficient, which is made of factorials

But it's not clear how to extract just one of these factorials. The trick is to hammer apart $n!$$n!$ by making $m$$m$ really huge.

So, if we let $c$$c$ be the product $\left(1-\frac{1}{m}\right)\left(1-\frac{2}{m}\right)\cdots \left(1-\frac{n-1}{m}\right)$$\left(1-\frac{1}{m}\right)\left(1-\frac{2}{m}\right)\cdots \left(1-\frac{n-1}{m}\right)$, we have

$n!=\frac{{m}^{n}}{\left(\genfrac{}{}{0}{}{m}{n}\right)}\cdot c$

If we could just ignore $c$$c$, we'd be done. The rest of this post is looking how large we need to make $m$$m$ to be able to do this.

Note that $c$$c$ approaches $1$$1$ from below as $m\to \mathrm{\infty }$$m \to \infty$. We just need to make $m$$m$ huge enough that omitting $c$$c$ gives us a value with integer part $n!$$n!$ so that we may compute

$n!=⌊\frac{{m}^{n}}{\left(\genfrac{}{}{0}{}{m}{n}\right)}⌋$

For this, it suffices to have $1-c<1/n!$$1 - c < 1/n!$ to avoid the ratio passing the next integer $n!+1$$n!+1$.

Observe that $c$$c$ is a product of $n$$n$ terms of which the smallest is $\left(1-\frac{n-1}{m}\right)$$\left(1-\frac{n-1}{m}\right)$. So, we have

$c>{\left(1-\frac{n-1}{m}\right)}^{n}>1-\frac{n-1}{m}n>1-\frac{{n}^{2}}{m},$

which means $1-c<\frac{{n}^{2}}{m}$$1 - c < \frac{n^2}{m}$. Since we're looking to have $1-c<1/n!$$1 - c < 1/n!$, it suffices to take $m\ge n!\cdot {n}^{2}$$m \geq n! \cdot n^2$.

In the code, we use $m={n}^{n}$$m=n^n$. Since Wilson's Theorem uses $\left(n-1\right)!$$(n-1)!$, we actually only need $m\ge \left(n-1\right)!\cdot \left(n-1{\right)}^{2}$$m \geq (n-1)! \cdot (n-1)^2$. It's easy to see that $m={n}^{n}$$m=n^n$ satisfies the bound for the small values and quickly outgrows the right hand side asymptotically, say with Stirling's approximation.

3

This answer doesn't use any number-theoretic cleverness. It spams Python's bitwise operators to create a manual "for loop", checking all pairs $1\le i,j$1 \leq i,j < n$ to see whether $i×j=n$$i \times j = n$.

# Python 2, way too many bytes (278 thanks to Jo King in the comments!)

((((((2**(n*n)/(2**n-1)**2)*(2**((n**2)*n)/(2**(n**2)-1)**2))^((n*((2**(n*n-n)/(2**n-1))*(2**((n**2)*(n-1))/(2**n**2-1))))))-((2**(n*n-n)/(2**n-1))*(2**((n**2)*(n-1))/(2**(n**2)-1))))&(((2**(n*(n-1))/(2**n-1))*(2**((n**2)*(n-1))/(2**(n**2)-1)))*(2**(n-1)))==0))|((1<n<6)&(n!=4))

Try it online!

This is a lot more bytes than the other answers, so I'm leaving it ungolfed for now. The code snippet below contains functions and variable assignment for clarity, but substitution turns isPrime(n) into a single Python expression.

def count(k, spacing):
return 2**(spacing*(k+1))/(2**spacing - 1)**2
def ones(k, spacing):
return 2**(spacing*k)/(2**spacing - 1)

def isPrime(n):
x = count(n-1, n)
y = count(n-1, n**2)
onebits = ones(n-1, n) * ones(n-1, n**2)
comparison = n*onebits
difference = (x*y) ^ (comparison)
differenceMinusOne = difference - onebits
checkbits = onebits*(2**(n-1))
return (differenceMinusOne & checkbits == 0 and n>1)or 1<n<6 and n!=4`

# Why does it work?

I'll do the same algorithm here in base 10 instead of binary. Look at this neat fraction:

$\frac{1.0}{{999}^{2}}=1.002003004005\dots$

If we put a large power of 10 in the numerator and use Python's floor division, this gives an enumeration of numbers. For example, ${10}^{15}/\left({999}^{2}\right)=1002003004$$10^{15}/(999^2) = 1002003004$ with floor division, enumerating the numbers $1,2,3,4$$1,2,3,4$.

Let's say we multiply two numbers like this, with different spacings of zeroes. I'll place commas suggestively in the product.

$1002003004×1000000000002000000000003000000000004=$
$1002003004,002004006008,003006009012,004008012016$

The product enumerates, in three-digit sequences, the multiplication table up to 4 times 4. If we want to check whether the number 5 is prime, we just have to check whether $005$$005$ appears anywhere in that product.

To do that, we XOR the above product by the number $005005005\dots 005$$005005005\dots005$, and then subtract the number $001001001\dots 001$$001001001\dots001$. Call the result $d$$d$. If $005$$005$ appeared in the multiplication table enumeration, it will cause the subtraction to carry over and put $999$$999$ in the corresponding place in $d$$d$.

To test for this overflow, we compute an AND of $d$$d$ and the number $900900900\dots 900$$900900900\dots900$. The result is zero if and only if 5 is prime.

1
A quick print of the expression puts this at 278 bytes (though I'm sure a lot of the parenthesises aren't necessary)
Jo King

Licensed under cc by-sa 3.0 with attribution required.