구의 임의의 점


31

도전

벡터 길이의 어떠한 입력을 필요하지 않고 출력하는 프로그램이나 함수 작성 1 A의 이론적 균일 임의의 방향.

이것은 x 2 + y 2 + z 2 = 1로 설명되는 구의 임의의 점과 같습니다.

x2+y2+z2=1

그런 분포를 초래

반지름이 1 인 구에서 점의 임의 분포

산출

방정식 x2+y2+z2=1 이 이론적으로 균일 한 랜덤 분포에서 3 개의 부동 소수점 을 정밀한 한계까지 유지합니다.

도전 비고

  • 랜덤 분포는 이론적으로 균일 해야합니다 . 즉, 의사 난수 생성기가 실수실제 RNG로 대체 되는 경우 구에서 점의 균일 한 무작위 분포가 발생합니다.
  • 균일 분포에서 3 개의 난수를 생성하고 정규화하는 것은 유효하지 않습니다. 3 차원 공간의 모서리를 향한 편향이 있습니다.
  • 마찬가지로 균일 분포에서 두 개의 난수를 생성하고이를 구형 좌표로 사용하는 것은 유효하지 않습니다. 구의 극점으로 편향됩니다.
  • 다음을 포함하지만 이에 국한되지 않는 알고리즘으로 적절한 균일 성을 달성 할 수 있습니다.
    • 0 주위 의 정규 (가우스) 분포 에서 3 개의 난수 x , yz 를 생성 하고 정규화합니다. 0
    • 세 난수 생성 x , yz A로부터 균일 한 범위의 분포 (1,1) . l = √로 벡터의 길이를 계산합니다l=x2+y2+z2 . 그런 다음l>1인 경우 벡터를 거부하고 새 숫자 세트를 생성하십시오. 그렇지 않으면l1인 경우 벡터를 정규화하고 결과를 반환합니다.
    • 두 난수 생성 ij (A)로부터 균일 한 범위의 분포 (0,1) 와 구면 좌표로 변환 정도로 같은
      θ=2×π×iϕ=cos1(2×j1)
      x,yz x 로 계산할 수있도록 = cos 1 ( 2 × j 1 )
      x=cos(θ)×sin(ϕ)y=sin(θ)×sin(ϕ)z=cos(ϕ)
  • 답에 사용중인 알고리즘에 대한 간단한 설명을 제공하십시오.
  • MathWorld의 구면 점 따기에 대해 자세히 알아보십시오 .

출력 예

[ 0.72422852 -0.58643067  0.36275628]
[-0.79158628 -0.17595886  0.58517488]
[-0.16428481 -0.90804027  0.38532243]
[ 0.61238768  0.75123833 -0.24621596]
[-0.81111161 -0.46269121  0.35779156]

총론


[-1, 1]에서 3 개의 실수를 균등하게 선택한 다음, 제곱의 합이 1이 아닌 경우 거부하고 반복합니다.
그리미

6
@ 그림 같은 허점을 좋아합니다. 아니요, 이론적으로 어떤 출력의 가능성도 없기 때문에 허용되지 않습니다.
Jitse

@Grimy의 제안은 당신이 언급 한 두 번째 예제 구현과 비슷하지 않습니까? 이 솔루션은 이론적으로 어떤 산출물을 생산할 가능성이 거의 없습니다
Saswat Padhi

2
@SaswatPadhi 아니오, pi/6 ≈ 0.5236출력을 생성 할 가능성 이 있습니다. 그것은 면적 면적 큐브에 새겨진 구체의 영역입니다
Luis Mendo

1
@LuisMendo 알겠습니다. 이 경우 확률은 ~ 0.5입니다. Grimy의 제안에 따르면 ~ 0입니다.
Saswat Padhi

답변:



24

R , 23 바이트

x=rnorm(3)
x/(x%*%x)^.5

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

N(0,1) 분포 의 3 가지 실현을 생성 하고 결과 벡터를 정규화합니다.

1000 개의 실현 도표 :

enter image description here


