Первинність і число пі


23

Вступ

Теорія чисел сповнена чудес, у вигляді несподіваних зв’язків. Ось один із них.

Два цілих числа є со-прем'єром , якщо вони не мають загальні моменти, крім 1. Дан число N , розглянуть всі цілі числа від 1 до N . Намалюйте два таких цілих числа навмання (усі цілі числа мають однакову ймовірність бути вибраними при кожному розіграші; малюнки є незалежними та із заміною). Нехай p позначає ймовірність того, що два вибраних цілих числа є співпростими. Тоді p має тенденцію до 6 / π 2 ≈ 0.6079 ... як N прагне до нескінченності.

Змагання

Мета цього завдання полягає в обчисленні р як функція від N .

Як приклад, розглянемо N = 4. Є 16 можливих пар, отриманих з цілих чисел 1,2,3,4. 11 з цих пар є спільними простими, а саме (1,1), (1,2), (1,3), (1,4), (2,1), (3,1), (4,1 ), (2,3), (3,2), (3,4), (4,3). Таким чином, p дорівнює 11/16 = 0,6875 для N = 4.

Точне значення р повинно бути обчислено щонайменше , чотирьох знаків після коми. Це означає, що обчислення повинні бути детермінованими (на відміну від Монте-Карло). Але це не повинно бути прямим перерахуванням всіх пар, як зазначено вище; будь-який метод може бути використаний.

Можуть використовуватися аргументи функції або stdin / stdout. Якщо відображається вихід, кінцеві нулі можуть бути опущені. Так, наприклад, 0.6300може відображатися як 0.63. Він повинен відображатися у вигляді десяткового числа, а не у вигляді дробу (відображення рядка 63/100заборонено).

Критерій виграшу - найменше байтів. Немає обмежень щодо використання вбудованих функцій.

Тестові справи

Введення / вихід (лише чотири десяткові дроби є обов'язковими, як зазначено вище):

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) таких, що j ≤ k і j і k є співпросте, дорівнює кількості пар (k, j), які відповідають однаковим умовам. Також, якщо j = k , j = 1 = k .

Таким чином, для підрахунку кількості парних простих пар з координатами між 1 і n достатньо обчислити величину m пар (j, k) таку, що j ≤ k , а потім обчислити 2m - 1 .

Нарешті, оскільки тотієнтська функція Ейлера φ (k) дає цілі числа між 1 і k, які є простими для k , ми можемо обчислити m як φ (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
О, Джеллі включає в себе функцію тотієнта! Хороша ідея!
Луїс Мендо

2
Зворотний відлік часу, поки MATL не включає команду totient в день T-1 ...
квінтопія

@quintopia (я, нарешті, включив функцію тотієнта) :-D
Луїс Мендо

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

Математика, 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

Діалог APL, 15 байт

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

Досить прямо. Це поїзд монадичної функції. Iota - це числа від 1 до введення, тому ми беремо зовнішній продукт за gcd, а потім підраховуємо частку одиниць.


3

Октава, 49 47 байт

Просто обчислення gcdвсіх пар і підрахунок.

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

Продукт kronecker є приголомшливим.


kron! Гарна ідея!
Луїс Мендо

Я спочатку використовував meshgrid, але потім помітив, що можу зробити те ж саме з kronвбудованим встроєм! (-> анонімна функція)
недолік

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

Спробуйте це в Інтернеті

Я не збираюся заважати пояснювати це, оскільки він буквально використовує абсолютно той самий алгоритм, що і рішення Jelnis Jelly (хоча я отримав його самостійно).


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

Рішення Денніса дає приємне пояснення, як ми можемо використовувати функцію тотієнта.

Спробуйте його онлайн тут.


2

Математика, 35 байт

Реалізує алгоритм @ Денніса.

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

Обчисліть суму коефіцієнта (функція філе Ейлера) в межах від 1 до вхідного значення. Помножте на плаваючу крапку другу (з чотирма цифрами точності) і відніміть одну. (Більше точності можна зберегти, використовуючи замість них " 2" і " 1`4".) Це загальна кількість пар копріме, тому поділіть на квадрат введення, щоб отримати потрібний дріб. Тому що два - приблизне число, такий і результат.

Тестування (із тимчасовими даними в лівій колонці, оскільки принаймні один з нас вважає це цікавим), з функцією, призначеною для fтого, щоб тестовий рядок був легше прочитати:

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} }  *)

Редагувати: Показує масштаб діапазону входів (замінюючи точність на той, а не на два, оскільки в іншому випадку результати стають досить одноманітними) і закликають інших робити те ж саме ...

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)))

Просто прямолінійний підхід на даний момент; Незабаром я розгляну коротші / елегантніші рішення. Це анонімна функція, яка приймає ціле число і повертає поплавок. Щоб викликати його, призначте його змінній.

Безголівки:

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лінивий предмет, щоб взяти його length.
кіт

@cat У деяких випадках, де lengthне визначений метод, це стосується ітератора відфільтрованих комбінацій. Так само endofне буде працювати, оскільки немає методу для цього типу getindex.
Алекс А.


@cat rangeне повертає такий самий об’єкт, як combinations. Останній повертає ітератор над комбінаціями, який є окремим типом без визначеного lengthметоду. Дивіться тут . (Також :синтаксис віддається перевазі rangeдля побудови діапазонів;))
Алекс А.

2

Шавлія, 55 байт

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

Завдяки Sage обчислюючи все символічно, епсилон машини та проблеми з плаваючою комою не виникають. Компроміс - для того, щоб слідувати правилу вихідного формату, потрібен додатковий виклик n()(функція десяткового наближення).

Спробуйте в Інтернеті


Дуже хороша! Ви, здається, використовуєте Sage останнім часом досить часто :-)
Луїс Мендо

@LuisMendo Sage чудовий і робить все. Це дуже приємно використовувати для вирішення завдань, заснованих на математиці, оскільки він має величезну вбудовану бібліотеку на зразок Mathematica, але синтаксис краще (в силу а) не бути Mathematica, а б) будуватися на Python).
Мего,

2

MATL , 20 17 байт

Для цього використовується поточна версія (5.0.0) мови.

Підхід на основі відповіді @ flawr .

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

Редагувати (28 квітня 2015 р.) : Спробуйте в Інтернеті! Після розміщення цієї відповіді функцію 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

Не могли б ви бути ще коротшими з таким підходом, як той, який я використовував в октаві?
недолік

Справді! Дякую! На 3 байти менше. Ви повинні були зробити це самостійно в MATL :-)
Луїс Мендо

Я б спробував, якби це не минуло мого сну =)
недолік

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^/

Шестнадцятковий дамп (Samau використовує кодування CP737):

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

Використовуючи той самий алгоритм, що і відповідь Денніса в Jelly.


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<nдвічі ( c+=2). Це ігнорує, (i,i) for i=1..nщо нормально, за винятком (1,1), таким чином, виправляється ініціалізацією лічильника 1( 1.0щоб пізніше підготуватися до поділу поплавця) для компенсації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.