Natural Pi # 0 - Рок

39

Цель

Создайте программу / функцию, которая принимает входные данные N, проверяет, являются ли Nслучайные пары целых чисел относительно простыми, и возвращает sqrt(6 * N / #coprime).

TL; DR

Эти проблемы представляют собой симуляции алгоритмов, которые требуют только природы и вашего мозга (и, возможно, некоторых ресурсов многократного использования) для приближения Pi. Если вам действительно нужен Пи во время апокалипсиса зомби, эти методы не тратят патроны ! Есть еще восемь задач. Оформить запись в песочнице, чтобы дать рекомендации.

моделирование

Что мы моделируем? Итак, вероятность того, что два случайных целых числа являются относительно простыми (т.е. взаимно простыми или gcd == 1), такова 6/Pi/Pi, поэтому естественным способом вычисления Pi будет выкопать два ведра (или горстки) камней; посчитай их; посмотрите, равен ли их gcd 1; повторение. После этого пару раз sqrt(6.0 * total / num_coprimes)будет стремиться к Pi. Если подсчет квадратного корня в постапокалиптическом мире заставляет вас нервничать, не волнуйтесь! Для этого есть метод Ньютона .

Как мы моделируем это?

  • Принять вход N
  • Делайте следующее Nвремя:
    • Равномерно генерировать случайные натуральные числа iиj
    • С 1 <= i , j <= 10^6
    • Если gcd(i , j) == 1:result = 1
    • Else: result = 0
  • Возьмите сумму Nрезультатов,S
  • Возвращение sqrt(6 * N / S)

введите описание изображения здесь

Спецификация

  • вход
    • Гибкость, принимать входные данные любым из стандартных способов (например, параметр функции, STDIN) и в любом стандартном формате (например, String, Binary)
  • Выход
    • Гибкость, вывод на печать любым из стандартных способов (например, возврат, печать)
    • Пробел, конечный и ведущий пробел приемлем
    • Точность, укажите не менее 4 знаков после запятой (т.е. 3.1416)
  • счет
    • Самый короткий код выигрывает!

Тестовые случаи

Ваш результат может не совпадать с этим из-за случайного шанса. Но в среднем вы должны получить примерно такую ​​точность для заданного значения N.

Input     ->  Output 
-----         ------
100       ->  3.????
10000     ->  3.1???
1000000   ->  3.14??
NonlinearFruit
источник
1
Должен ли наш ответ работать N = 1000000или это нормально, если программа возвращает, например, переполнение стека, если Nоно слишком велико?
Fatalize
@ Фатализировать, если это ограничение языка, конечно. В противном случае вам нужно справиться N=10^6.
Нелинейный
1
Связанные
Луис Мендо
2
Цель вводит в заблуждение, говорится, что проверяется только одна пара целых чисел.
user253751
1
Должен ли верхний предел генерируемых случайных чисел быть ровно 1000000? Был бы приемлем больший верхний предел?
Сок

Ответы:

12

APL, 23 байта

{.5*⍨6×⍵÷1+.=∨/?⍵2⍴1e6}

Объяснение:

  • ?⍵2⍴1e6: сгенерировать матрицу случайных чисел размером 2 на range в диапазоне [1..10 6 ]
  • 1+.=∨/: получить GCD каждой пары и посмотреть, сколько равно 1. Это вычисляет S.
  • .5*⍨6×⍵÷: (6 × ⍵ ÷ S) 0,5
Мэринус
источник
11

Желе , 20 18 16 байт

-2 байта благодаря @ Pietu1998 (цепочка и счет использования 1, ċ1вместо суммированных менее двух <2S)

-2 байта благодаря @Dennis (повторяйте 1e6 несколько раз перед выборкой, чтобы избежать цепочки)

Ḥȷ6xX€g2/ċ1÷³6÷½

(Чрезвычайно медленный из-за случайной функции)

Как?

Ḥȷ6xX€g2/ċ1÷³6÷½ - Main link: n
 ȷ6              - 1e6
   x             - repeat
Ḥ                -     double, 2n
    X€           - random integer in [1,1e6] for each
       2/        - pairwise reduce with
      g          -     gcd
         ċ1      - count 1s
           ÷     - divide
            ³    - first input, n
             6   - literal 6
              ÷  - divide
               ½ - square root

TryItOnline

Джонатан Аллан
источник
ḤRµȷ6Xµ€g2/ċ1÷³6÷½экономит 2 байта. ( ȷ610 ^ 6 в одной ниладе, ċ1считая единиц)
PurkkaKoodari
Ах, я не мог понять, как это сделать цепочкой (я попробовал несколько вещей), и забыл трюк со счетом 1 - спасибо (я думаю ȷ², это чуть-чуть быстрее ȷ6)
Джонатан Аллан
Возможно. Теперь, когда я думаю об этом, наличие ȷ²двух ссылок здесь не повредит, но потребует дополнительной ссылки или ¤для некоторых случаев использования
PurkkaKoodari
1
Ḥȷ6xX€должен работать для случайной выборки.
Деннис
9

Python 2, 143 140 132 124 122 124 122 байта

Прошло довольно много времени с тех пор, как я пробовал играть в гольф, поэтому я, возможно, что-то здесь упустил! Буду обновлять, как я сокращаю это.

import random as r,fractions as f
n,s=input(),0
k=lambda:r.randrange(1e6)+1
exec's+=f.gcd(k(),k())<2;'*n
print(6.*n/s)**.5

Проверь меня здесь!

спасибо Джонатану Аллану за двухбайтовое сохранение :)

