Монте-Карло, оцінювач Pi


25

З Днем Пі усіх! Без всяких причин я намагаюся побудувати оцінку Монте-Карло Pi, яка є якомога коротшою. Чи можемо ми побудувати той, який може вміститись у твіт?

Для уточнення, що я маю на увазі, - це типовий підхід малювання випадкових точок з одиничного квадрата та обчислення відношення, що потрапляє в одиничне коло. Кількість зразків може бути жорстко закодованою чи ні. Якщо ви жорстко кодуєте їх, ви повинні використовувати щонайменше 1000 зразків. Результат може бути повернутий або надрукований у вигляді плаваючої точки, фіксованої точки або раціонального числа.

Ніякі триггерні функції чи константи Пі не повинні бути підходом до Монте-Карло.

Це код гольфу, тому виграє найкоротше подання (у байтах).


2
чи дозволено триггерні функції? Я пропоную вам прямо заборонити їх.
Річка рівня Св.

((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
Джон Дворак

@JanDvorak Як це має працювати? Чи не mapдає вам масив trueі false?
Мартін Ендер

@ MartinBüttner Ах, ой, вибачте. .filter{...}.sizeповинні працювати, хоча.
Джон Дворак

@JanDvorak Дійсно. Це дійсно акуратно :)
Мартін Ендер

Відповіді:


17

80386 код машини, 40 38 байт

Шестнадцятковий код:

60 33 db 51 0f c7 f0 f7 e0 52 0f c7 f0 f7 e0 58
03 d0 72 03 83 c3 04 e2 eb 53 db 04 24 58 db 04
24 58 de f9 61 c3

Як отримати цей код (з мови складання):

    // ecx = n (number of iterations)
    pushad;
    xor ebx, ebx; // counter
    push ecx; // save n for later
myloop:
    rdrand eax; // make a random number x (range 0...2^32)
    mul eax; // calculate x^2 / 2^32
    push edx;
    rdrand eax; // make another random number y
    mul eax; // calculate y^2 / 2^32
    pop eax;
    add edx, eax; // calculate D = x^2+y^2 / 2^32 (range 0...2^33)
    jc skip; // skip the following if outside the circle
    add ebx, 4; // accumulate the result multiplied by 4
skip:
    loop myloop;
    push ebx; // convert the result
    fild dword ptr [esp]; // to floating-point
    pop eax;
    fild dword ptr [esp]; // convert n to floating-point
    pop eax;
    fdivp st(1), st; // divide

    popad;
    ret;

Це функція, що використовує fastcallконвенцію виклику MS (кількість ітерацій передається в регістр ecx). Він повертає результат у stрегістр.

Веселі речі щодо цього коду:

  • rdrand - всього 3 байти, щоб генерувати випадкове число!
  • Він використовує (непідписаний) цілу арифметику до остаточного поділу.
  • Порівняння квадратичної відстані ( D) з радіусом квадрата ( 2^32) виконується автоматично - прапор перенесення містить результат.
  • Щоб помножити підрахунок на 4, він підраховує вибірки з кроками 4.

У коментарі слід сказати "Обчислити х ^ 2% 2 ^ 32"
Коул Джонсон

@ColeJohnson Ні - випадкове число в eax; то mulкоманда примножує його саме по собі і ставить високу частку в edx; низька частина у eaxвикидається.
anatolyg

11

Матлаб / Октава, 27 байт

Я знаю, що вже є відповідь Matlab / Octave, але я спробував власний підхід. Я використав той факт, що інтеграл 4/(1+x^2)між 0 і 1 є pi.

mean(4./(1+rand(1,1e5).^2))

Різний алгоритм завжди чудовий! Також ефективніше!
анатоліг

7

R, 40 (або 28 або 24 з використанням інших методів)

mean(4*replicate(1e5,sum(runif(2)^2)<1))

mean(4*sqrt(1-runif(1e7)^2))

mean(4/(1+runif(1e7)^2))

Пітон 2, 56

Ще один Python, якщо numpy дозволений, але досить схожий на Matlab / Octave:

import numpy;sum(sum(numpy.random.rand(2,8e5)**2)<1)/2e5

6

Mathematica, 42 40 39 байт (або 31/29?)

У мене є три рішення в 42 байти:

4Count[1~RandomReal~{#,2},p_/;Norm@p<1]/#&
4Tr@Ceiling[1-Norm/@1~RandomReal~{#,2}]/#&
4Tr@Round[1.5-Norm/@1~RandomReal~{#,2}]/#&

Всі вони є неназваними функціями, які беруть кількість зразків і nповертають раціональне наближення π. По-перше, всі вони генерують nточки в одиничному квадраті в додатному квадранті. Потім вони визначають кількість тих зразків, які лежать в одиничному колі, а потім ділять на кількість зразків і множать на 4. Єдина відмінність полягає в тому, як вони визначають кількість проб всередині одиничного кола:

  • Перший використовує Countз умовою, що Norm[p] < 1.
  • Другий віднімає норму кожної точки з, 1а потім округляє. Це перетворює числа всередині одиничного кола до 1та зовнішніх 0. Згодом я просто підсумовую їх Tr.
  • Третя робить по суті те саме, але віднімає з 1.5, тому я можу використовувати Roundзамість Ceiling.

Aaaaaand, коли я писав це, мені спало на думку, що дійсно є коротше рішення, якщо я просто відняти 2і потім використовувати Floor:

4Tr@Floor[2-Norm/@1~RandomReal~{#,2}]/#&

або збереження іншого байта за допомогою операторів підлоги або стелі Unicode:

4Tr@⌊2-Norm/@1~RandomReal~{#,2}⌋/#&
4Tr@⌈1-Norm/@1~RandomReal~{#,2}⌉/#&

Зауважте, що три рішення на основі округлення також можна записувати з Meanзамість Trі без /#, знову ж таки, для тих же байтів.


Якщо інші підходи, засновані на Монте-Карло, добре (конкретно, той, який вибрав Пітер), я можу зробити 31 байт, оцінивши інтеграл або 29, використовуючи інтеграл , на цей раз заданий як число з плаваючою комою:√(1-x2)1/(1+x2)

4Mean@Sqrt[1-1~RandomReal~#^2]&
Mean[4/(1+1~RandomReal~#^2)]&

9
У вас є три рішення життя, Всесвіту і всього, і ви вирішили його зруйнувати? Єресь.
seequ


6

CJam, 27 23 22 або 20 байт

4rd__{{1dmr}2*mhi-}*//

2 байти збережено завдяки Runner112, 1 байт збережено завдяки Sp3000

Підрахунок ітерації від STDIN приймається як вхід.

Це так само прямо, як це стає. Це основні кроки:

  • Прочитайте введення та запустіть ітерації Монте-Карло багато разів
  • У кожній ітерації отримайте суму квадрата двох випадкових плавців від 0 до 1 і подивіться, чи менша вона від 1
  • Отримайте співвідношення, скільки разів у нас було менше 1 на загальні ітерації, і помножте його на 4, щоб отримати PI

Розширення коду :

4rd                     "Put 4 on stack, read input and convert it to a double";
   __{            }*    "Take two copies, one of them determines the iteration"
                        "count for this code block";
      {1dmr}2*          "Generate 2 random doubles from 0 to 1 and put them on stack";
              mh        "Take hypot (sqrt(x^2 + y^2)) where x & y are the above two numbers";
                i       "Convert the hypot to 0 if its less than 1, 1 otherwise";
                 -      "Subtract it from the total sum of input (the first copy of input)";
                    //  "This is essentially taking the ratio of iterations where hypot";
                        "is less than 1 by total iterations and then multiplying by 4";

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


Якщо середнє значення 1/(1+x^2)також вважається Монте-Карло, то це можна зробити в 20 байтах:

Urd:K{4Xdmr_*)/+}*K/

Спробуйте тут


2
Я також спробував відповідь CJam, і мені вдалося ввести 2 байти під ваш рахунок. Але мій код вийшов настільки подібним до вашого, що я почуваю себе брудною публікацією як окрему відповідь. Все було однаковим, за винятком вибору змінної та цих двох оптимізацій: отримайте випадкове число від 0 до 1 1dmrзамість KmrK/, і перевірте, чи сума квадратів більша за 1 зi а не 1>(я вважав, що це особливо розумно) .
Runer112

@ Runer112 Дякую iтрюк дійсно акуратний! І чорт відсутність документації1dmr
оптимізатор

5

Python 2, 77 75 байт

from random import*;r=random;a=0;exec"a+=r()**2+r()**2<1;"*4000;print a/1e3

Для збереження байтів використовується 4000 зразків 1e3.


5
Ви можете отримати трохи більше точності безкоштовно ...*8000;print a/2e3.
Логічний лицар

5

Commodore 64 Basic, 45 байт

1F┌I=1TO1E3:C=C-(R/(1)↑2+R/(1)↑2<1):N─:?C/250

Заміни PETSCII: = SHIFT+E, /= SHIFT+N, =SHIFT+O

Генерує 1000 балів у першому квадранті; для кожного додає істинність "x ^ 2 + y ^ 2 <1" до підрахунку, а потім ділить рахунок на 250, щоб отриматиpi . (Наявність знаку мінус тому, що на C64 "true" = -1.)


Що робить (1)?
ехрістоферсон

@echristopherson, ти неправильно його читаєш. /це не символ поділу, це символ, який створюється введенням SHIFT+Nна клавіатурі Commodore 64. R/(1)є формою ярлика для RND(1), тобто. "створити випадкове число між 0 і 1, використовуючи поточне насіння RNG".
Марк

О, ти маєш рацію! Старі хороші графічні символи PETSCII.
echristopherson

5

J, 17 байт

Обчислює середнє значення 40000вибіркових значень функції 4*sqrt(1-sqr(x))в діапазоні [0,1].

Легко 0 o.xповертається sqrt(1-sqr(x)).

   1e4%~+/0 o.?4e4$0
3.14915

4

> <> (Риба) , 114 байт

:00[2>d1[   01v
1-:?!vr:@>x|  >r
c]~$~< |+!/$2*^.3
 .41~/?:-1r
|]:*!r$:*+! \
r+)*: *:*8 8/v?:-1
;n*4, $-{:~ /\r10.

Тепер у <<> немає вбудованого генератора випадкових чисел. Однак у нього є функція, яка спрямовує покажчик у випадковому напрямку. Генератор випадкових чисел у моєму коді:

______d1[   01v
1-:?!vr:@>x|  >r
_]~$~< |+!/$2*^__
 __________
___________ _
_____ ____ _______
_____ ____~ ______

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

Решта - це лише регулярні точки в квадратному підході.

Використання: коли ви запускаєте код, ви повинні переконатись у тому, що ви зможете перегрупувати стек (-v у інтерфейсі python) числом зразків, наприклад

pi.fish -v 1000

повертає

3.164

4

29 байт Matlab або Octave (завдяки недосконалості!)

mean(sum(rand(2,4e6).^2)<1)*4

(Я не зовсім впевнений, якщо <1 добре. Я прочитав, що це має бути <= 1. Але наскільки велика ймовірність намалювати рівно 1 ...)

Matlab або Octave 31 байт

sum(sum(rand(2,4e3).^2)<=1)/1e3

1
Дуже приємна ідея! Ви можете зберегти два додаткових байти за допомогою mean(sum(rand(2,4e6).^2)<1)*4.
недолік

4

Java, 108 байт

double π(){double π=0,x,i=0;for(;i++<4e5;)π+=(x=Math.random())*x+(x=Math.random())*x<1?1e-5:0;return π;}

Чотири тисячі ітерацій, додаючи 0,001 кожного разу, коли точка знаходиться всередині одиничного кола. Досить базові речі.

Примітка. Так, я знаю, що можу пролити чотири байти, змінивши πна однобайтовий символ. Мені це подобається так.


чому б не 9999 ітерацій?
Оптимізатор

1
@Optimizer Це робить суму коротшою. Для ітерацій 9999, мені доведеться щоразу додавати більш точне число, що коштує мені цифр.
Геобіт

1
Ви можете зберегти ще один байт і підвищити точність, використовуючи для цифр "4e5" і "1e-5".
Вільмантас Баранаускас

@VilmantasBaranauskas Дякую! Я завжди про це забуваю :) Заманливо використовувати замість цього 4e9 та 1e-9, але це забирає досить багато часу ...
Geobits

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

3

Javascript: 62 байт

for(r=Math.random,t=c=8e4;t--;c-=r()**2+r()**2|0);alert(c/2e4)

Я використав попередню (тепер видалену) відповідь на JavaScript і поголив 5 байт.


Ви можете посилатися на відповідь cfern, щоб правильно надати кредит.
Джонатан Фрех

Ваша відповідь представляє фрагмент, який заборонено введення / виведення . Виправте або видаліть свою публікацію.
Джонатан Фрех

Вибачте, я новий, я не знав, як перенести посилання на попереднє рішення, яке, як видається, було видалено. Щодо фрагменту: я повністю згоден, але це був код попереднього рішення javascript, і я також вважаю, що це причина недійсна. Я змінив шахту на програму.
Гузман Тірно

Так; попередня відповідь була видалена як недійсна - я побачив вашу відповідь, перш ніж порекомендував її видалити, таким чином, коментар. +1 за подання дійсної відповіді; Ласкаво просимо до PPCG!
Джонатан Фрех

2

GolfScript (34 символи)

0{^3?^rand.*^.*+/+}2000:^*`1/('.'@

Демонстрація в Інтернеті

Для цього використовується фіксована точка, оскільки GS насправді не має плаваючої точки. Це трохи зловживає використанням фіксованої точки, тому, якщо ви хочете змінити кількість ітерацій, переконайтеся, що це вдвічі більше, ніж десять.

Кредит xnor для конкретного методу Монте-Карло.


2

Python 2, 90 85 81 байт

from random import*;r=random;print sum(4.for i in[0]*9**7if r()**2+r()**2<1)/9**7

повертається, 3.14120037157наприклад. Кількість вибірки становить 4782969 (9 ^ 7). Ви можете отримати краще пі з 9 ^ 9, але вам доведеться набратися терпіння.


Ви можете зберегти 3 шляхом заміни range(9**7)з [0]*9**7або що - то, так як ви не використовуєте i. І список не надто довгий, щоб стикатися з проблемами пам'яті.
Sp3000

Спасибі. Мені хотілося позбутися, range()але я зовсім забув цю хитрість.
Логічний лицар

У мене таке відчуття [0]9**7не сильно виражений синтаксис.
seequ

Ти правий. Я знову приєднав загублену астерікс (вона була під моїм столом).
Логічний лицар

2

Рубін, 39 байт

p (1..8e5).count{rand**2+rand**2<1}/2e5

Одним із важливих моментів є те, що цей вміє використовувати 8e5позначення, завдяки чому він може розширюватися до ~ 8e9 зразків у тому ж рахунку байтів програми.



1

Scala, 87 77 66 байт

def s=math.pow(math.random,2);Seq.fill(1000)(s+s).count(_<1)/250d

Якщо замінити 1000з 8000і 250dз 2e4вами і зберегти байти і збільшити число зразків з коефіцієнтом 8.
Дейв Шварца

1

Чистий баш, 65 байт

for((;i++<$1*4;a+=RANDOM**2+RANDOM**2<32767**2));{ :;}
echo $a/$1

Бере єдиний параметр командного рядка, який множиться на 4, щоб дати кількість вибірок. Арифметика Баша є лише цілим числом, тому виводиться раціональне. Це може бути вирішено bc -lдля остаточного поділу:

$ ./montepi.sh 10000
31477/10000
$ ./montepi.sh 10000|bc -l
3.13410000000000000000
$ 

1

Джо , 20 19 байт

Примітка: ця відповідь є неконкурентоспроможною, оскільки версія 0.1.2, яка додала випадковості, була випущена після цього виклику.

Названа функція F:

:%$,(4*/+1>/+*,?2~;

Безіменна функція:

%$,(4*/+1>/+*,?2~;)

Вони обидва беруть вибірку як аргумент і повертають результат. Як вони працюють?

%$,(4*/+1>/+*,?2~;)
   (4*/+1>/+*,?2~;) defines a chain, where functions are called right-to-left
               2~;  appends 2 to the argument, giving [x, 2]
              ?     create a table of random values from 0 to 1 with that shape
            *,      take square of every value
          /+         sum rows, giving a list of (x**2+y**2) values
        1>           check if a value is less than 1, per atom
      /+             sum the results
    4*               multiply by four
%$,                  divide the result by the original parameter

Приклад виконання:

   :%$,(4*/+1>/+*,?2~;
   F400000
3.14154
   F400000
3.14302

1

DC, 59 символів (пробіл проігноровано)

[? 2^ ? 2^ + 1>i]su
[lx 1+ sx]si
[lu x lm 1+ d sm ln>z]sz

5k
?sn
lzx
lx ln / 4* p
q

Я перевірив це на План 9 і OpenBSD, тому думаю, що він буде працювати на Linux (GNU?) dc.

Пояснення за рядком:

  1. Зберігає код до [читання та квадрат двох плавців; виконати регістр, iякщо 1 більше суми їх квадратів] у регістрі u.
  2. Зберігає код до [приріст реєстру xна 1] в регістрі i.
  3. Зберігає код у [виконувати реєстр u, приріст реєстру m, а потім виконати регістр, zякщо реєстр mбільший за реєстр n] у регістрі z.
  4. Встановіть шкалу на 5 знаків після коми.

  5. Прочитайте кількість балів для вибірки з першого рядка введення.
  6. Виконати регістр z.
  7. Розділіть регістр x(кількість звернень) на регістр n(кількість балів), помножте результат на 4 та роздрукуйте.
  8. Вийдіть.

Однак я обдурив:

Програмі потрібно подача випадкових плавців між 0 і 1.

/* frand.c */
#include <u.h>
#include <libc.h>

void
main(void)
{
    srand(time(0));

    for(;;)
        print("%f\n", frand());
}

Використання:

#!/bin/rc
# runpi <number of samples>

{ echo $1; frand } | dc pi.dc

Пробіг:

% runpi 10000
3.14840

Тепер з меншим обманом (100 байт)

Хтось зазначав, що я можу включити простий PRng.
http://en.wikipedia.org/wiki/RANDU

[lrx2^lrx2^+1>i]su[lx1+sx]si[luxlm1+dsmln>z]sz[0kls65539*2 31^%dsslkk2 31^/]sr?sn5dksk1sslzxlxlm/4*p

Безумовно

[
Registers:
u - routine : execute i if sum of squares less than 1
i - routine : increment register x
z - routine : iterator - execute u while n > m++
r - routine : RANDU PRNG
m - variable: number of samples
x - variable: number of samples inside circle
s - variable: seed for r
k - variable: scale for division
n - variable: number of iterations (user input)
]c
[lrx 2^ lrx 2^ + 1>i]su
[lx 1+ sx]si
[lu x lm 1+ d sm ln>z]sz
[0k ls 65539 * 2 31^ % d ss lkk 2 31 ^ /]sr
? sn
5dksk
1 ss
lzx
lx lm / 4*
p

Пробіг:

$ echo 10000 | dc pigolf.dc
3.13640

1

Піт, 19

c*4sm<sm^OQ2 2*QQQQ

Уведіть бажану кількість ітерацій як вхідних даних.

Демонстрація

Оскільки Pyth не має функції "Випадкове плаваюче число", мені довелося імпровізувати. Програма вибирає два випадкових натуральних числа, менших за вхідні, квадрати, суми та порівняно з введеними квадратами. Це виконується в кілька разів, рівне вводу, потім результат множать на 4 і ділять на вхід.

У відповідних новинах я незабаром додаю операцію з числом плаваючої крапки до Pyth. Ця програма, однак, не використовує цю функцію.


Якщо ми інтерпретуємо "Результат може бути повернутий або надрукований як плаваюча точка, фіксована точка або раціональне число". вільно, тоді друк чисельника та знаменника отриманої дробу має бути достатнім. В такому разі:

Піт, 18

*4sm<sm^OQ2 2*QQQQ

Це ідентична програма, операцію поділу з плаваючою комою ( c) видалено.


1

Джулія, 37 байт

4mean(1-floor(sum(rand(4^8,2).^2,2)))

Кількість зразків - 65536 (= 4 ^ 8).

Нарізно більш тривалий варіант: функція, що має лише кількість зразків sяк єдиний аргумент:

s->4mean(1-floor(sum(rand(s,2).^2,2)))

1

C, 130 байт

#include<stdlib.h>f(){double x,y,c=0;for(int i=0;i<8e6;++i)x=rand(),y=rand(),c+=x*x+y*y<1.0*RAND_MAX*RAND_MAX;printf("%f",c/2e6);}

Безголівки:

#include <stdlib.h>
f(){
 double x,y,c=0;
 for(int i=0; i<8e6; ++i) x=rand(), y=rand(), c+=x*x+y*y<1.0*RAND_MAX*RAND_MAX;
 printf("%f",c/2e6);
}

звичайно, ви все ще повинні, ймовірно, розміщувати версію без пробілів (збережіть поточну версію із заголовком "неробочий / з пробілами" чи щось)
лимон

@DestructibleWatermelon зроблено!
Карл Напф

Рішення не працює в GCC без нового рядка раніше f(). Який компілятор ви використовували? Дивіться tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/…
eush77


1

Насправді 14 байт (неконкуренто)

`G²G²+1>`nkæ4*

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

Це рішення є неконкурентоспроможним, оскільки мова постає перед викликом. Кількість зразків подається як вхідні дані (а не жорсткі).

Пояснення:

`G²G²+1>`nkæ4*
`G²G²+1>`n      do the following N times:
 G²G²+            rand()**2 + rand()**2
      1>          is 1 greater?
          kæ    mean of results
            4*  multiply by 4

2
Чому потік?
Руйнуючий лимон

1

Ракетка 63 байти

Використовуючи метод відповіді на мову R від @Matt:

(/(for/sum((i n))(define a(/(random 11)10))(/ 4(+ 1(* a a))))n)

Безголівки:

(define(f n)
   (/
    (for/sum ((i n))
      (define a (/(random 11)10))
      (/ 4(+ 1(* a a))))
    n))

Тестування:

(f 10000)

Вихід (частка):

3 31491308966059784/243801776017028125

Як десятковий:

(exact->inexact(f 10000))

3.13583200307849

1

Фортран (GFortran) , 84 83 байти

CALL SRAND(0)
DO I=1,4E3
X=RAND()
Y=RAND()
IF(X*X+Y*Y<1)A=A+1E-3
ENDDO
PRINT*,A
END

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

Цей код написаний дуже погано. Це не вдасться, якщо gfortran вирішить ініціалізувати змінну Aз іншим значенням, то 0 (що зустрічається 50% компіляцій, приблизно) і, якщоA ініціалізовано як 0, він завжди генерує ту саму випадкову послідовність для даного насіння. Тоді те саме значення для Pi друкується завжди.

Це набагато краща програма:

Фортран (GFortran) , 100 99 байт

A=0
DO I=1,4E3
CALL RANDOM_NUMBER(X)
CALL RANDOM_NUMBER(Y)
IF(X*X+Y*Y<1)A=A+1E-3
ENDDO
PRINT*,A
END

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

(У кожній версії зберігається один байт; дякую Пінгвіно).


1
У кожній версії ви можете зберегти байт, змінивши "DO I = 1,1E3" на "DO I = 1,4E3", змінивши "A = A + 1" на "A = A + 1E-3" і змінивши " PRINT *, A / 250 'до' PRINT *, A '
Penguino

Так, ви впевнені! Дякую за пропозицію!
rafa11111

1

Japt , 26 або 18 байт

o r_+ÂMhMr p +Mr p <1Ã*4/U

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

Аналогічна відповіді оптимізатора , в основному лише намагається вивчити Japt.
Приймає кількість повторень, які слід виконати як неявний вхід U.

o                           Take the input and turn it into a range [0, U),
                            essentially a cheap way to get a large array.
  r_                        Reduce it with the default initial value of 0.
    +Â                      On each iteration, add one if
      MhMr p +Mr p          the hypotenuse of a random [0,1)x[0,1) right triangle
                   <1       is smaller than one.
                     Ã*4/U  Multiply the whole result by four and divide by input.

Якщо 1/(1+x^2)це дозволено (замість двох окремих рандов), то ми можемо досягти 18 байт з однаковою логікою.

o r_Ä/(1+Mr pÃ*4/U

1
Ви можете зберегти кілька байтів, дозволяючи Mhобчислити гіпотенузу, а не робити це самостійно ;-) Також ви можете xвзяти суму масиву, а не зменшувати додаванням:o x@MhMr Mr)<1Ã*4/U
ETHproductions

@ETHproductions Охайний, я не знав, що ти можеш так використовувати Mh, дякую! Ваша двовипадкова відповідь майже така ж коротка, як моя відповідь лише з однією випадковою, це дуже круто. Я маю xна увазі, я, як правило, використовую скорочення дуже багато, коли намагаюся пограти в гольф, тому це стане дуже зручним.
Ніт

1

F #, 149 байт

open System;
let r=new Random()
let q()=
 let b=r.NextDouble()
 b*b
let m(s:float)=(s-Seq.sumBy(fun x->q()+q()|>Math.Sqrt|>Math.Floor)[1.0..s])*4.0/s

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

Наскільки я можу розібратися, щоб зробити такий тип загальної кількості в F # це коротше створити масив чисел і використовувати Seq.sumByметод, ніж використовуватиfor..to..do блок.

Що робить цей код, він створює колекцію чисел з плаваючою комою від 1 до s , виконує функцію fun x->...для кількості елементів колекції та підсумовує результат. У sколекції є елементи, тому робиться випадкова перевіркаs разів. Фактичні числа в колекції ігноруються ( fun x->, алеx не використовуються).

Це також означає, що програма повинна спершу створити і заповнити масив, а потім повторити його. Так що, мабуть, удвічі повільніше, ніжfor..to..do петля. А при створенні масиву використання пам'яті використовується в області O (f ** k)!

Для самого власного тесту замість використання if then elseоператора, що він робить, він обчислює відстань ( q()+q()|>Math.Sqrt) та округляє його Math.Floor. Якщо відстань знаходиться в колі, вона буде округлена до 0. Якщо відстань поза колом, вона округлятиметься до 1.Seq.sumBy метод підсумовує ці результати.

Тоді зауважимо, що всього, що Seq.sumByмає значення, - це не точки всередині кола, а точки зовні ним. Отже для результату він бере s(наш розмір вибірки) і віднімає з нього загальну суму.

Також виявляється, що взяти розмір вибірки як параметр коротше, ніж значення жорсткого кодування. Тож я трохи обманюю ...


1

Haskell, 116 114 110 96 байт

d=8^9
g[a,b]=sum[4|a*a+b*b<d*d]
p n=(sum.take(floor n)$g<$>iterate((\x->mod(9*x+1)d)<$>)[0,6])/n

Оскільки для роботи import System.Random; r=randoms(mkStdGen 2)буде потрібно занадто багато дорогоцінних байтів, я генерую нескінченний список випадкових чисел з лінійним конгруентним генератором, який, як кажуть деякі, майже криптографічно сильний: x↦x*9+1 mod 8^9який теорема Халла-Доубела має повний період 8^9.

g врожайність 4 якщо точка випадкового числа знаходиться всередині кола для пар випадкових чисел у[0..8^9-1] оскільки це виключає множення використовуваної формули.

Використання:

> p 100000
3.14208

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


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