Bir küredeki rastgele nokta


31

Meydan okuma

Girişsiz olan ve uzunluğu 1 olan bir vektörü teorik olarak düzgün bir rastgele yönde çıkaran bir program veya işlev yazın .

Bu, açıklanan küre üzerindeki rastgele bir noktaya eşdeğerdir.

x2+y2+z2=1

böyle bir dağıtım sonuçlandı

Yarıçap 1 olan bir küre üzerindeki noktaların rastgele dağılımı.

Çıktı

denkleminin hassasiyet limitlerine sadık kaldığı teorik olarak düzgün rastgele dağılımdan üç değişken .x2+y2+z2=1

Meydan açıklamalar

  • Rastgele dağılımın teorik olarak tek tip olması gerekir . Yani, eğer sözde rasgele sayı üreteci, gerçek sayılardan gerçek bir RNG ile değiştirilecekse , küre üzerinde noktaların düzgün rastgele dağılmasıyla sonuçlanacaktır.
  • Düzgün bir dağılımdan üç rasgele sayı üretmek ve bunları normalleştirmek geçersizdir: üç boyutlu boşluğun köşelerine doğru bir önyargı olacaktır.
  • Benzer şekilde, düzgün bir dağılımdan iki rasgele sayı üretmek ve bunları küresel koordinatlar olarak kullanmak geçersizdir: kürenin kutuplarına doğru bir önyargı olacaktır.
  • Aşağıdakileri içeren ancak bunlarla sınırlı olmayan algoritmalar ile uygun tek biçimlilik elde edilebilir:
    • A'dan üç rasgele sayı , ve oluşturunxyz0 , normal çevresinde (Gauss) dağıtım ve normalize. 0
    • Oluşturmak üç rasgele sayılar , ve , bir gelen muntazam aralığında dağılımı . Vektörün uzunluğunu hesaplayın . O zaman, eğerxyz( - 1 , 1 ) l = (1,1)l=x2+y2+z2l>1 ise vektörü reddedin ve yeni bir sayı kümesi oluşturun. Aksi takdirde, ise vektörü normalleştirir ve sonucu döndürür. l1
    • İki rasgele sayı oluşturmak ve bir gelen muntazam aralığında dağılımı ve bunu gibi küresel koordinatlar dönüştürmek: böylece , veij( 0 , 1 ) θ(0,1)
      θ=2×π×iϕ=cos1(2×j1)
      xyz ile hesaplanabilir
      x=cos(θ)×sin(ϕ)y=sin(θ)×sin(ϕ)z=cos(ϕ)
  • Cevabınıza, kullandığınız algoritmanın kısa bir açıklamasını sağlayın.
  • Küre noktası toplama hakkında daha fazla bilgi edinin MathWorld'de seçimi hakkında .

Çıktı örnekleri

[ 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]

Genel açıklamalar


[1, 1] 'de 3 tane üniform bir seçim yapmak, karelerinin toplamı 1 değilse bunları reddetmek (ve tekrarlamak) olur mu?
Grimmy

6
@Grimy Bu kaçıktan hoşlanıyorum. Hayır, buna izin verilmiyor, çünkü teorik olarak sıfır herhangi bir çıktının şansı var.
Jitse

@ Grimy'nin önerisi, bahsettiğiniz ikinci örnek uygulamaya benzemiyor mu? Bu çözüm ayrıca teorik olarak herhangi bir çıktı üretme şansına sahip değil
Saswat Padhi

2
@SwatwatPadhi Hayır, bu pi/6 ≈ 0.5236bir çıktı üretme şansına sahip. Bu, birim alan küpünde yazılı kürenin alanı
Luis Mendo

1
@ LouisMendo Görüyorum, doğru. Bahsettiğin gibi, bu durumda olasılık ~ 0,5'tir. Grimy'nin teklifi için, bu ~ 0.
Saswat Padhi

Yanıtlar:



24

R , 23 bayt

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

Çevrimiçi deneyin!

N(0,1) dağılımının 3 gerçekleşmesini oluşturur ve elde edilen vektörü normalleştirir.

1000 gerçekleştirmenin arsa:

görüntü tanımını buraya girin