2
3 축이 정상적으로 분포되어있는 것을 정당화 할 수 있습니까? (보이지 않음)
Jeffrey는

4
@Jeffrey 확률 / 통계량에서 잘 알려져 있습니다. 그러나 2D에 대한 증거 (정확하게 3 차원으로 확장 됨)는 대략 이며 독립적입니다. 그런 다음 f X ( x ) = K e - 1X,YN(0,1)fY(y)=Ke-1fX(x)=Ke12x2이므로 독립성fxY(x,y)=K2e-1fY(y)=Ke12y2Z=(X,Y), 그것의 분포 것이 분명하므로, Z는의 크기에만 의존Z, 따라서 방향이 균일하게 분포되어있다. fXY(x,y)=K2e12(x2+y2)=fZ(z)=K2e12z2z=(x,y)zz
주세페

1
따라서 정규 분포는 우리에게 균일하게 분포 된 점을 제공합니다 주위에 원 및 크기로 나누어하면 포인트가 거짓말 보장
주세페

23

x86-64 기계 코드 -63 62 55 49 바이트

6A 4F                push        4Fh  
68 00 00 80 3F       push        3F800000h  
C4 E2 79 18 4C 24 05 vbroadcastss xmm1,dword ptr [rsp+5]  
rand:
0F C7 F0             rdrand      eax  
73 FB                jnc         rand  
66 0F 6E C0          movd        xmm0,eax  
greaterThanOne:
66 0F 38 DC C0       aesenc      xmm0,xmm0  
0F 5B C0             cvtdq2ps    xmm0,xmm0  
0F 5E C1             divps       xmm0,xmm1  
C4 E3 79 40 D0 7F    vdpps       xmm2,xmm0,xmm0,7Fh  
0F 2F 14 24          comiss      xmm2,dword ptr [rsp]  
75 E9                jne         greaterThanOne
58                   pop         rax  
58                   pop         rax  
C3                   ret  

수정 된 두 번째 알고리즘을 사용합니다. 의 벡터를 반환[x, y, z, 0]xmm0의 .

설명:

push 4Fh
push 3f800000h

스택에 부동 소수점으로 1 및 2 ^ 31의 값을 푸시합니다. 부호 확장으로 인해 데이터가 겹치므로 몇 바이트가 절약됩니다.

vbroadcastss xmm1,dword ptr [rsp+5] 2 ^ 31의 값을 xmm1의 4 개 위치에로드합니다.

rdrand      eax  
jnc         rand  
movd        xmm0,eax

임의의 32 비트 정수를 생성하여 xmm0의 맨 아래로로드합니다.

aesenc      xmm0,xmm0  
cvtdq2ps    xmm0,xmm0  
divps       xmm0,xmm1 

임의의 32 비트 정수를 생성하고이를 부동 (부호)으로 변환 한 후 2 ^ 31로 나누어 -1과 1 사이의 숫자를 얻습니다.

vdpps xmm2,xmm0,xmm0,7Fh내적을 사용하여 하단 3 개의 부동 소수점의 제곱을 추가하고 상단 부동을 마스킹합니다. 이것은 길이를 제공합니다

comiss      xmm2,dword ptr [rsp]  
jne          rand+9h (07FF7A1DE1C9Eh)

길이의 제곱을 1과 비교하고 값이 1이 아닌 경우 값을 거부합니다. 길이의 제곱이 1이면 길이도 1입니다. 즉, 벡터가 이미 정규화되어 있고 제곱근을 나누고 나눕니다.

pop         rax  
pop         rax 

스택을 복원하십시오.

ret xmm0의 값을 반환

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


7
+1 aesenc128 개의 "무작위"비트를 생성하는 것은 매우 아름답습니다.
DocMax

13

파이썬 2 , 86 바이트

from random import*;R=random
z=R()*2-1
a=(1-z*z)**.5*1j**(4*R())
print a.real,a.imag,z

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

-1에서 1까지의 z 좌표를 균일하게 생성합니다. 그러면 x 및 y 좌표가 반경 원에서 균일하게 샘플링 (1-z*z)**.5됩니다.

