내추럴 파이 # 1-모래


9

N균일 한 길이 ( l) 의 임의의 선분을 생성하고 ( ) 등거리 ( t) 평행선 을 교차하는지 확인합니다 .

시뮬레이션

우리는 무엇을 시뮬레이션하고 있습니까? 부폰의 바늘 . 샌드 박스에서 모래를 부드럽게하고 같은 간격의 평행선을 그리십시오 (사이의 거리를 호출하십시오 t). 길이가 똑 바른 막대를 가지고 샌드 박스에 l떨어 뜨립니다 N. 라인을 넘은 횟수를로하자 c. 그럼 Pi = (2 * l * n) / (t * c)!

우리는 이것을 어떻게 시뮬레이트합니까?

  • 입력 받기 N,t,l
  • 가진 N, t, l모든 것을 양의 정수
  • 다음과 같이하십시오 N:
    • 균일하게 임의의 정수 좌표 생성 x,y
    • 1 <= x, y <= 10^6
    • x,y 길이의 선분의 중심 l
    • 균일하게 임의의 정수 생성 a
    • 1 <= a <= 180
    • 하자 P선분이 x 축과 교차하는 위치를 수
    • 그런 다음 a각도입니다(x,y), P, (inf,0)
  • 정수에 c대해 선 x = i*t을 교차하는 선분 의 수를 세십시오.i
  • 반환 (2 * l * N) / (t * c)

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

사양

  • 입력
    • 유연성, 표준 방식 (예 : 함수 매개 변수, STDIN) 및 표준 형식 (예 : 문자열, 이진)으로 입력
  • 산출
    • 유연하고 표준적인 방법으로 출력합니다 (예 : 반환, 인쇄)
    • 공백, 후행 및 선행 공백이 허용됩니다.
    • 정확도, 정밀도의 적어도 4 소수점을 제공하십시오 (예 3.1416)
  • 채점
    • 최단 코드 승리!

테스트 사례

무작위 확률로 인해 결과가 이것들과 일치하지 않을 수 있습니다. 그러나 평균적으로 주어진 값에 대해이 정도의 정확도를 얻을 수 N, t, l있습니다.

Input (N,t,l)    ->  Output 
-----------        ------
10,10,5          -> ?.????
10,100,50        -> ?.????
1000,1000,600    -> 3.????
10000,1000,700   -> 3.1???
100000,1000,700  -> 3.14??

TL; DR

이러한 과제는 Pi를 근사화하기 위해 자연과 두뇌 (및 일부 재사용 가능한 리소스) 만 필요한 알고리즘 시뮬레이션입니다. 좀비 종말 중에 Pi가 정말로 필요하다면,이 방법들은 탄약을 낭비 하지 않습니다 ! 총 9 가지 과제 가 있습니다 .


벌써 1 번했다고 생각 했어?
Conor O'Brien

1
@ ConorO'Brien I 인덱스 0 XD
NonlinearFruit 1

이 문제는 복잡한 숫자가없는 언어에서 숫자 0..180을 0..pi로 바꿔야한다는 것입니다.
Level River St

@NonlinearFruit 방향 a이 균일하다면 다른 방법 으로 방향 을 만들 수 있습니까? (2D Gauss Bubble 생각)
Karl Napf

1
그렇게 가정 할 수 있습니까 t > l? 아래의 두 가지 솔루션이 이러한 가정을하므로 교차점 점검이 상당히 간단 해집니다.
primo

답변:


9

R, 113 (100) 75 70 68 67 65 59 63 57 바이트

통계적이고 기능적인 프로그래밍 언어로서, R이 이런 종류의 작업에 상당히 적합하다는 것은 놀라운 일이 아닙니다. 대부분의 함수가 벡터화 된 입력을 취할 수 있다는 사실은 반복을 N반복 하지 않고 size의 벡터를 전달 하기 때문에이 문제에 실제로 도움이 N됩니다. 4 바이트를 잘라내는 몇 가지 제안에 대해 @Billywob에게 감사드립니다. @Primo에게 감사의 말을 전합니다 t > l.

pryr::f(2*l*N/t/sum(floor(runif(N)+sinpi(runif(N))*l/t)))

온라인으로 사용해보십시오!

샘플 출력 :

N=1000, t=1000, l=500
3.037975

N=10000, t=1000, l=700
3.11943