Када
источник
Согласно ОП, 1 <= i , j <= 10^6так что вам нужно использовать randrange(1,1e6+1).
mbomb007
1
Кроме того, очень странно иметь ссылку repl.it в названии языка. Ссылка на имя языка должна быть на главной странице языка, если что-нибудь. Поместите вашу ссылку repl.it как отдельную ссылку под вашим кодом.
mbomb007
@ mbomb007 Хороший вопрос, я исправил это :) Давненько!
Каде
1
k=lambda:r.randrange(1e6)+1сохраняет два байта
Джонатан Аллан
1
@JonathanAllan хороший улов, спасибо!
Kade
8

Mathematica, 49 48 51 байт

Благодаря @ LegionMammal978 сохранен один байт и исправлена ​​одна ошибка .

(6#/Count[GCD@@{1,1*^6}~RandomInteger~{2,#},1])^.5&
alephalpha
источник
1
Вы можете сохранить байт:(6#/Count[GCD@@1*^6~RandomInteger~{2,#},1])^.5&
LegionMammal978
1
Кроме того, 1*^6должно быть заменено на, {1,1*^6}чтобы убедиться, что я , J ≠ 0.
LegionMammal978
8

R, 103 99 95 99 98 94 байта

Скорее всего, немного проиграл. Сократите 4 байта из-за @ antoine-sac и еще 4 байта, определив псевдоним для sample, используя ^.5вместо sqrtи 1e6вместо 10^6. Добавлены 4 байта для обеспечения того, чтобы выборка iи jбыла действительно равномерной. Убрал один байт после того, как понял, что 6*N/sum(x)это тоже самое 6/mean(x). Используется pryr::fвместо function(x,y)сохранения 4 байта.

N=scan()
s=sample
g=pryr::f(ifelse(o<-x%%y,g(y,o),y))
(6/mean(g(s(1e6,N,1),s(1e6,N,1))==1))^.5

Образец вывода:

N=100     -> 3.333333
N=10000   -> 3.137794
N=1000000 -> 3.141709
rturnbull
источник
1
Вы можете просто использовать sample(10^6,N). Он не только короче, но и гораздо эффективнее.
asac - Восстановить Монику
Возможно, я ошибаюсь, но не следует ли использовать образец с заменой = T для правильно однородных случайных целых чисел. Например sample(10,10)гарантированно вернет все числа в 1:10, тогда как sample(10,10,T)произведет случайный выбор, где числа могут повторяться.
MickyT
@ MickyT Вы абсолютно правы, я сам понял это несколько минут назад. Я не совсем уверен, как это математически разыгрывается в данном случае - насколько я могу судить, оба метода примерно одинаково точны. Я отредактирую свой пост, чтобы добавить эту информацию.
rturnbull
Оба метода одинаково точны при N << 10 ^ 6. Чтобы справиться с произвольно большим N, вы должны попробовать с заменой, хороший улов.
asac - Восстановить Монику
7

На самом деле, 19 байтов

`6╤;Ju@Ju┤`nkΣß6*/√

Попробуйте онлайн!

Объяснение:

`6╤;Ju@Ju┤`nkΣß6*/√
`6╤;Ju@Ju┤`n         do this N times:
 6╤;                   two copies of 10**6
    Ju                 random integer in [0, 10**6), increment
      @Ju              another random integer in [0, 10**6), increment
         ┤             1 if coprime else 0
            kΣ       sum the results
              ß      first input again
               6*    multiply by 6
                 /   divide by sum
                  √  square root
Мего
источник
i, j не могут быть 0
isaacg
1
@isaacg Это не так. Если вы прочитаете объяснение, оно говорит, что случайные значения выбираются из [0, 10 ** 6), а затем увеличиваются.
Mego
7

MATL , 22 байта

1e6Hi3$YrZ}Zd1=Ym6w/X^

Попробуйте онлайн!

1e6      % Push 1e6
H        % Push 2
i        % Push input, N
3$Yr     % 2×N matrix of uniformly random integer values between 1 and 1e6
Z}       % Split into its two rows. Gives two 1×N arrays
Zd       % GCD, element-wise. Gives a 1×N array
1=       % Compare each entry with 1. Sets 1 to 0, and other values to 0
Ym       % Mean of the array
6w/      % 6 divided by that
X^       % Square root. Implicitly display
Луис Мендо
источник
6