구면 분포가 z 좌표에서 (그리고 모든 좌표에서) 인자로 균일하다는 것은 분명하지 않을 수 있습니다. 이것은 차원 3에 특별한 것입니다. 이 증거를보십시오 입니다. 구의 수평 슬라이스의 표면적이 높이에 비례한다는 를 . 적도 부근의 조각은 반지름이 더 크지 만 기둥 근처의 조각은 안쪽으로 더 많은 제목이 붙어 있으며이 두 가지 효과가 정확하게 취소됩니다.

이 원에 임의의 각도를 생성하기 위해 가상 단위 1j를 0에서 4 사이의 균일 한 임의의 제곱으로 올립니다. 이로 인해 삼각 함수, pi 또는 e가 필요하지 않으며 가져 오기가 필요합니다. 그런 다음 실제 허수 부분을 추출합니다. 두 좌표에 대해 복소수를 출력 할 수 있다면 마지막 줄은 그냥됩니다 print a,z.


86 바이트

from random import*
a,b,c=map(gauss,[0]*3,[1]*3)
R=(a*a+b*b+c*c)**.5
print a/R,b/R,c/R

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

3 개의 법선을 생성하고 결과를 스케일링합니다.


numpy, 57 바이트의 Python 2

from numpy import*
a=random.randn(3)
print a/sum(a*a)**.5

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

sum(a*a)**.5보다 짧습니다 linalg.norm(a). 우리는 또한 dot(a,a)같은 길이로 할 수 있습니다 sum(a*a). Python 3에서는 a@anew 연산자 를 사용하여 단축 할 수 있습니다 @.


1
I like your first approach. I'm having trouble understanding how a bias towards the equator is avoided if z, from a uniform distribution, is left unmodified.
Jitse

2
@Jitse 구면 분포는 각 좌표에서 균일합니다. 이것은 차원 3에 특별한 것입니다. 예를 들어 구 조각의 표면적이 높이에 비례한다는 증거 를 참조하십시오 . 이것이 적도에 편향되어 있다는 직관과 관련하여 적도 부근의 조각은 반지름이 더 크지 만 극 근처의 조각은 안쪽으로 더 많은 제목을 지정하여 더 많은 영역을 제공 하며이 두 가지 효과가 정확하게 취소됩니다.
xnor

Very nice! Thanks for the clarification and the reference.
Jitse

@Jitse 감사합니다, 나는 그것을 몸에 추가했습니다. 그래도 나는 단지 긍정적으로 샘플링한다는 것을 깨달았고 z몇 바이트 동안 고정했습니다.
xnor

1
@Jitse 실제로, 구의 표면적은 밀폐 실린더의 측면 적과 동일합니다!
Neil

13

옥타브 , 40 33 22 바이트

We sample form a 3d standard normal distribution and normalize the vector:

(x=randn(1,3))/norm(x)

Try it online!


For Octave only (i.e. not MATLAB), you can save a byte with this
Tom Carpenter

1
@TomCarpenter Thanks! In this case as it is just one expression we can even omit the disp:)
flawr

10

Unity C#, 34 bytes

f=>UnityEngine.Random.onUnitSphere

Unity has a builtin for unit sphere random values, so I thought I'd post it.


Good use of a built in +1, You could just submit a function to be a bit shorter f=>Random.onUnitSphere
LiefdeWen

@LiefdeW 람다에 대해 알고 있었지만, 그것이 (Code Golf에 대한 타당성 측면에서) 그것이 fType을 선언하지 않기 때문에 충분한 지 확신하지 못했습니다 . 사용 var하는 것은 메소드 내부에서만 작동하며 System.Func<Vector3>더 길었습니다.
Draco18s

1
codegolf에서 함수를 반환하는 것은 완벽하며 선언을 계산할 필요가 없으며 동적 매개 변수를 사용하여 은밀한 작업을 수행 할 수 있습니다. 마지막 세미콜론도 계산하지 않습니다. 그러나 추가 한 모든 구문을 사용하여 계산합니다. 따라서 바이트 수에는 using을 포함해야합니다. 그러나 f=>Random.onUnitSphere완벽하게 유효한 제출입니다
LiefdeWen