N=100000, t=1000, l=700
3.140351

설명

문제 x는 바늘 의 두 값이 평행선의 양쪽 에 있는지 여부를 결정하는 것으로 요약됩니다 . 이것은 몇 가지 중요한 결과를 초래합니다.

  1. y-값은 관련이 없습니다
  2. - x축의 절대 위치 는 관련이 없으며 가장 가까운 평행선을 기준으로 한 위치입니다.

본질적으로 이것은 1 차원 공간에서 작업이며, 여기서 우리는 [0, l]의 길이를 가진 선을 생성하고 (각 a이이 길이를 결정)이 길이가 몇 번을 초과하는지 확인합니다 t. 대략적인 알고리즘은 다음과 같습니다.

  1. x1[0, 1000000]의 샘플 값. 평행선 tx축을 따라 모든 점 에서 발생하므로 상대 x위치는 x모듈로 t입니다.
  2. 각도를 샘플링합니다 a.
  3. x2기준으로 위치를 계산하십시오 a.
  4. 바닥에 몇 번 x1+x2들어가는 지 확인하십시오 .t(x1+x2)/t

샘플링 N[0, 1E6] 모듈의 숫자 것은 t단순히 샘플링 동등하다 N[0에서 참조 t]. (x1+x2)/t와 동일 하므로 x1/t + x2/t첫 번째 단계는 [0, t] / t, 즉 [0, 1] 에서 샘플링됩니다 . 운 좋게도, 그것은 R의 runif함수 의 기본 범위이며 N, 균일 분포에서 0에서 1까지의 실수 를 반환합니다 .

                          runif(N)

이 단계를 반복 a하여 바늘 각도 를 생성 합니다.

                                         runif(N)

이 숫자는 반 회전 (즉 .590도)으로 해석됩니다 . (영업은 1 내지 180도를 요구하지만, 주석에 그것 또는 더 정확한 경우 임의의 방법이 허용되는지 명확히있다.)의 각도를 들어 θ, sin(θ)우리가 니들의 단부 사이의 X 축 거리를 제공한다. (일반적으로는이 같은 대한 코사인을 사용하는 것입니다,하지만 우리의 경우, 우리는 각도를 고려하고있는 θ(즉, 0도의 값이 간다 y 축에 상대적이 아닌 x 축 인 것으로를 위로 하지 우측 ), 따라서 우리는 사인에 의해 기본적으로 위상 변화 숫자를.) 곱한 사용 l이 우리에게주는 x바늘의 끝의 위치를.

                                   sinpi(runif(N))*l

이제 우리 tx1값을 나누고 더합니다 . 이것은 평행선의 수로 (x1+x2)/t바늘이 얼마나 멀리 돌출되어 있는지를 나타 x1냅니다. 몇 줄을 넘 었는지 정수를 얻으려면을 사용합니다 floor.

                    floor(runif(N)+sinpi(runif(N))*l/t)

우리는 합계를 계산하여 c바늘로 몇 줄을 넘 었는지 계산합니다 .

                sum(floor(runif(N)+sinpi(runif(N))*l/t))

나머지 코드는 pi를 근사하는 공식, 즉을 구현합니다 (2*l*N)/(t*c). 우리는 다음과 같은 사실을 이용하여 괄호에 약간의 바이트를 절약합니다 (2*l*N)/(t*c) == 2*l*N/t/c.

        2*l*N/t/sum(floor(runif(N)+sinpi(runif(N))*l/t))

그리고 모든 것이 익명 함수로 싸여 있습니다.

pryr::f(2*l*N/t/sum(floor(runif(N)+sinpi(runif(N))*l/t)))

@rturnbull 멋진 하나! 그래도 처음에 괄호를 건너 뛸 수 없어야합니까? (2*l*N) => 2*l*N?
Billywob

@Billywob 잘 발견! 감사.
rturnbull

@rturnbull 아 그리고 그런데, (2*l*N)/(t*c) = 2*l*N/t/c마지막 부분에서 괄호를 건너 뛰면 2 바이트를 더 절약 할 수 있습니다.
Billywob

@Billywob 다시, 잘 발견! 다시 감사합니다.
rturnbull

1
@primo 다시 한번 감사드립니다. 이제 수정해야합니다.
rturnbull

6

펄, 97 바이트

