共素数と数pi


23

前書き

数論は、予想外のつながりという形で驚異に満ちています。そのうちの1つです。

二つの整数は互いに素彼らは数を考えると1より一般的な他に何の要因を持っていない場合はN、1からのすべての整数を考えるN。このような整数をランダムに 2つ描画します(すべての整数は、各描画で同じ確率で選択されます。描画は独立しており、置換されます)。してみましょうpは選択された2つの整数が互いに素である確率を表します。次いで、pは 6 /傾向にあるπ 2 ≈0.6079 ...としてNが無限大になる傾向があります。

チャレンジ

このチャレンジの目的は、pNの関数として計算することです。

例として、N = 4を考えます。整数1,2,3,4から得られる16の可能なペアがあります。これらのペアの11は、互いに素、つまり(1,1)、(1,2)、(1,3)、(1,4)、(2,1)、(3,1)、(4,1 )、(2,3)、(3,2)、(3,4)、(4,3)。したがって、N = 4の場合、pは11/16 = 0.6875です。

p正確な値は、少なくとも4つの小数で計算する必要があります。これは、計算が決定論的でなければならないことを意味します(モンテカルロとは対照的に)。ただし、上記のようにすべてのペアを直接列挙する必要はありません。任意の方法を使用できます。

関数の引数またはstdin / stdoutを使用できます。出力を表示する場合、末尾のゼロは省略できます。したがって、たとえば0.6300として表示できます0.63。分数ではなく、10進数として表示する必要があります(文字列の表示は63/100許可されていません)。

勝利基準は最小バイトです。組み込み関数の使用に関する制限はありません。

テストケース

入力/出力(上記のように、小数点以下4桁のみが必須です):

1    / 1.000000000000000
2    / 0.750000000000000
4    / 0.687500000000000
10   / 0.630000000000000
100  / 0.608700000000000
1000 / 0.608383000000000

入力範囲に制限はありますか?
エリックタワーズ

@EricTowersプログラムは、メモリとデータ型の制限までの適切なサイズで動作するはずです。少なくとも1000
ルイスメンドー

