디스크의 포인트를 랜덤 화


14

나는 어딘가에 서클에 대해 읽었고 지금은 디스크에 대해 배웠고 ( 실제로는 매우 일반적인 개념 임) codegolf에 대해 생각했습니다.

당신의 임무는 반경이 1 인 디스크 의 포인트 / 여러 포인트를 무작위로 만드는 것 입니다.

규칙 :

  • 모든 포인트는 생성 될 확률이 같아야합니다
  • 부동 소수점 좌표를 사용해야합니다. 최소 요구 사항은 소수점 이하 두 자리입니다 (예 : 점 (0.12, -0.45)또는 (0.00, -1.00)유효)
  • 프로그램이 실제로 경계 원과 그 안에 생성 된 점을 표시하면 -20 바이트를 얻습니다. 좌표는 여전히 유효해야하지만 표시되지 않아야하며 생성 된 이미지의 크기는 201 x 201 픽셀 이상이어야합니다.
  • 프로그램이 stdin에서 입력으로 생성되는 포인트 수를 사용하면 -5 바이트를 얻습니다.
  • 경계 원과 점을 플롯하지 않기로 결정한 경우, 프로그램은 형식 (x, y)또는 (x,y)stdout에서 생성 된 점을 출력해야합니다
  • 생성 된 점의 수를 입력으로 사용하지만이를 플롯하지 않기로 결정한 경우, 프로그램은 사이에 하나의 공백이 있거나없는 위에서 언급 한 형식으로 모든 무작위 점을 출력해야합니다.

바이트 단위의 최단 제출이 승리합니다!


1
@sweerpotato 네, 동그라미 안의 모든 점이 유효하도록 지정하십시오. 나는 당신이 둘 다를 의미한다는 것을 몰랐습니다. 또한이 질문은 인기 대회보다 코드 골프 도전에 더 적합한 것처럼 보이지만 내 의견 일뿐입니다.
cole

5
" 마 XYZ는 창조적 인 방법으로 "™ 고전 나쁜 Popcon 질문입니다. 한 사람이 창조적이라고 생각하는 것은 다른 사람이 분명한 방법을 고려하는 것입니다.
피터 테일러

호기심에서 플롯에 201x201 픽셀 출력 요구 사항이 필요한 이유는 무엇입니까?
JohnE

이 필요한 소수점 이하 2 자리 정도 일치로 @JohnE 나는 201x201 픽셀을 제안
trichoplax

좌표를 복소수로 출력 할 수 있습니까? 예를 들면 다음과 같습니다 0.3503082505747327+0.13499221288682994j..
orlp

답변:


5

Pyth, 26-5 = 21 바이트

VQp(sJ*@OZ2^.n1*yOZ.l_1)eJ

stdin에서 생성 할 좌표 수를 가져 와서 다음과 같이 stdout에 출력합니다.

(-0.5260190768964058, -0.43631187015380823)(-0.12127959509302746, -0.08556306418467638)(-0.26813756369750996, -0.4564539715526493)

복잡한 지수를 사용하는 점을 제외하고는 극좌표와 반지름을 생성하는 @ MartinBüttner와 유사한 전략을 사용합니다.


를 제거 p할 수 있습니까? 출력을 별도의 행으로 변경합니다.
PurkkaKoodari

@ Pietu1998 허용되지 않습니다. 주요 질문에 대한 의견을 참조하십시오.
orlp

아, 그렇습니다.
PurkkaKoodari

16

CJam, 28 27 바이트

PP+mr_mc\ms]1.mrmqf*"(,)".\

이 솔루션은 거부 기반이 아닙니다. 점을 극좌표로 생성하지만 점의 균일 한 밀도를 달성하기 위해 반지름의 균일하지 않은 분포를 사용합니다.

여기에서 테스트하십시오.

설명

PP+     e# Push 2π.
mr_     e# Get a random float between 0 and 2π, make a copy.
mc\     e# Take the cosine of one copy and swap with the other.
ms]     e# Take the sine of the other copy and wrap them in an array.
        e# This gives us a uniform point on the unit circle.
1.mr    e# Get a random float between 0 and 1.
mq      e# Take the square root. This is the random radius.
f*      e# Multiply x and y by this radius.
"(,)".\ e# Put the resulting numbers in the required format.