Pyth, 21 байт

@*6cQ/iMcmhO^T6yQ2lN2

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

объяснение

                Q          input number
               y           twice that
         m                 map numbers 0 to n-1:
             T                 10
            ^ 6                to the 6th power
           O                   random number from 0 to n-1
          h                    add one
        c        2         split into pairs
      iM                   gcd of each pair
     /            lN       count ones
   cQ                      divide input number by the result
 *6                        multiply by 6
@                   2      square root
PurkkaKoodari
источник
6

Scala, 149 126 байт

val& =BigInt
def f(n: Int)={math.sqrt(6f*n/Seq.fill(n){val i,j=(math.random*99999+1).toInt
if(&(i).gcd(&(j))>1)0 else 1}.sum)}

Объяснение:

val& =BigInt                //define & as an alias to the object BigInt, because it has a gcd method
def f(n:Int)={              //define a method
  math.sqrt(                //take the sqrt of...
    6f * n /                //6 * n (6f is a floating-point literal to prevent integer division)
    Seq.fill(n){            //Build a sequence with n elements, where each element is..
      val i,j=(math.random*99999+1).toInt //take 2 random integers
      if(&(i).gcd(&(j))>1)0 else 1        //put 0 or 1 in the list by calling
                                          //the apply method of & to convert the numbers to
                                          //BigInt and calling its bcd method
    }.sum                   //calculate the sum
  )
}
corvus_192
источник
Я <3 Скала! Тем более, что иногда это действительно нуждается в объяснении.
Роман Греф
@ RomanGräf Честно говоря, единственное, что я думаю, может быть неясно 6f, Seq.fillи math.random.
corvus_192
5

Ракетка 92 байта

(λ(N)(sqrt(/(* 6 N)(for/sum((c N))(if(= 1(gcd(random 1 1000000)(random 1 1000000)))1 0)))))

Ungolfed:

(define f
  (λ (N)
    (sqrt(/ (* 6 N) 
            (for/sum ((c N))
              (if (= 1
                     (gcd (random 1 1000000)
                          (random 1 1000000)))
                  1 0)
              )))))

Тестирование:

(f 100)
(f 1000)
(f 100000)

Выход:

2.970442628930023
3.188964020716403
3.144483068444827
rnso
источник
5

JavaScript (ES7), 107 95 94 байта

n=>(n*6/(r=_=>Math.random()*1e6+1|0,g=(a,b)=>b?g(b,a%b):a<2,q=n=>n&&g(r(),r())+q(n-1))(n))**.5

Версия ES6 составляет ровно 99 байтов, но оператор возведения в степень ES7 **экономит 5 байтов Math.sqrt.

Ungolfed