(文字列ではなく)戻り値としての有理数は許可されていますか?私の言語にはネイティブの有理型63/100があります。これは有効なリテラルであり、計算に使用できます。(私が話している言語:因子ラケット

@catもちろん、どうぞ!ただし、必要な精度を考慮してください
ルイスメンドー

回答:


14

ゼリー12 8バイト

RÆṪSḤ’÷²

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

次のバイナリコードは、このバージョンのJellyインタープリターで機能します。

0000000: 52 91 b0 53 aa b7 9a 8a  R..S....

アイディア

明らかに、j≤k かつjk互いに素であるようなペア(j、k)の数は、同じ条件を満たすペア(k、j)の数に等しくなります。また、j = kの場合、j = 1 = kです。

したがって、間の座標と互いに素ペアの数をカウントする1及びN、それは量の計算すれば十分でM(J、Kに)ようJ≤K 、次いで計算1〜2メートルを

オイラーのφ関数のため、最後に、φ(k)がの間に数の整数を生成1K互いに素になっているkは、我々は計算することができますメートルとしてφ(1)+ ... +φ(n)を

コード

RÆṪSḤ’÷²    Input: n

R           Yield [1, ..., n].
 ÆṪ         Apply Euler's totient function to each k in [1, ..., n].
   S        Compute the sum of all results.
    Ḥ       Multiply the result by 2.
     ’      Subtract 1.
      ÷²    Divide the result by n².

2
ああ、Jellyにはtotient機能が含まれています!?良いアイデア!
ルイスメンドー

2
MATLまでのカウントダウンは... T-1日目のトーティエントコマンドが含まれて
quintopia

@quintopia(最終的にtotient関数を追加しました):
ルイスメンドー

14

Mathematica 43 42バイト

原点からラティスポイントが見えることがわかりました。そこから下の写真が撮影され、単位格子の所定の正方形領域に関する次の質問を通じて問題を再構成するのに役立ちます。

  • 単位格子点のどの部分が互いに素な座標を持っていますか?
  • 原点から単位格子点の何分の一を見ることができますか?

グリッド


N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&

末尾のゼロは省略されます。

N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&/@Range@10

{1.、0.75、0.777778、0.6875、0.76、0.638889、0.714286、0.671875、0.679012、0.63}


タイミング

タイミングは秒単位で、答えに先行します。

N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&[1000]// AbsoluteTiming

{0.605571、0.608383}



6

Mathematica、42 32バイト

Count[GCD~Array~{#,#},1,2]/#^2.&

無名関数、単純な総当たり攻撃を使用します。最後のケースは、私のマシンで約.37秒で実行されます。説明:

                               &   A function taking N and returning
Count[               , , ]           the number of
                      1               ones
                                     in the
                        2             second
                                     level of
         ~Array~                      a matrix of
      GCD                              the greatest common denominators of
                {#,#}                 all 2-tuples in [1..N]
                          /         divided by
                           #          N
                            ^2.      squared.

Mathematicaを持っていない人のために、サンプルの実行と説明を投稿できますか?
ルイスメンドー

2
これは私たちの提出物を結び付けます: Count[Array[GCD,{#, #}],1,2]/#^2.& 私のゲストになります。
DavidC

4

Dyalog APL、15バイト

(+/÷⍴)∘∊1=⍳∘.∨⍳

とても簡単です。モナド関数列です。Iotaは1から入力までの数値であるため、gcdによって外積を取得し、1の割合をカウントします。


3

オクターブ、49 47バイト

gcdすべてのペアの計算とカウントだけです。

@(n)mean(mean(gcd(c=kron(ones(n,1),1:n),c')<2))

クロネッカー製品は素晴らしいです。


kron!良いアイデア!
ルイスメンドー

最初に使用meshgridしましたが、kronインラインで同じことができることに気付きました!( - >匿名関数)
flawr

2

JavaScript(ES6)、88バイト

n=>eval(`p=0;for(i=n;i;i--)for(j=n;j;j--,p+=a)for(a=1,k=j;k>1;k--)a=i%k||j%k?a:0;p/n/n`)

説明

n=>
  eval(`                     // use eval to enable for loop without {} or return
    p=0;                     // p = number of pairs
    for(i=n;i;i--)           // i = 1 to n
      for(j=n;j;j--,p+=a)    // j = i to n, a will equal 1 if i and j are coprime, else 0
        for(a=1,k=j;k>1;k--) // for each number from 0 to j
          a=i%k||j%k?a:0;    // if i%k and j%k are both 0, this pair is not coprime
    p/n/n                    // return result (equivalent to p/(n*n))
  `)

テスト

>100値が大きい場合はしばらく時間がかかりますn


2

真剣に、15バイト

,;ª)u1x`▒`MΣτD/

六角ダンプ:

2c3ba62975317860b1604de4e7442f

オンラインで試す

デニスのゼリーソリューションとまったく同じアルゴリズムを文字通り使用しているので、私はそれを説明するつもりはありません(私はそれを独立して導出しましたが)。


2

J、19 17バイト

*:%~1-~5+/@p:|@i:

使用法:

   (*:%~1-~5+/@p:|@i:) 4
0.6875

説明:

*:%~1-~5+/@p:|@i:
               i: [-n..n]
             |@   absolute value of each element ([n..1,0,1,..n])
       5+/@p:     sum of the totient function for each element
    1-~           decreased by one, giving the number of co-prime pairs
*:%~              divided by N^2

Dennisのソリューションは、totient関数をどのように使用できるかを説明しています。

こちらからオンラインでお試しください。


2

Mathematica、35バイト

@Dennisのアルゴリズムを実装します。

(2`4Plus@@EulerPhi@Range[#]-1)/#^2&

1から入力値までの範囲でトーティエントの合計(オイラーのファイ関数)を計算します。浮動小数点2(4桁の精度)で乗算し、1を減算します。(代わりに「2」と「1`4」を使用すると、より高い精度を保持できます。)これは余素ペアの総数であるため、入力の2乗で除算して目的の分数を取得します。2つは概数なので、結果も同じです。

テスト行(f読みやすくするために少なくとも1人が興味深いと思うので、左側の列にタイミングデータがあります)とテスト関数が割り当てられています。

f=(2`4Plus@@EulerPhi@Range[#]-1)/#^2&
RepeatedTiming[f[#]] & /@ {1, 2, 4, 10, 100, 1000}
(* {{5.71*10^-6, 1.000}, 
    {5.98*10^-6, 0.750}, 
    {0.000010  , 0.6875}, 
    {0.0000235 , 0.6300}, 
    {0.00028   , 0.6087}, 
    {0.0033    , 0.6084} }  *)

編集:入力範囲の範囲を表示し(そうでない場合は結果が単調になるため、精度を2つではなく1つに入れ替える)、他の人に同じように挑戦する...

f = (2 Plus @@ EulerPhi@Range[#] - 1`4)/#^2 &
{#}~Join~RepeatedTiming[f[#]] & /@ {1, 2, 4, 10, 100, 1000, 10^4, 10^5, 10^6, 10^7}
(*  Results are {input, wall time, output}
    {{       1,  5.3*10^-6, 1.000}, 
     {       2,  6.0*10^-6, 0.7500}, 
     {       4,  0.0000102, 0.68750}, 
     {      10,  0.000023 , 0.63000}, 
     {     100,  0.00028  , 0.6087000}, 
     {    1000,  0.0035   , 0.608383000}, 
     {   10000,  0.040    , 0.60794971000}, 
     {  100000,  0.438    , 0.6079301507000}, 
     { 1000000,  4.811    , 0.607927104783000}, 
     {10000000, 64.0      , 0.60792712854483000}}  *)

RepeatedTiming[]計算を複数回実行し、平均時間を取り、コールドキャッシュやタイミングの異常値を引き起こすその他の影響を無視しようとします。漸近的な制限は

N[6/Pi^2,30]
(*  0.607927101854026628663276779258  *)

したがって、引数が10 ^ 4を超える場合、「0.6079」を返すだけで、指定された精度と精度の要件を満たすことができます。


2

ジュリア、95バイト

n->(c=combinations([1:n;1:n],2);((L=length)(collect(filter(x->gcd(x...)<2,c)))÷2+1)/L(∪(c)))

今のところは簡単なアプローチです。短い/よりエレガントなソリューションをすぐに検討します。これは、整数を受け入れ、floatを返す匿名関数です。呼び出すには、変数に割り当てます。

ゴルフをしていない:

function f(n::Integer)
    # Get all pairs of the integers from 1 to n
    c = combinations([1:n; 1:n], 2)

    # Get the coprime pairs
    p = filter(x -> gcd(x...) == 1, c)

    # Compute the probability
    return (length(collect(p)) ÷ 2 + 1) / length(unique(c))
end

私が知る限り、あなたはcollectその遅延を取るために怠need なオブジェクトを必要としませんlength

@cat lengthメソッドが定義されていない場所でこれを行います。これは、フィルター処理された組み合わせイテレーターの場合です。同様にendof、その型にはのメソッドがないため機能しませんgetindex
アレックスA.


@catはとrange同じ種類のオブジェクトを返しませんcombinations。後者は、定義されたlengthメソッドを持たない別個の型である組み合わせの反復子を返します。こちらをご覧ください。(また、範囲を構築:するrangeための構文よりも優先されます;))
アレックスA.

2

セージ、55バイト

lambda a:n((sum(map(euler_phi,range(1,a+1)))*2-1)/a**2)

すべてを象徴的に計算するSageのおかげで、マシンのイプシロンと浮動小数点の問題は発生しません。トレードオフは、出力形式の規則に従うために、追加の呼び出しn()(10進近似関数)が必要です。

オンラインで試す


非常に素晴らしい!最近セージを頻繁に使用しているようです:
ルイスメンドー

@LuisMendo Sageは素晴らしく、あらゆることを行います。Mathematicaのような巨大な組み込みライブラリがあるため、数学ベースのチャレンジで使用するのは非常に良いことですが、構文は(aにより)Mathematicaではなく、b)Pythonで構築されている方が優れています)。
メゴ

2

MATL20 17バイト

これは、現在のバージョン(5.0.0)の言語を使用します。

@flawrの答えに基づいたアプローチ。

i:tg!X*t!Zd1=Y)Ym

編集(2015年4月28日)オンラインで試してみてください!この回答が投稿された後、関数のY)名前がX:; に変更されました 。リンクにはその変更が含まれます。

>> matl i:tg!X*t!Zd1=Y)Ym
> 100
0.6087

説明

i:         % vector 1, 2, ... up to input number
tg!        % copy, convert into ones, transpose
X*         % Kronecker product. Produces a matrix
t!         % copy, transpose
Zd         % gcd of all pairs
1=         % is it equal to 1?
Y)         % linearize into column array
Ym         % compute mean

古い答え:20バイト

Oi:t"t@Zd1=sb+w]n2^/

説明

O             % produce literal 0. Initiallizes count of co-prime pairs.
i             % input number, say N
:             % create vector 1, 2, ... N
t             % duplicate of vector
"             % for loop
    t         % duplicate of vector
    @         % loop variable: each element from vector
    Zd        % gcd of vector and loop variable. Produces a vector
    1=s       % number of "1" in result. Each "1" indicates co-primality
    b+w       % accumulate into count of co-prime pairs
]             % end
n2^/          % divide by N^2

私がオクターブで使ったようなアプローチでもっと短くすることはできませんでしたか?
flawr

確かに!ありがとうございました!3バイト少ない。MATLで自分でやるべきだった:-)
ルイスメンドー

それが私の就寝時間を過ぎていなかったら=)
flawr