왜 작동합니까? 반지름이 좁은 고리 r와 너비가 작은 것을 고려하십시오 dr. 면적은 대략 2π*r*dr(환형이 좁 으면 내주와 외주가 거의 같고, 곡률을 무시할 수있어 면적이 원주와 옆면의 가로 길이를 가진 직사각형의 영역으로 취급 될 수 있음) 고리). 따라서 면적은 반지름에 따라 선형으로 증가합니다. 즉, 일정한 밀도를 달성하기 위해 (반지름의 두 배에서 채우는 면적이 두 배이므로, 두 배의 포인트가 필요합니다) 랜덤 반경의 선형 분포가 필요합니다.

0에서 1까지 선형 랜덤 분포를 어떻게 생성합니까? 개별 사례를 먼저 살펴 보겠습니다. 예를 들어, 우리는 4 배의 원하는 분포를가집니다 {0.1, 0.4, 0.2, 0.3}(즉, 우리는 14 배 0, 두 배는 일반적이고 2; 우리는 3세배를 공통적으로 원합니다 0) :

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

원하는 분포로 4 가지 값 중 하나를 어떻게 선택할 수 있습니까? 우리는 그것들을 쌓아 올릴 수 있고 y 축에서 0과 1 사이의 균일 한 무작위 값을 고르고 그 시점에서 세그먼트를 선택할 수 있습니다 :

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

이 선택을 시각화하는 다른 방법이 있습니다. 대신 분포의 각 값을 해당 시점까지의 값 누적으로 대체 할 수 있습니다.

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

이제이 차트의 맨 윗줄을 함수로 취급하고 함수 f(x) = y를 얻기 위해 뒤집습니다.이 함수 는 다음 에서 균일하게 임의의 값을 적용 할 수 있습니다 .g(y) = f-1(y) = xy ∈ [0,1]

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

근사한데, 어떻게 이것을 사용하여 반지름의 선형 분포를 생성 할 수 있습니까? 이것은 우리가 원하는 분포입니다.

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

첫 번째 단계는 분포 값을 누적하는 것입니다. 그러나 분포는 연속적이므로 이전의 모든 값을 합산하는 대신에서 0를 적분 합니다 r. 이를 분석적으로 쉽게 해결할 수 있습니다 . 그러나 우리는 이것을 정규화하기를 원합니다. 즉 , 최대 값을 얻을 수 있도록 상수를 곱하면 실제로 원하는 것은 다음과 같습니다.0r r dr = 1/2 r21rr2

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

그리고 마지막으로, 우리는이 반전은 우리가 균일 한 값에 적용 할 수있는 기능을 얻을 수 [0,1]는 단지 : 우리는 다시 해석 할 수있는, r = √y, y임의의 값입니다 :

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

이것은 간단한 분포를 정확하게 생성하기 위해 종종 사용될 수있는 상당히 유용한 기술입니다 (모든 분포에서 작동하지만 복잡한 것에서는 마지막 두 단계를 수치 적으로 해결해야 할 수도 있습니다). 그러나 제곱근, 사인 및 코사인이 엄청나게 비싸기 때문에 생산 코드 에서이 특별한 경우에는 사용하지 않을 것입니다. 거부 기반 알고리즘을 사용하는 것은 평균과 곱셈 만 필요하기 때문에 평균적으로 훨씬 빠릅니다.


1
아주 좋은 설명!
sweerpotato

2
음 그림 : D
베타 부패

12

Mathematica, 68 44-20 = 24 바이트

RandomPoint24 비트를 절약 한 David Carraher에게 많은 감사를드립니다 . Mathematica 에는 모든 것이 내장되어 있습니다.

Graphics@{Circle[],Point@RandomPoint@Disk[]}

이것은 보너스를받을 수있는 지점과 경계 원을 표시합니다.

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

결과는 벡터 이미지이므로 201x201 픽셀의 크기 사양은 실제로 의미가 없지만 기본적으로 그보다 더 크게 렌더링됩니다.


어때요 Graphics[{Circle[], Point@RandomPoint@Disk[]}]?
DavidC