#!perl -p
/ \d+/;$_*=2*$'/$&/map{($x=(1+~~rand 1e6)/$&)-$a..$x+($a=$'/$&/2*sin~~rand(180)*71/4068)-1}1..$_

shebang을 하나로 계산하면 입력이 stdin에서 분리되어 공간이 분리됩니다. 정수가 아닌 임의의 값이 허용 된 경우 다소 짧을 수 있습니다.

나는 π / 18071/4068근사한 하나의 자유 를 얻었으며 , 이는 1.48 · 10-9 내에서 정확 합니다.

샘플 사용법

$ echo 1000000 1000 70000 | perl pi-sand.pl
3.14115345174061

다소 수학적으로 동등한 대체

x 좌표가 문제 설명에 지정된 바늘의 가운데가 아니라 바늘의 가장 왼쪽 점을 나타낸다고 가정합니다.

89 바이트

#!perl -p
/ \d+/;$_*=2*$'/$&/map{($x=(1+~~rand 1e6)/$&)..$x+($'/$&*sin~~rand(180)*71/4068)-1}1..$_

문제 x는이를 임의의 정수로 샘플링하도록 지정합니다 . 우리가 하나의 간격으로 줄 간격을 투사 할 경우,이 형태의 값으로 우리를 떠나 n/t함께 0 <= n < t하는 경우, 반드시 균일하지, t균등 분할하지 않습니다 1e6. 그럼에도 불구하고 균일 한 분포가 허용된다고 가정하면 :

76 바이트

#!perl -p
/ \d+/;$_*=2*$'/$&/map{($x=rand)..$x+($'/$&*sin~~rand(180)*71/4068)-1}1..$_

이후 있습니다 rand항상 미만 (따라서 제로로 잘립니다)입니다,이 범위의 시작에 필요하지 않습니다 :

70 바이트

#!perl -p
/ \d+/;$_*=2*$'/$&/map{1..(rand)+($'/$&*sin~~rand(180)*71/4068)}1..$_

바늘의 각도가 정수 정도일 필요는 없지만 균일하게 무작위로만 가정하면 :

59 바이트

#!perl -p
/ \d+/;$_*=2*$'/$&/map{1..(rand)+abs$'/$&*sin rand$`}1..$_

각도가 균일 한 분포 일 수 있다고 가정합니다.

52 바이트

#!perl -p
/ \d+/;$_*=2*$'/$&/map{1..(rand)+abs$'/$&*sin}1..$_

위는 Buffon 's Needle의 수학적으로 올바른 시뮬레이션입니다. 그러나이 시점에서 나는 대부분의 사람들이 이것이 실제로 질문 한 것이 아니라는 데 동의 할 것이라고 생각합니다.


정말 밀어 붙여

두 번째 엔드 포인트가 첫 번째의 왼쪽에있을 때마다 테스트 케이스의 절반을 버릴 수 있습니다.

47 바이트

#!perl -p
/ \d+/;$_*=$'/$&/map{1..(rand)+$'/$&*sin}1..$_

의 값을 참고 t하고 l실험 결과에 하찮은이다. 우리는 그것들을 무시할 수 있습니다 (암시 적으로 동일하다고 가정).

28 바이트

#!perl -p
$_/=map{1..(rand)+sin}1..$_

분명히 비 경쟁적이지만, 당신은 인정해야합니다, 그것은 그것에 우아함이 있습니다.


4

파이썬 2, 141 바이트

rtumbull의 뻔뻔한 포트, y완전히 필요하지 않기 때문에 이미 건너 뜁니다 .

from math import*
from random import*
lambda N,t,l:(2.*l*N)/(t*sum(randint(1,1e6)%t+abs(cos(randint(1,180)*pi/180))*l>t for _ in range(N)))

문제는 단지 pi가 이미 프로그램에 알려져 있다는 것입니다.

여기 pi가 알려지지 않고 삼각 함수가없는 (골프 가능)

def g(N,t,l):
 c=0
 for _ in range(N):
    x,y=gauss(0,1),gauss(0,1);c+=randint(1,1e6)%t+abs(x/sqrt(x*x+y*y))*l>t
 return(2.*l*N)/(t*c)

x,yin g은 방향입니다.


필요합니다 from random import randint;from math import cos,pi. 에 실패합니다 t < l(예 :) 1000000,1000,70000.
primo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.