2
Normal olarak dağıtılan 3 ekseni küre üzerinde düzgün dağılımla sonuçlandırabilir misiniz? (
Jeffrey, Monica

4
@Jeffrey Olasılık / istatistikte oldukça iyi bilinmektedir; ancak 2B'nin kanıtı (düzgün şekilde 3 boyuta uzanır) yaklaşık olarak: ve bağımsız olsun. Sonra f X ( x ) = K e - 1X,Y~N-(0,1)vefY(y)=Ke-1fX(x)=Ke-12x2çok bağımsızlık ile,fX,Y(x,y)=K2E-1fY(y)=Ke-12y2buradaz=(x,y), bu nedenle,zdağılımınınyalnızcaz'ninbüyüklüğüne bağlıolduğu ve dolayısıyla yönün eşit şekilde dağıldığı açıktır. fXY(x,y)=K2e-12(x2+y2)=fZ(z)=K2e-12z2z=(x,y)zz
Giuseppe

1
Yani, normal dağılım bize düzgün yayılı puan verir etrafında çember ve büyüklük bölerek noktaları yalan sağlamaktadır üzerinde daire
Giuseppe

23

x86-64 Makine Kodu - 63 62 55 49 bayt

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  

Değiştirilen ikinci algoritmayı kullanır. [x, y, z, 0]Xmm0 içindeki vektörü döndürür .

Açıklama:

push 4Fh
push 3f800000h

1 ve 2 ^ 31 değerini yığına kayan nokta olarak iter. Veri işareti uzantısı nedeniyle çakışıyor ve birkaç bayt kaydediliyor.

vbroadcastss xmm1,dword ptr [rsp+5] 2 ^ 31 için değeri xmm1'in 4 konumuna yükler.

rdrand      eax  
jnc         rand  
movd        xmm0,eax

Rasgele 32 bit tam sayı oluşturur ve xmm0'ın altına yükler.

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

Rasgele bir 32 bit tam sayı üretir, onu yüzdürmeye (işaretli) dönüştür ve -1 ile 1 arasında sayı elde etmek için 2 ^ 31 ile böl.

vdpps xmm2,xmm0,xmm0,7Fhüst yüzgecin maskelenerek kendi başına bir nokta ürünü kullanarak alt 3 yüzgecinin karelerini ekler. Bu uzunluğu verir

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

Kare uzunluğu 1 ile karşılaştırır ve 1'e eşit değilse değerleri reddeder. Kare uzunluğu bir ise, uzunluk da birdir. Bu, vektörün normalize olduğu ve karekök kaydettiği ve böldüğü anlamına gelir.

pop         rax  
pop         rax 

Yığını geri yükle.

ret xmm0 içindeki değeri döndürür

Çevrimiçi deneyin .


7
+1 aesenc128 "rasgele" bit üretmek için kullanmak çok güzel.
DocMax

13

Python 2,86 bayt

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

Çevrimiçi deneyin!

Z koordinatını 1 ile 1 arasında eşit olarak oluşturur. Sonra x ve y koordinatları yarıçap dairesinde eşit olarak örneklenir (1-z*z)**.5.

Küresel dağılımın z koordinatı üzerinde tekdüze bir faktörde olduğu açık olmayabilir (ve böylece her koordinat üzerinde). Bu, boyut 3 için özel bir şeydir. Bu kanıtı , bir kürenin yatay bir diliminin yüzey alanının yüksekliğiyle orantılı olduğunu görün. Ekvatorun yanındaki dilimler daha büyük bir yarıçapa sahip olsalar da, direğe yakın dilimler daha fazla içe doğru başlıklandırılır ve bu iki efekt tam olarak iptal edilir.

Bu dairede rastgele bir açı oluşturmak için, hayali birimi 1j0 ile 4 arasında düzgün rastgele bir güce yükseltiriz; bu da bizi herhangi bir içe aktarmaya ihtiyaç duyan trig işlevlerine, pi veya e'ye ihtiyaç duymadan kurtarır. Ardından asıl hayali kısmı çıkarıyoruz. İki koordinat için karmaşık bir sayı çıkarabilirsek, son satır tam olabilir print a,z.


86 bayt

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

Çevrimiçi deneyin!

Üç normal üretir ve sonucu ölçeklendirir.


Numune ile Python 2 , 57 bayt

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

Çevrimiçi deneyin!

sum(a*a)**.5daha kısa linalg.norm(a). dot(a,a)Aynı uzunluk için de yapabiliriz sum(a*a). Python 3'te bu a@a, yeni operatörün kullanılmasıyla kısaltılabilir @.


1
İlk yaklaşımını beğendim. zEşit bir dağılımdan değiştirilmemiş olarak bırakılırsa , ekvatora karşı bir önyargının nasıl önlendiğini anlamakta güçlük çekiyorum .
Jitse,

2
@Jitse Küresel dağılım, her bir koordinat üzerinde tekdüze faktördedir. Bu, boyut 3 için özel bir şeydir. Örneğin , bir kürenin bir diliminin yüzey alanının yüksekliğiyle orantılı olduğunu kanıtlayın . Bunun ekvator için önyargılı olduğu sezgisine gelince, ekvatorun yanındaki dilimlerin daha büyük bir yarıçapa sahip olmasına rağmen, direğe yakın olanların daha fazla alan veren içe doğru daha fazla başlıklı olduğunu ve bu iki etkinin tamamen iptal edildiğini belirtir.
xnor

Çok hoş! Açıklama ve referans için teşekkür ederiz.
Jitse,

@Jitse Teşekkürler, vücuda ekledim. Sadece pozitif zolsa örnekleme yaptığımı fark ettim ve bunu birkaç bayt için düzelttim.
xnor

1
@Jitse Gerçekten, bir kürenin yüzey alanı, muhafaza silindirinin yanal yüzey alanına eşittir!
Neil

13

Octave , 40 33 22 bayt

3d standart bir normal dağılım oluşturur ve vektörü normalleştiririz:

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

Çevrimiçi deneyin!


Octave sadece (yani değil MATLAB) için, bir bayt kaydedebilirsiniz bu
Tom Carpenter

1
@ TomCarpenter Teşekkürler! Bu durumda biz bile atlayabilirsiniz sadece bir ifadesidir olarak disp:)
flawr