function pi(n) {
  function random() {
    return Math.floor(Math.random() * 1e6) + 1;
  }
  function gcd(a, b) {
    if (b == 0)
      return a;
    return gcd(b, a % b);
  }
  function q(n) {
    if (n == 0)
      return 0;
    return (gcd(random(), random()) == 1 ? 1 : 0) + q(n - 1));
  }
  return Math.sqrt(n * 6 / q(n));
}
ETHproductions
источник
В версии Ungolfed gcdвызывает функциюg
Роман Gräf
r=_=>это код или рисунок?
aross
n=>(n*6/(r=_=>Math.random()*1e6,g=(a,b)=>b?g(b,a%b):a>-2,q=n=>n&&g(~r(),~r())+q(n-1))(n))**.51B короче
l4m2
n=>(n*6/(q=_=>n--&&q(r=_=>Math.random()*1e6)+g(~r(),~r()))(g=(a,b)=>b?g(b,a%b):a>-2))**.5
l4m2
5

PHP, 82 77 74 байта

for(;$i++<$argn;)$s+=2>gmp_gcd(rand(1,1e6),rand(1,1e6));echo(6*$i/$s)**.5;

Запустите так:

echo 10000 | php -R 'for(;$i++<$argn;)$s+=2>gmp_gcd(rand(1,1e6),rand(1,1e6));echo(6*$i/$s)**.5;' 2>/dev/null;echo

объяснение

Делает то, что говорит на банке. Требуется PHP_GMP для gcd.

Tweaks

  • Сохранено 3 байта с помощью $argn
aross
источник
4

Perl, 64 байта

sub r{1+~~rand 9x6}$_=sqrt$_*6/grep{2>gcd r,r}1..$_

Требуется опция командной строки -pMntheory=gcd, считается как 13. Ввод взят из стандартного ввода.

Образец использования

$ echo 1000 | perl -pMntheory=gcd pi-rock.pl
3.14140431218772
Примо
источник
4

R, 94 байта

N=scan();a=replicate(N,{x=sample(1e6,2);q=1:x[1];max(q[!x[1]%%q&!x[2]%%q])<2});(6*N/sum(a))^.5

Относительно медленно, но все еще работает. Повторяем N раз функцию, которая берет 2 случайных числа (от 1 до 1e6) и проверяет, меньше ли их gcd, чем 2 (используя мою старую функцию gcd ).

plannapus
источник
1
Если вы не беспокоитесь о предупреждениях, 1:xсработает.
MickyT
4

PowerShell v2 +, 118 114 байт

param($n)for(;$k-le$n;$k++){$i,$j=0,1|%{Random -mi 1};while($j){$i,$j=$j,($i%$j)}$o+=!($i-1)}[math]::Sqrt(6*$n/$o)

Принимает ввод $n, запускает forцикл до тех пор, пока не $kстанет равным $n(неявно $k=0при первом входе в цикл). Каждую итерацию получают новые Randomчисла $iи $j( -miминимум1 флаг гарантирует, что мы >=1и флаг максимума не позволяет [int]::MaxValue, что разрешено OP, так как он больше, чем 10e6).

Затем мы идем в цикл GCDwhile . Тогда, пока GCD 1,$o увеличивается. В конце forцикла мы делаем простой [math]::Sqrt()вызов, который остается в конвейере и вывод неявен.

Занимает около 15 минут, чтобы работать со входом 10000на моем ~ 1-летнем ноутбуке Core i5.

Примеры

PS C:\Tools\Scripts\golfing> .\natural-pi-0-rock.ps1 100
3.11085508419128

PS C:\Tools\Scripts\golfing> .\natural-pi-0-rock.ps1 1000
3.17820863081864

PS C:\Tools\Scripts\golfing> .\natural-pi-0-rock.ps1 10000
3.16756133579975
AdmBorkBork
источник
3

Java 8, 164 151 байт

n->{int c=n,t=0,x,y;while(c-->0){x=1+(int)(Math.random()*10e6);y=1+(int)(Math.random()*10e6);while(y>0)y=x%(x=y);if(x<2)t++;}return Math.sqrt(6f*n/t);}

объяснение

n->{
    int c=n,t=0,x,y;
    while(c-->0){                          // Repeat n times
        x=1+(int)(Math.random()*10e6);     // Random x
        y=1+(int)(Math.random()*10e6);     // Random y
        while(y>0)y=x%(x=y);               // GCD
        if(x<2)t++;                        // Coprime?
    }
    return Math.sqrt(6f*n/t);              // Pi
}