사양하지 마세요. 또한 1 바이트를 절약하려면Graphics@{Circle[], Point@RandomPoint@Disk[]}
DavidC

@DavidCarraher 감사합니다! :)
Martin Ender

Mathematica 구문을 모르지만 반드시 ,? 뒤에 공백을 제거하여 다른 바이트를 저장할 수 있습니다 .
푹신한

@fluffy 나는 이미 게시 된 버전에서했다
Martin Ender

9

CJam, 31 26 바이트

{];'({2dmr(_}2*@mhi}g',\')

이것은 측면 길이 2의 제곱에서 임의의 점을 반복적으로 생성하고 첫 번째 점을 단위 디스크 내부에 유지함으로써 작동합니다.

3 바이트를 사용하지 않은 @ MartinBüttner에게 감사합니다!

CJam 통역사 에서 온라인으로 사용해보십시오 .

작동 원리

{                  }g       Do:
 ];'(                         Clear the stack and push a left parenthesis.
     {      }2*               Do twice:
      2dmr                      Randomly select a Double between 0 and 2.
          (_                    Subtract 1 and push a copy.
               @              Rotate the copy of the first on top of the stack.
                mh            Compute the Euclidean norm of the vector consisting
                              of the two topmost Doubles on the stack.
                  i           Cast to integer.
                            If the result is non-zero, repeat the loop.
                     ',\    Insert a comma between the Doubles.
                        ')  Push a right parenthesis.

8

iKe , 53 51 바이트

특별히 특별한 것은 없지만 적어도 하나의 그래픽 솔루션이 있어야한다고 가정합니다.

,(80+160*t@&{.5>%(x*x)+y*y}.+t:0N 2#-.5+?9999;cga;3)

음모

브라우저에서 사용해보십시오 .

편집 : 극좌표의 분포를 수정하기 위해 @ MartinBüttner의 접근 방식을 적용하여 2 바이트를 줄일 수 있습니다. 나는 또한 그것이 조금 더 직접적이라고 생각합니다.

,(80*1+(%?c){x*(cos y;sin y)}'6.282*?c:9999;cga;3)

3
경계 원을 그리면 -20을 사용할 수 있습니다.
orlp

1
iKe는 래스터 기반 도면 모델을 가지고 있기 때문에 요구 사항이 불공평합니다. 경계 원의 근사값을 렌더링하는 데 20 자 이상이 소요될 것으로 생각합니다.
JohnE

7

펄, 59 바이트

while(($x=1-rand 2)**2+($y=1-rand 2)**2>1){};print"($x,$y)"

이것은 간단한 해결책으로 사각형에 점을 생성하고 너무 멀리 떨어진 점을 거부합니다. 나의 단골 골프 트릭은 조건 안에 과제를 포함시키는 것입니다.

편집 : 골프 과정에서 에 임의의 점을 인쇄하는 흥미로운 방법을 찾았습니다 .

use Math::Trig;$_=rand 2*pi;print"(",sin,",",cos,")"

7

옥타브, 24 53-20 = 33 바이트

polar([0:2e-3:1,rand]*2*pi,[ones(1,501),rand^.5],'.')

501의 동일한 간격의 세타 값과 하나의 난수를 생성하고 모두 [0..2π]로 조정합니다. 그런 다음 원의 반지름에 대해 501 1을 생성하고 점에 대한 임의의 반지름을 생성하고 제곱근을 취해 디스크에 균일하게 분포시킵니다. 그런 다음 모든 점을 극좌표로 플로팅합니다.

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


다음은 분포에 대한 간단한 데모입니다 (단위 원 제외).

polar(2*pi*rand(99),rand(99).^.5,'.')

9801 포인트


5

옥타브 / 매트랩, 74 64 바이트

거부 방법 , 64 바이트 :

u=1;v=1;while u^2+v^2>1
u=rand;v=rand;end
sprintf('(%f,%f)',u,v)

직접적인 방법 , 74 바이트 (마틴 부트 너 덕분에 두 가지 오류를 수정 해 주셔서 감사합니다) :

t=rand*2*pi;r=1-abs(1-sum(rand(2,1)));sprintf('(%f,%f)',r*cos(t),r*sin(t))

5

R, 99 95 81-20 = 79 75 61 바이트

symbols(0,0,1,i=F,asp=1,ylim=c(-1,1));points(complex(,,,runif(9),runif(9,-1)*pi))

복소수 구성을 사용하여 극좌표에서 x / y를 만듭니다. 입력을받는 것은 약간 비쌌으며 아마도 더 좋은 방법이있을 것입니다. ylim xlim 전체 원 플롯하고 보장하는 asp보장하지만이 지점은 원형 심볼로 나타낸다.

저축을위한 @jbaums와 @flodel에 감사합니다

여기 사용해보십시오


runif(9,0,1)로 단순화 할 수있다runif(9)
jbaums

@jbaums, 고마워 ... 내가 항상 잊어 버린 것 중 하나 :)
MickyT

14를 면도 할 수 있습니다 :symbols(0,0,1,i=F,asp=1,ylim=c(-1,1));points(complex(,,,runif(9),runif(9,-1)*pi))
flodel

@flodel 아주 좋은 감사합니다.
MickyT

또 다른 조그만 절약 : yli대신 작동합니다 ylim.
jbaums

4

/ Java 처리 141 바이트 -20 = 121

201 * 201의 최소 크기 요구 사항은 setupProcessing.org의 기본값이 200x200이므로 메서드 를 입력해야합니다.

void setup(){noFill();size(201,201);}void draw(){float f=10,a=PI*2*random(),r=random();point(f+f*sin(a)*r,f+f*cos(a)*r);ellipse(f,f,f*2,f*2)}

처리 / 자바가 허용되는지 몰랐습니다.
J Atkin

4

Q 기본, 138 바이트-20-5 = 113

INPUT n
r=200
SCREEN 12
RANDOMIZE TIMER
CIRCLE(r,r),r
PAINT(r,r)
FOR i=1TO n
DO
x=RND*r*2
y=RND*r*2
LOOP UNTIL POINT(x,y)
PSET(x,y),1
NEXT

사용자 입력을 받아 디스크와 포인트를 그립니다. QB64에서 테스트되었습니다 .

이것은 매우 기본적인 "다트 보드에서 던지고 무엇을 고수 하는가"전략입니다. 캐치는 "수 착점"은 수학적으로 결정되는 것이 아니라 그래픽으로 결정한다는 것입니다. 흰색 디스크는 검은 색 배경에 그려지고 무작위로 생성 된 점은 검은 색이 아닐 때까지 거부됩니다. 점 자체는 파란색으로 표시됩니다 (단일 픽셀인지는 알기가 어렵지만 이미지를 클릭하여 확대하십시오).


3

awk-95-5 = 90

{
    for(;$1--;printf"("(rand()<.5?x:-x)","(rand()<.5?y:-y)")")
        while(1<(x=rand())^2+(y=rand())^2);
}

rand () <. 5 부분에 대해 잘 모르기 때문에이 스크립트를 사용하여 이것으로 배포 테스트를 수행했습니다.

BEGIN{ srand() }
{ 
    split("0 0 0 0", s)
    split("0 0 0 0", a)

    for(i=$1; i--; )
    {
        while( 1 < r2 = ( x=rand() )^2 + ( y=rand() )^2 );

        x = rand()<.5 ? x : -x
        y = rand()<.5 ? y : -y

        ++s[ x>=0 ? y>=0 ? 1 : 4 : y>=0 ? 2 : 3 ]

        ++a[ r2>.75 ? 1 : r2>.5 ? 2 : r2>.25 ? 3 : 4]
    }

    print "sector distribution:"
        for(i in s) print "sector " i ": " s[i]/$1

    print "quarter area distribution:"
        for(i in a) print "ring " i ":   " a[i]/$1
}

1e7을 입력하면 커피에 한두 번 뱉은 후이 결과를 얻을 수 있습니다.

1e7
sector distribution:
sector 1: 0.250167
sector 2: 0.249921
sector 3: 0.249964
sector 4: 0.249948
quarter area distribution:
ring 1:   0.24996
ring 2:   0.25002
ring 3:   0.250071
ring 4:   0.249949

제 생각에는 아주 괜찮습니다.

약간의 설명 :
잠시 동안 낙서 한 후에 디스크를 같은 면적의 네 개의 고리로 나누려면 잘라야 할 반지름은 sqrt (1/4), sqrt (1/2) ) 및 sqrt (3/4). 내가 테스트 한 점의 실제 반지름은 sqrt (x ^ 2 + y ^ 2)이므로 제곱근을 모두 건너 뛸 수 있습니다. 1/4, 2/4, 3/4 "우연성"은 M. Buettner가 이전에 지적한 것과 관련이있을 수 있습니다.


3

HPPPL , 146 (171-20-5) 바이트

EXPORT r(n)BEGIN LOCAL R,A,i,Q;RECT();Q:=118.;ARC_P(Q,Q,Q);FOR i FROM 1 TO n DO R:=√RANDOM(1.);A:=RANDOM(2*π);PIXON_P(G0,IP(Q+Q*R*COS(A)),IP(Q+Q*R*SIN(A)));END;FREEZE;END;

10000 포인트의 예 (실제 장치의 시간 (초) 포함) :

디스크의 포인트를 무작위로 타이밍

함수 자체는에 의해 호출됩니다 r(n). 위 이미지의 나머지 부분은 타이밍 목적으로 만 사용됩니다.

결과 (디스크 직경은 236 픽셀) :

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

위의 버전은 점 좌표를 저장하지 않으므로 두 개의 매개 변수를 사용하는 버전을 작성했습니다 r(n,p). n포인트의 수이고, p=0상기 단말기에 포인트 반환 p=1좌표를 저장하는 것이 필수적이다 경우 플롯 점과 디스크). 이 버전은 283 (308-20-5) 바이트입니다.