10

Birlik C # , 34 bayt

f=>UnityEngine.Random.onUnitSphere

Birliğin birim küre rasgele değerleri için bir yerleşimi vardır, bu yüzden göndermeyi düşündüm.


f=>Random.onUnitSphere
Yerleşik

@LiefdeWen lambdas hakkında bir şey biliyordum, yeteri kadar olup olmadığından emin değildim (Code Golf’un geçerliliği açısından) çünkü bu türün türünü açıklamıyordu f; varsadece bir metodun içindeki eserleri kullanmak ve System.Func<Vector3>daha uzundur.
Draco18,

1
Kod işlevinde bir işlevi döndürmek tamamen iyidir ve bildirimi saymak zorunda kalmazsınız; bu da sinsi şeyleri dinamik parametrelerle yapabileceğiniz anlamına gelir. Ayrıca son yarı-kolonu saymazsınız. Ancak, eklediğiniz ifadeleri kullanarak hepsini sayıyorsunuz. bu yüzden bayt sayınızın kullanımını içermesi gerekir. Ama f=>Random.onUnitSpheremükemmel bir şekilde geçerli bir sunum
LiefdeWen

@LiefdeWen Evet, bildirimin nasıl işlendiğinden emin değildim ve gerçekten "meta arama" yı istemiyordu.
Draco18,

f=>UnityEngine.Random.onUnitSpheresizi kurtarıyorusing
Orace

6

MATL , 10 bayt

1&3Xrt2&|/

Çevrimiçi deneyin!

açıklama

Bu, mücadelede açıklanan ilk yaklaşımı kullanır.

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

Ruby , 34 50 49 bayt

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

Çevrimiçi deneyin!

3 sayı dizisini döndürür [z,y,x].

xve 0 ile 4 arasında rastgele bir güce (-1 karekökü) yyükseltilerek üretilir i. Bu karmaşık sayının zPisagor teoremine uygun değere göre uygun şekilde ölçeklendirilmesi gerekir :(x**2 + y**2) + z**2 = 1.