Test Harness

class Main {
    public static interface F{ double f(int n); }
    public static void g(F s){
        System.out.println(s.f(100));
        System.out.println(s.f(1000));
        System.out.println(s.f(10000));
    }
    public static void main(String[] args) {
        g(
            n->{int c=n,t=0,y,x;while(c-->0){x=1+(int)(Math.random()*10e6);y=1+(int)(Math.random()*10e6);while(y>0)y=x%(x=y);if(x<2)t++;}return Math.sqrt(6f*n/t);}
        );
    }
}

Обновить

  • -13 [16-10-05] Благодаря @TNT и добавленному тестовому жгуту
NonlinearFruit
источник
1
Вам не нужны круглые скобки вокруг первой n, t+=1может стать t++, вы можете сжать свои intобъявления в одну строку, то есть int c=n,t=0,x,y;, и !=0(я думаю) может стать >0. Это должно сэкономить 12 байт в целом. Это отличный способ найти GCD для x и y.
TNT
1

Фринк, 84 89

r[]:=random[10^6]+1
g=n=eval[input[1]]
for a=1to n
g=g-1%gcd[r[],r[]]
println[(6*n/g)^.5]

Мне повезло: g = n = ... сохраняет байт за g = 0 n = ... ; и 1% gcd () дает (0,1) против (1,0), поэтому я могу вычесть. И не повезло: n предварительно назначено и используется, потому что переменные цикла и их границы являются локальными и неопределенными вне цикла.

Подробный

r[] := random[10^6] + 1     // function. Frink parses Unicode superscript!
g = n = eval[input[""]]     // input number, [1] works too
for a = 1 to n              // repeat n times
   g = g - 1%gcd[r[], r[]]  // subtract 1 if gcd(i, j) > 1
println[(6*n/g)^.5]         // ^.5 is shorter than sqrt[x], but no super ".", no ½
Может быть и так
источник
Это 90 байтов и 88 символов ...?
CalculatorFeline
Спасибо, что поймали это. Я не считал переводы строки, и пока «,« только 1 байт »- это больше. Я исправил это до 89 байтов без окончательного перевода строки.
Maybeso
Вы не исправили подробный код.
CalculatorFeline
В любом случае это не однозначное совпадение с пробелами, кавычками, цифрами и т. Д.
maybeso
1

AWK , 109 байт

func G(p,q){return(q?G(q,p%q):p)}{for(;i++<$0;)x+=G(int(1e6*rand()+1),int(1e6*rand()+1))==1;$0=sqrt(6*$0/x)}1

Попробуйте онлайн!

Я удивлен, что он работает в разумные сроки за 1000000.

Роберт Бенсон
источник
1

Пыть , 37 35 байт

←Đ0⇹`25*⁶⁺Đ1⇹ɾ⇹1⇹ɾǤ1=⇹3Ș+⇹⁻łŕ⇹6*⇹/√

Объяснение:

←Đ                                              Push input onto stack twice
  0                                             Push 0
   ⇹                                            Swap top two elements of stack
    `                      ł                    Repeat until top of stack is 0
     25*⁶⁺Đ1⇹ɾ⇹1⇹ɾ                              Randomly generate two integers in the range [1,10^6]
                  Ǥ1=                           Is their GCD 1?
                     ⇹3Ș                        Reposition top three elements of stack
                        +                       Add the top 2 on the stack
                         ⇹⁻                     Swap the top two and subtract one from the new top of the stack
                            ŕ                   Remove the counter from the stack
                             ⇹                  Swap the top two on the stack
                              6*                Multiply top by 6
                                ⇹               Swap top two
                                 /              Divide the second on the stack by the first
                                  √             Get the square root
mudkip201
источник
1

J, 27 байт

3 :'%:6*y%+/(1:=?+.?)y#1e6'

Объяснение:

3 :'                      '  | Explicit verb definition
                     y#1e6   | List of y copies of 1e6 = 1000000
            (1:=?+.?)        | for each item, generate i and j, and test whether their gcd is 1
          +/                 | Sum the resulting list
      6*y%                   | Divide y by it and multiply by six
    %:                       | Square root

Есть очень повезло с 3.14157для N = 10000000, который занял 2.44секунд.

Bolce Bussiere
источник