EXPORT r(n,p)BEGIN LOCAL R,A,j,Q,x,y;Q:=118.0;CASE IF p==0 THEN print() END IF p==1 THEN RECT();ARC_P(Q,Q,Q) END END;FOR j FROM 1 TO n DO R:=√RANDOM(1.0);A:=RANDOM(2*π);x:=R*COS(A);y:=R*SIN(A);CASE IF p==0 THEN print("("+x+", "+y+")") END IF p==1 THEN PIXON_P(G0,IP(Q+Q*x),IP(Q+Q*y)) END END;END;FREEZE;END;

언 골프 버전 :

EXPORT r(n,p)
BEGIN
LOCAL R,A,j,Q,x,y;
  Q:=118.0;
  CASE
    IF p==0 THEN print() END
    IF p==1 THEN RECT();ARC_P(Q,Q,Q) END
  END;
  FOR j FROM 1 TO n DO
    R:=√RANDOM(1.0);
    A:=RANDOM(2*π);
    x:=R*COS(A);
    y:=R*SIN(A);
    CASE
      IF p==0 THEN print("("+x+", "+y+")") END
      IF p==1 THEN PIXON_P(G0,IP(Q+Q*x),IP(Q+Q*y)) END
    END;
  END;
  FREEZE;
END;

터미널 출력 r(10,0):

디스크 터미널 출력의 포인트를 랜덤 화

r(10,1) 위와 같이 디스크에 포인트가 표시됩니다.


2

자바 스크립트, 75 바이트

거부 기반 :

do x=(r=()=>4*Math.random()-2)(),y=r()
while(x*x+y*y>1)
alert(`(${[x,y]})`)

직접 방법 (80 바이트) :

alert(`(${[(z=(m=Math).sqrt((r=m.random)()))*m.sin(p=m.PI*2*r()),z*m.cos(p)]})`)

2

파이썬, 135130 바이트

from random import*
def r():return uniform(-1,1)
p=[]
while not p:
    x,y=r(),r()
    if x**2+y**2<=1:p=x,y
print'(%.2f, %2f)'%p

@ jimmy23013 의 제안 **0.5덕분에 제거되었습니다 (단위 원이기 때문에 (x, y)와 (0, 0) 사이의 제곱 거리가 1 2와 같은지 여부를 확인하고 있습니다 . 같은 것입니다).

또한 괄호를 제거 할 수있었습니다.


나는 당신이 필요하지 않다고 생각합니다 **0.5.
jimmy23013

감사합니다! 제거되었습니다.
JF
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.