zArasında 1 ve 1 olmasa da hemen dA / küre aracılığıyla bir dilim için dz sürekli açıktır, homojen olarak dağıtılmış bir sayı yeterli olan (ilk elde edildiği) koordinat (ve aynı yarıçaplı bir daire olarak çevresine eşit bütün küre.

Bu, görünüşe göre, hesabı olmayan bir şekilde tanımlayan Arşimed tarafından keşfedildi ve Arşimet Şapkası Teoremi olarak bilinir. Bkz. Https://brilliant.org/wiki/surface-area-sphere/

Xnor'ın cevabı hakkındaki yorumlardan başka bir referans. Şaşırtıcı derecede basit bir formülü açıklayan şaşırtıcı derecede kısa bir URL: http://mathworld.wolfram.com/Zone.html


@Jitse, x ve y değerlerini z'nin yüksek değerlerinde geri ölçeklemeyi unuttum. Etkili bir nokta bir silindir tanımladı. Şimdi düzeltildi, ancak çok fazla bayta mal oldu! Çıktı karmaşık bir sayıyla ifade edilebilirse birkaçını kurtarabilirim [z, x+yi], tamam olmadığını söylemedikçe olduğu gibi bırakacağım.
Seviye Nehri St

İyi görünüyor! Bu yaklaşımı gerçekten seviyorum. Tutarlılık için, gereken çıktı üç değişkendir, bu yüzden böyle bırakmanızı öneririm.
Jitse,

Neden z*zyerine kullanmıyorsun z**2?
Değerli Mürekkep

@ValueInk evet teşekkürler bunu özleyeceğimi farkettim z*z. Şimdi düzenledim. Yapabileceğim diğer şey ise, ya da (olası değerleri küre üzerindeki çok ince bir spirale etkin bir şekilde sınırlamak) rand*4ile değiştirmektir , ancak bunun rasgele kalitesini düşürdüğünü düşünüyorum. z*99x*9E9
Seviye River St

4

05AB1E , 23 22 bayt

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

2. algoritmayı uygular.

Çevrimiçi deneyin veya birkaç rasgele çıktı alın .

Açıklama:

[0,1)0,00001,00000000159

[            # 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<1l1lx0<x1l<0.51

@Jitse Tamam, normalizasyonu hem Java hem de 05AB1E cevaplarımda uyguladı. Umarım şimdi her şey doğrudur.
Kevin Cruijssen

v1v==1v<10<x1l1

4

TI-BASIC, 15 bayt *

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

Algoritmayı kullanarak "normalde 3 dağıtılmış değer üret ve bu vektörü normalleştir".

İfadeli bir programın sonlandırılması, program sona erdikten sonra Ana Ekranda sonucu otomatik olarak yazdırır, bu nedenle sonuç yalnızca oluşturulan ve kara delikli değil aslında gösterilir.

*: randNorm(A, iki baytlık bir belirteç , geri kalan tek baytlı simgeler . İlkini saydım (kaçınılmaz) :, onsuz 14 byte olur. Tek harfli bir adla program olarak kaydedilen, 9 byte dosya sistemi yükünü içeren 24 byte belleği alır.


3

JavaScript (ES7),  77 76  75 bayt

kullanarak 3. algoritmayı uygular.günah(φ)=günah(marul-1(z))=1-z2

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

Çevrimiçi deneyin!

Yorumlananlar

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(ɸ)
  ]                              //

JavaScript (ES6), 79 bayt

Uygular 2 nd algoritması.

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

Çevrimiçi deneyin!

Yorumlananlar

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

İşleme 26 bayt

Tam program

print(PVector.random3D());

Bu uygulama 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
Uygulamanın bayt sayınızın bir parçası olmadığını açıkça belirtmek isteyebilirsiniz. İlk okumayı özledim, sonra iki kez yaptım.
Seviye River St

Uygulama aslında benim gibi aynı yaklaşımı kullanıyor olsa da,
Level River St

2

Python 2,86 bayt

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

Çevrimiçi deneyin!

İlk algoritmayı uygular.


Python 2 , 107 103 bayt

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

Çevrimiçi deneyin!

İkinci algoritmayı uygular.


2
@RobinRyder Bu uygulama, başlangıçta uzunluğu> 1 olan vektörleri reddetti ve meydan okumada belirtildiği şekilde geçerli.
Jitse,

@Jitse Doğru, üzgünüm. Kodu yanlış okudum.
Robin Ryder

2

Haskell , 125 123 119 118 bayt

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

Çevrimiçi deneyin!

Üç üniforma rastgele ve ret örnekleme yapar.


Görünüşe göre rastgele sayılarınız (-1,1) yerine dağılımdan (0,1) geliyor, böylece kürenin sadece 1 / 8'i kaplanacak.
Jitse,

@Jitse gotcha, fark ettiğiniz için teşekkürler.
8

2

JavaScript, 95 bayt

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)

Sen yok gerek yok girişine a.


Vay, bunu çok özledim. Sabit.
Naruyoko

2

Julia 1.0 , 24 bayt

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

Çevrimiçi deneyin!

Standart sapma 1 ile 0 civarında normal bir dağılımdan çizilmiş 3 değerlik bir vektör çizer. Sonra onları normalleştirir.


randn()Birkaç hızlı testten, istenen aralığa bağlı gibi görünmüyor. Ayrıca, bu, reddedilmesi gereken hypot()bir değer döndürme kontrolü içermez >1.
Shaggy

3
@Shaggy randntek tip (0,1) olandan ziyade standart bir normal dağılımdan taklit olur , bu nedenle bu yaklaşım R olanla aynıdır.
Giuseppe,

@Giuseppe Evet, kesinlikle!
user3263164

@Giuseppe, bu zorluğun ardındaki matematiği tam anlamıyla kavrayamayacağımı düşünüyorum ama, eğer sizi doğru anlarsam, şamandıraların herhangi birinin sınırlarının dışında kalması durumunda onlarla ayrıldığını söylüyorsunuz [-1,1). hipotenüs, hangi olacak >1, ofset? Bu benim çözümümde üçlülüğün gerekli olup olmadığını merak etmeme neden oluyor ...
Shaggy

@Shaggy hayır, normal / Gauss dağılımının üniformanın sahip olmadığı bazı özellikleri (özellikle dönme değişmezliği) vardır, örneğin şu yorumu görün
Giuseppe

2

MathGolf , 21 19 18 bayt

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

2. algoritmanın uygulanması.

Çevrimiçi deneyin veya aynı anda birkaç çıktı daha görün .

Açıklama:

{              }▲   # 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

Java 8 ( @Arnauld değiştirilmiş 3. algoritma), 131 126 119 111 109 bayt

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;}