@LiefdeWen 그래, 나는 그 선언이 어떻게 처리되는지 확실하지 않았고 실제로 "메타 검색"에 대해 느끼지 않았다.
Draco18s

f=>UnityEngine.Random.onUnitSphere 당신을 저장합니다 using
Orace

6

MATL, 10 bytes

1&3Xrt2&|/

Try it online!

Explanation

This uses the first approach described in the challenge.

1&3Xr  % Generate a 1×3 vector of i.i.d standard Gaussian variables
t      % Duplicate
2&|    % Compute the 2-norm
/      % Divide, element-wise. Implicitly display

6

루비 , 34 50 49 바이트

->{[z=rand*2-1]+((1-z*z)**0.5*1i**(rand*4)).rect}

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

3 개의 숫자 배열을 반환합니다 [z,y,x].

xy상승에 의해 발생되는 i임의의 전력 10-0 내지 4.이 복소수 필요에 따라 적절하게 스케일링 될 (-1의 제곱근) z피타고라스 정리에 따른 값 :(x**2 + y**2) + z**2 = 1.

z사이 -1과 1 비록되지 즉시 (DA) / 구를 통해 슬라이스 DZ 상수 명백 균일 분포 수가 단순히 (제 1 생성되는) 좌표 (동일 반경의 원으로의 둘레와 동일 전체 구).

이것은 매우 미적분법과 같은 방식으로 묘사 한 아르키메데스에 의해 발견되었으며, 아르키메데스 모자-박스 정리로 알려져 있습니다. https://brilliant.org/wiki/surface-area-sphere/를 참조 하십시오

xnor의 답변에 대한 의견에서 또 다른 참조. 놀랍도록 간단한 공식을 설명하는 놀랍도록 짧은 URL : http://mathworld.wolfram.com/Zone.html


@Jitse 높은 값의 z에서 x와 y를 축소하는 것을 잊었습니다. 사실상 점들이 실린더를 정의했습니다. 이제 수정되었지만 많은 바이트가 필요합니다! 출력이 복소수로 표현 될 수 있다면 몇 가지를 절약 할 수 있습니다. 괜찮게 [z, x+yi]말하지 않으면 그대로 둡니다.
레벨 리버 세인트

좋아 보인다! 이 방법이 정말 마음에 듭니다. 일관성을 유지하기 위해 필요한 출력은 3 개의 플로트이므로 다음과 같이 두는 것이 좋습니다.
Jitse

z*z대신에 사용 하지 z**2않겠습니까?
가치 잉크

@ValueInk 그래, 고맙습니다 z*z. 지금 편집했습니다. 내가 할 수있는 다른 일은 대체 할 수 rand*4있는 것과 같 z*99거나 x*9E9(구체적으로 가능한 값을 매우 미세한 나선형으로 제한) 무작위의 품질을 떨어 뜨린다 고 생각합니다.
Level River St

4

05AB1E , 23 22 바이트

[тε5°x<Ýs/<Ω}DnOtDî#}/

두 번째 알고리즘을 구현합니다.

온라인으로 시도 하거나 더 많은 무작위 출력을 얻으십시오 .

설명:

참고 : 05AB1E에는 범위의 임의의 10 진수 값을 얻을 수있는 내장 기능이 없습니다 [0,1). 대신, 나는 증분으로 목록을 만듭니다0.00001해당 목록에서 임의의 값을 선택하십시오. 이 증분은0.000000001코드 에서 5~ 9를 변경하여 (느리게 진행되지만).