1

PARI / GP、25バイト

関数を匿名にすることでバイトを節約できますが、self全体的に高価になるように使用する必要があります。

f(n)=n^2-sum(j=2,n,f(n\j))

1

係数、120 113バイト

私はこれをクラスでゴルフに費やしましたが、短くすることはできません。

翻訳:ジュリア

[ [a,b] dup append 2 <combinations> [ members ] keep [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap /f ]

例は最初の5つのテストケースで実行されます(値が1000の場合、エディターがフリーズし、実行可能ファイルをすぐにコンパイルすることはできません)。

! with floating point division
IN: scratchpad auto-use {
      1    
      2    
      4    
      10   
      100  
    }
    [ 
      [1,b] dup append 2 <combinations> [ members ] keep 
      [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap /f 
    ]
    map

--- Data stack:
{ 1.0 0.75 0.6875 0.63 0.6087 }
! with rational division
IN: scratchpad auto-use {
      1    
      2    
      4    
      10   
      100  
    }
    [ 
      [1,b] dup append 2 <combinations> [ members ] keep 
      [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap / 
    ]
    map

--- Data stack:
{ 1.0 0.75 0.6875 0.63 0.6087 }
{ 1 3/4 11/16 63/100 6087/10000 }

たぶん実行例を追加しますか?
ルイスメンドー

1
@LuisMendo完了!

1

サマウ、12バイト

免責事項:質問の投稿後に言語を更新したため、競合していません。

▌;\φΣ2*($2^/

16進ダンプ(SamauはCP737エンコードを使用):

dd 3b 5c ad 91 32 2a 28 24 32 5e 2f

JellyのDennisの答えと同じアルゴリズムを使用します。


0

Python2 / Pypy、178バイト

xファイル:

N={1:set([1])}
n=0
c=1.0
e=input()
while n<e:
 n+=1
 for d in N[n]:
  m=n+d
  try:N[m].add(d)
  except:N[m]=set([d,m])
 for m in range(1,n):
  if N[m]&N[n]==N[1]:c+=2
print c/n/n

ランニング:

$ pypy x <<<1
1.0
$ pypy x <<<10
0.63
$ pypy x <<<100
0.6087
$ pypy x <<<1000
0.608383

コードは、互いに素なペアを(n,m) for m<n2回カウントします(c+=2)。これは(i,i) for i=1..nを除いて大丈夫で(1,1)、無視するため、カウンタを初期化することで修正されます11.0後でフロート除算の準備をするため)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.