Liman içinde @Arnauld 'ın JavaScript cevap , çok emin onu upvote olun! @ OlivierGrégoire
sayesinde -2 bayt .

Bu şöyle uygulanır:

k=N-[-1,1)
t=1-k2
u=2πx(N-[0,1))
x,y,z={k,marul(u)xt,günah(u)xt}

Çevrimiçi deneyin.

Önceki 3. algoritma uygulaması ( 131 126 119 bayt):

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);}

Olarak uygulandı:

k=N-[-1,1)
t=2πx(N-[0,1))
x,y,z={k,marul(t)xgünah(arccos(k)),günah(t)xgünah(arccos(k))}

Çevrimiçi deneyin.

Açıklama:

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. algoritma), 153 143 bayt

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;}

Çevrimiçi deneyin.

2. algoritma:

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)Aslında kullanmak , Java'da JS'de olduğundan daha fazla bayt tasarrufu sağlar. :)
Arnauld,

@Arnauld Yep. 3x M.sin, 1x M.cosve 1x yerine, M.acosyaklaşımınız 2x M.sinve 1x kullanır M.sqrt; bu, kaydedilen ek baytların çoğunlukla geldiği yerdir. :)
Kevin Cruijssen

108 bayt Yalnızca s == 1 (s <= 1 yerine normalleştirme yerine) değerlerine izin verdiğim değiştirilmiş bir 2. algoritma kullanır. Bazen bir cevap verir, ancak çoğunlukla zaman aşımı nedeniyle değildir. Düzenleme: Hata, Math.sqrt sonucunu unuttum
Olivier Grégoire

Aslında, hayır, sqrt gerek yok çünkü sqrt (1) == 1. Bu yüzden golf önerim ile ayağa kalkıyorum.
Olivier Grégoire

1
109 bayt ( double[]bayt sayısını değiştirmez, bunun yerine dize çıktınızı kullanabilirsiniz .)
Olivier Grégoire

1

Japt , 20 bayt

Arnauld Limanı'nın 2. algoritmayı uygulaması .

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

Dene

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 bayt

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

Çevrimiçi deneyin!

Algoritma kullanır # 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 bayt

(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

benjlet ... infun()

Çevrimiçi deneyin


Orijinal çözüm:

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])

İlk önce tanımladım:

bir=arccos,  c=marul,  s=günahben~UNIF(0,4),  j~UNIF(0,2)

OCaml'in Random.floatişlevi sınırları içerir. Sonra,

t=benbir(0)=benπ2,  p=bir(j-1)

φ=pθ=t-benj


1
Ben bu dil ile oldukça aşina değilim ama aralarında rastgele yüzen kullanmak gibi görünüyor 0ve 1doğrudan küresel koordinatlar olarak. Bu, 3 ve 4 numaralı meydan okuma notlarında gösterildiği gibi yanlıştır, çünkü kürenin kutuplarına doğru bir önyargılı olursunuz. Bunu 4.
notta

Teşekkür ederim! Bunu tamamen özledim. Hata düzeltildi ve benim cevap güncellenen
Saswat Padhi

1
İyi görünüyor! Çok güzel ilk cevap!
Jitse

Teşekkür ederim :) 100 baytın altına düşürdüm!
Saswat Padhi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.