[            # Start an infinite loop:
 тε          #  Push 100, and map (basically, create a list with 3 values):
   5°        #   Push 100,000 (10**5)
     x       #   Double it to 200,000 (without popping)
      <      #   Decrease it by 1 to 199,999
       Ý     #   Create a list in the range [0, 199,999]
        s/   #   Swap to get 100,000 again, and divide each value in the list by this
          <  #   And then decrease by 1 to change the range [0,2) to [-1,1)
           Ω #   And pop and push a random value from this list
  }          #  After the map, we have our three random values
   D         #   Duplicate this list
    n        #   Square each inner value
     O       #   Take the sum of these squares
      t      #   Take the square-root of that
       D     #   Duplicate that as well
        î    #   Ceil it, and if it's now exactly 1:
         #   #    Stop the infinite loop
}/           # After the infinite loop: normalize by dividing
             # (after which the result is output implicitly)

1
사용 l<1 똑같이 유효합니다 1. 에 대한 유일한 기준엑스 그게 0<엑스1. 당신은뿐만 아니라 벡터를 받아 들일 수 있습니다<0.5바이트를 절약 할 수 있다면 작거나 같은 값1 편견을 제거합니다.
Jitse

@Jitse Ok, Java 및 05AB1E 답변 모두에서 정규화를 구현했습니다. 나는 모든 것이 지금 정확하기를 바랍니다.
케빈 크루이 센

@Jitse 실제로 확인하여 바이트를 저장했습니다. V1 같이 V==1, 대신에 V<1. 그러나 명확하게 해주셔서 감사합니다.0<엑스1 요구 사항이며 엄격한 것은 아닙니다. 요구 사항 그것이있는 한 1.
Kevin Cruijssen

4

TI-BASIC, 15 바이트 *

:randNorm(0,1,3
:Ans/√(sum(Ans²

알고리즘을 사용하여 "3 개의 정규 분포 값을 생성하고 해당 벡터를 정규화"합니다.

표현식을 사용하여 프로그램을 종료하면 프로그램이 종료 된 후 홈 화면에 결과가 자동으로 인쇄되므로 결과가 생성 및 블랙홀되지 않고 실제로 표시됩니다.

* randNorm(A는 2 바이트 토큰 , 나머지는 1 바이트 토큰 . 나는 :14 바이트가 아닌 초기 (피할 수없는)를 세었다 . 한글자 이름의 프로그램으로 저장하면 24 바이트의 메모리가 필요하며 여기에는 9 바이트의 파일 시스템 오버 헤드가 포함됩니다.


3

자바 스크립트 (ES7),  77 76  75 바이트

다음을 사용하여 3 알고리즘을 구현합니다.(ϕ)=(코사인1())=12.

with(Math)f=_=>[z=2*(r=random)()-1,cos(t=2*PI*r(q=(1-z*z)**.5))*q,sin(t)*q]

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

댓글

with(Math)                       // use Math
f = _ =>                         //
  [ z = 2 * (r = random)() - 1,  // z = 2 * j - 1
    cos(                         //
      t =                        // θ =
        2 * PI *                 //   2 * π * i
        r(q = (1 - z * z) ** .5) // q = sin(ɸ) = sin(arccos(z)) = √(1 - z²)
                                 // NB: it is safe to compute q here because
                                 //     Math.random ignores its parameter(s)
    ) * q,                       // x = cos(θ) * sin(ɸ)
    sin(t) * q                   // y = sin(θ) * sin(ɸ)
  ]                              //

자바 스크립트 (ES6), 79 바이트

번째 알고리즘을 구현합니다 .

f=_=>(n=Math.hypot(...v=[0,0,0].map(_=>Math.random()*2-1)))>1?f():v.map(x=>x/n)

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

댓글

f = _ =>                         // f is a recursive function taking no parameter
  ( n = Math.hypot(...           // n is the Euclidean norm of
      v =                        // the vector v consisting of:
        [0, 0, 0].map(_ =>       //
          Math.random() * 2 - 1  //   3 uniform random values in [-1, 1]
        )                        //
  )) > 1 ?                       // if n is greater than 1:
    f()                          //   try again until it's not
  :                              // else:
    v.map(x => x / n)            //   return the normalized vector

3

26 바이트 처리

전체 프로그램

print(PVector.random3D());

이것은 https://github.com/processing/processing/blob/master/core/src/processing/core/PVector.java 구현입니다.

  static public PVector random3D(PVector target, PApplet parent) {
    float angle;
    float vz;
    if (parent == null) {
      angle = (float) (Math.random()*Math.PI*2);
      vz    = (float) (Math.random()*2-1);
    } else {
      angle = parent.random(PConstants.TWO_PI);
      vz    = parent.random(-1,1);
    }
    float vx = (float) (Math.sqrt(1-vz*vz)*Math.cos(angle));
    float vy = (float) (Math.sqrt(1-vz*vz)*Math.sin(angle));
    if (target == null) {
      target = new PVector(vx, vy, vz);
      //target.normalize(); // Should be unnecessary
    } else {
      target.set(vx,vy,vz);
    }
    return target;
  }

2
구현이 바이트 수의 일부가 아님을 더 명확하게하고 싶을 수도 있습니다. 나는 처음 읽을 때 그것을 놓친 다음 두 번 테이크를했다.
Level River St

나는 구현이 본질적으로 나와 같은 접근법을 사용한다는 것을 좋아한다.
Level River St

2

파이썬 2 , 86 바이트

from random import*
x,y,z=map(gauss,[0]*3,[1]*3);l=(x*x+y*y+z*z)**.5
print x/l,y/l,z/l

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

첫 번째 알고리즘을 구현합니다.


파이썬 2 , 107103 바이트

from random import*
l=2
while l>1:x,y,z=map(uniform,[-1]*3,[1]*3);l=(x*x+y*y+z*z)**.5
print x/l,y/l,z/l

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

두 번째 알고리즘을 구현합니다.


2
@RobinRyder이 구현은 초기 길이가 1보다 큰 벡터를 거부하며, 이는 챌린지에 지정된대로 유효합니다.
Jitse

@Jitse 맞습니다. 죄송합니다. 코드를 잘못 읽었습니다.
로빈 라이더

2

하스켈 , 125 123 119 118 바이트

import System.Random
f=mapM(\_->randomRIO(-1,1))"lol">>= \a->last$f:[pure$(/n)<$>a|n<-[sqrt.sum$map(^2)a::Double],n<1]

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

3 개의 유니폼 랜덤 및 거부 샘플링을 수행합니다.


랜덤이 (-1,1) 대신 분포 (0,1)에서 온 것으로 보이므로 구의 1/8 만 커버됩니다.
Jitse

@Jitse gotcha, 감사합니다.
앙스

2

자바 스크립트, 95 바이트

f=(a=[x,y,z]=[0,0,0].map(e=>Math.random()*2-1))=>(s=Math.sqrt(x*x+y*y+z*z))>1?f():a.map(e=>e/s)

당신은 하지 않습니다 필요 하지 입력 a.


와우, 나는 그것을 완전히 놓쳤다. 결정된.
Naruyoko

2

Julia 1.0 , 24 바이트

x=randn(3)
x/hypot(x...)

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

표준 편차 1을 사용하여 0 주위의 정규 분포에서 가져온 3 개의 값으로 구성된 벡터를 그립니다.


randn(), 몇 가지 빠른 테스트에서 필요한 범위에 속하지 않는 것 같습니다. 또한 여기에는 hypot()값 을 반환하는 검사가 포함되어 있지 않으므로 >1거부해야합니다.
Shaggy

3
@Shaggy 그것은 randn균일 한 (0,1) 분포가 아닌 표준 정규 분포에서 시뮬레이트되는 것처럼 보이기 때문에이 접근법은 R과 동일합니다.
주세페

@ 주세페 맞아!
user3263164

@ 주세페, 나는이 도전의 배후에있는 수학을 제대로 이해하지 못할 것이라고 생각하지만, 내가 올바르게 이해하고 있다면, 수레 중 하나가 경계 바깥 [-1,1)에 있다면 빗변은 어느 >1것을 상쇄 할 것인가? 내 솔루션의 삼항이 필요한지 궁금해합니다.
Shaggy

@Shaggy no, normal / Gaussian 분포에는 유니폼에없는 몇 가지 속성 (특히 회전 불변) 이 있습니다.
Giuseppe

2

MathGolf , 21 19 18 바이트

{╘3Ƀ∞(ß_²Σ√_1>}▲/

두 번째 알고리즘의 구현.

온라인으로 시도 하거나 동시에 더 많은 출력을 보십시오 .

설명:

{              }▲   # Do-while true by popping the value:
                   #  Discard everything on the stack to clean up previous iterations
  3É                #  Loop 3 times, executing the following three operations:
    ƒ               #   Push a random value in the range [0,1]
                   #   Double it to make the range [0,2]
      (             #   Decrease it by 1 to make the range [-1,1]
       ß            #  Wrap these three values into a list
        _           #  Duplicate the list of random values
         ²          #  Square each value in the list
          Σ         #  Sum them
                   #  And take the square-root of that
            _       #  Duplicate it as well
             1>     #  And check if it's larger than 1
                 /  # After the do-while, divide to normalize
                    # (after which the entire stack joined together is output implicitly,
                    #  which is why we need the `╘` to cleanup after every iteration)

2

자바 8 ( @Arnauld 의 변형 알고리즘 3) 131 126 119 111 109 바이트

v->{double k=2*M.random()-1,t=M.sqrt(1-k*k),r[]={k,M.cos(k=2*M.PI*M.random())*t,M.sin(k)*t};return r;}

@Arnauld 의 JavaScript 답변 포트이므로 그를 투표 하십시오! @ OlivierGrégoire
덕분에 -2 바이트 .

이것은 다음과 같이 구현됩니다.

케이=[1,1)
=1케이2
=2π×([0,1))
엑스,와이,={케이,코사인()×,()×}

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

이전 3 알고리즘의 구현 ( 131 126 119 바이트)

Math M;v->{double k=2*M.random()-1,t=2*M.PI*M.random();return k+","+M.cos(t)*M.sin(k=M.acos(k))+","+M.sin(t)*M.sin(k);}

다음과 같이 구현됩니다.

케이=[1,1)
=2π×([0,1))
엑스,와이,={케이,코사인()×(아르 코스(케이)),()×(아르 코스(케이))}

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

설명:

Math M;                         // Math on class-level to use for static calls to save bytes
v->{                            // Method with empty unused parameter & double-array return
  double k=2*M.random()-1,      //  Get a random value in the range [-1,1)
         t=M.sqrt(1-k*k),       //  Calculate the square-root of 1-k^2
    r[]={                       //  Create the result-array, containing:
         k,                     //   X: the random value `k`
         M.cos(k=2*M.PI         //   Y: first change `k` to TAU (2*PI)
                     *M.random()//       multiplied by a random [0,1) value
                )               //      Take the cosine of that
                 *t,            //      and multiply it by `t`
         M.sin(k)               //   Z: Also take the sine of the new `k` (TAU * random)
                  *t};          //      And multiply it by `t` as well
  return r;}                    //  Return this array as result

Java 8 (2 차 알고리즘), 153143 바이트

v->{double x=2,y=2,z=2,l;for(;(l=Math.sqrt(x*x+y*y+z*z))>1;y=m(),z=m())x=m();return x/l+","+y/l+","+z/l;};double m(){return Math.random()*2-1;}

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

두 번째 알고리즘 :

v->{                              // Method with empty unused parameter & String return-type
  double x=2,y=2,z=2,l;           //  Start results a,b,c all at 2
  for(;(l=Math.sqrt(x*x+y*y+z*z)) //  Loop as long as the hypotenuse of x,y,z
       >1;                        //  is larger than 1
    y=m(),z=m())x=m();            //   Calculate a new x, y, and z
  return x/l+","+y/l+","+z/l;}    //  And return the normalized x,y,z as result
double m(){                       // Separated method to reduce bytes, which will:
  return Math.random()*2-1;}      //  Return a random value in the range [-1,1)

sqrt(1-k*k)실제로 사용하면 JS보다 Java에서 더 많은 바이트가 절약됩니다. :)
Arnauld

@Arnauld Yep. 3x M.sin, 1x M.cos및 1x 대신 M.acos, 접근 방식은 2x M.sin및 1x를 사용하는데 M.sqrt, 이는 추가로 저장된 바이트가 주로 나오는 곳입니다. :)
Kevin Cruijssen

108 바이트 수정 된 2 차 알고리즘을 사용합니다. 여기서 s == 1 인 값만 허용합니다 (s <= 1 대신 정규화). 때로는 답변을 제공하지만 시간 초과로 인한 것이 아닙니다. 편집 : 아차, 나는 Math.sqrt에 결과를 잊었다
올리비에 그레고르

실제로 sqrt (1) == 1이므로 sqrt가 필요 없습니다. 그래서 저는 골프 제안을지지합니다.
Olivier Grégoire

1
109 바이트 ( 바이트 수를 double[]변경하지 않기 때문에 대신 문자열 출력을 사용할 수 있습니다 .)
Olivier Grégoire

1

Japt , 20 바이트

포트 Arnauld의 구현 2 알고리즘.

MhV=3ÆMrJ1
>1?ß:V®/U

그것을 테스트

MhV=3ÆMrJ1
Mh             :Get the hypotenuse of
  V=           :  Assign to V
    3Æ         :  Map the range [0,3)
      Mr       :    Random float
        J1     :    In range [-1,1)
>1?ß:V®/U      :Assign result to U
>1?            :If U is greater than 1
   ß           :  Run the programme again
    :V®/U      :Else map V, dividing all elements by U

1

Pyth , 24 바이트

W<1Ks^R2JmtO2.0 3;cR@K2J

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

알고리즘 # 2 사용

W                         # while 
 <1                       #   1 < 
   Ks                     #       K := sum(
     ^R2                  #               map(lambda x:x**2,
        Jm      3         #                    J := map(                            , range(3))
          tO2.0           #                             lambda x: random(0, 2.0) - 1           )):
                 ;        #   pass
                   R   J  # [return] map(lambda x:            , J)
                  c @K2   #                        x / sqrt(K)

1

OCaml , 110 99 95 바이트

(fun f a c s->let t,p=f 4.*.a 0.,a(f 2.-.1.)in[c t*.s p;s t*.s p;c p])Random.float acos cos sin

편집 : 인라인하여 일부 바이트를 줄였습니다. 나는j, 첫 번째를 let ... in로 바꾸고 fun연산자의 연관성을 활용하여 일부 parens를 피하십시오 ().

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


독창적 인 솔루션 :

Random.(let a,c,s,i,j=acos,cos,sin,float 4.,float 2. in let t,p=i*.(a 0.),a (j-.1.) in[c t*.s p;s t*.s p;c p])

먼저 다음을 정의합니다.

에이=아르 코스,  기음=코사인,  에스=나는unif(0,4),  junif(0,2)

OCaml의 Random.float기능 에는 범위가 포함됩니다. 그때,

=나는에이(0)=나는π2,  =에이(j1)

이것은 세 번째 예제 구현과 매우 유사합니다. ϕ=θ=) 내가 고르는 것을 제외하고 나는j 나중에 (2로) 곱셈을 피하기 위해 더 큰 간격으로.


1
나는이 언어에 아주 익숙하지 해요,하지만 당신이 사이의 임의의 수레 사용하는 것 같습니다 01직접 구형 좌표로합니다. 챌린지 비고 3과 4에서 볼 수 있듯이 구의 극점을 향한 치우침이 발생하기 때문에 이는 잘못된 것입니다.
비고

고맙습니다! 완전히 놓쳤다. 버그를 수정하고 내 답변을 업데이트했습니다
Saswat Padhi

1
좋아 보인다! 아주 좋은 첫 번째 답변!
Jitse

감사합니다 :) 100 바이트 미만으로 줄일 수있었습니다!
Saswat Padhi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.