Bir diziden rastgele seçim


19

Bu zorluk oldukça basittir:
Size pozitif (0 dahil değil) tamsayılar dizisi verilir ve bu diziden rastgele bir öğe seçmeniz gerekir.

Ama burada bir bükülme var:
Bir eleman seçme olasılığı, tamsayının değerine bağlıdır, yani tamsayı büyüdükçe, seçilme olasılığı da artar!

Misal

Size dizi verilir [4, 1, 5].

4 seçme olasılığı, bu durumda dizideki tüm öğelerin toplamına bölünerek 4'e eşittir 4 / ( 4 + 1 + 5 ) = 4 / 10 =40%.
1 seçilme olasılığı 1 / 10veya 10%.

Giriş

Pozitif tamsayılar dizisi.

Çıktı

Bir yöntem kullanıyorsanız, seçilen tamsayıyı döndürün veya doğrudan olarak yazdırın stdout.

kurallar

  • Bu herhangi bir dilde bayt en kısa kod kazanır.
  • Standart boşluklar yasaktır.

Yanıtlar:


20

Jöle , 3 bayt

x`X

Çevrimiçi deneyin!

Bak, Unicode yok!

Açıklama:

x`X
 `  Make monad from dyad and use same left and right arguments
x   Repeat each element of the left argument (implicit) list its respective number of times in the right argument list
  X Random element

1
Kodunuzun ne yaptığını açıklayabilir misiniz, lütfen? :)
Ian H.

1
@IanH. Gerçekten basit bir algoritma her öğenin kendisini kez tekrarlayın ve rastgele seçin.
Outgolfer Erik

16

R , 25 bayt

function(s)sample(s,1,,s)

Çevrimiçi deneyin!

Açıklama:

function(s){
 sample(x = s, size = 1, replace = FALSE, prob = s)
}

Ağırlıkları olmayan yedek olmadan sboyuttan bir örnek alır ; bunlar olasılık olarak yeniden ölçeklendirilir.1s

Dağıtımı doğrulamak için bu bağlantıyı kullanın .


beni 9 ay geçirdin! : D
JayCe

@JayCe heh, senin üzerinde tek avantajım oldukça golfçü olduğun için "önce gidiyor" gibi görünüyor! :-)
Giuseppe

13

Pyth , 4 bayt

OsmR

Burada deneyin.

@Jakube sayesinde oldukça sıradışı bir yaklaşımla bir bayt kurtardı.

Pyth , 5 bayt

Osm*]

Burada deneyin!

Nasıl?

1.

OsmR - Tam program.

   R - Sağ Harita ...
  m - ... Haritayı Kullanma. Bu esasen [[4,4,4,4], [1], [5,5,5,5,5]] listesini oluşturur.
       - ... Kredi bunun için Jakube'ye gidiyor!
 s - Düzleştir.
O - ^ öğesinin rastgele öğesi. Örtük olarak görüntüleyin.

2.

Osm *] - Tam program.

  m - Girişin üzerinden harita.
    ] - Geçerli öğe, d, sarılmış; [D].
   * - Tekrarlanan d kez.
 s - Düzleştir.
O - Rastgele Eleman. Sonucu dolaylı olarak yazdırın.

1
Bunu 4'te yapabilirim. Bozabilir miyim, yoksa kendiniz mi bulmak istersiniz?
Jakube

2
@ Jakube Biraz bekleyin. Bunu yapıp yapamayacağımı görmek istiyorum. Öyle mi o belli mi?
Bay Xcoder

1
@ Jakube Tamam, pes ettiğimde ping yapacağım.
Bay Xcoder

1
OsmLveyaOsmR
Jakube

1
@Jakube Ooh bu çok akıllı! Örtük argüman d, sonra dbir dizi üzerinde haritalar ... dahi!
Outgolfer Erik

8

CJam (9 bayt)

q~_]ze~mR

Çevrimiçi demo . Bu, stdin'de CJam dizi formatında girdi alan ve seçilen elemanı stdout'a basan tam bir programdır.

teşrih

q~   e# Read and parse input
_]z  e# Copy and transpose
e~   e# Run-length decode
mR   e# Select random element uniformly

1
Böyle basit bir görev için çok güçlü bir golf.
Outgolfer Erik

7

Perl 6 , 20 bayt

@Brad Gilbert b2gills sayesinde 1 bayt kaydedildi.

{bag(@_ Zxx@_).pick}

Çevrimiçi deneyin!

Bu 1 liste argümanı alır. Bu listenin 2 kopyasını xxoperatörü kullanarak sıkıştırıyoruz. Böylece @_ Zxx@_, öğenin xsunulduğu xzamanların bir listesini alırız . Daha sonra Bag, nesnelere koleksiyonda kaç kez göründükleri ile birlikte depolayan bir koleksiyon olan zorlanır . Son olarak, bu koleksiyondan picksayıları hesaba katan ve The Right Thing ™ 'i yapan rastgele bir öğe seçiyoruz .


Bu kısaltılabilir{bag(@_ Z=>@_).pick}
Brad Gilbert b2gills 15:17

@ BradGilbertb2gills, ne yazık ki bu işe yaramıyor. Çiftlerden bir çanta yapar (bu yüzden bir kez "1", iki kez "2" vb. Değil, "1 => 1" bir kez, "2 => 2" de bir kez vb. - istediğim şey değil) . Çünkü bu Advent Takvimi'nde açıklandığı gibi besteciler zorlayıcı değillerdir .
Ramillies

@ BradGilbertb2gills, ama yine de teşekkür ederim, burada ve diğer zorluklarda da bazı alanları dışarı çıkarmama yardım ettin!
Ramillies

Demek istediğim{bag(@_ Zxx@_).pick}
Brad Gilbert b2gills

Aah, anlıyorum. Bana neden olmadı ...: -) Teşekkürler.
Ramillies


5

MATL , 8 6 bayt

tY"1Zr

MATL Online'da deneyin !

açıklama

t    % Implicit input. Duplicate
Y"   % Run-length decoding
1Zr  % Randomly take one value with uniform distribution. Implicitly display




4

Java (OpenJDK 8) , 88 87 86 83 bayt

a->{int r=0,x=-1;for(int i:a)r-=i;for(r*=Math.random();r<1;)r+=a[++x];return a[x];}

Çevrimiçi deneyin!


Bir açıklama ekleyebilir misiniz? Neden for(r*=Math.random();;)gerekli olduğunu ya da ihtiyacınız olan her şeyi anlamaya çalışıyorum r*=Math.random().
Ayb4btu

@ Ayb4btu Döngü olmadan for(;;)bu for(int i:a)..., derleyiciyi tatmin etmek için ikinci bir (asla ulaşılmayan) dönüş deyimi gerektirir - ki bu 3 bayt daha uzun olur.
Nevay

Ah, elbette, C # 'daki for(int i:a)gibi foreach. Aynı problemi yaşadım, ama forsürekli döngüleri olan bir problem kullandım . Yeni cevabınız ilgimi çekiyor, bazı fikirlerinizi çalmaya çalışabilirim.
Ayb4btu

3

J, 8 7 8 bayt

7 byter geçersiz; Bir iki gün içinde bilgisayarıma geri döndüğümde bunu önceki bir düzenlemeye geri döndüreceğim.

Çevrimiçi deneyin!

?@+/{#~

:( bir diziden rastgele elemanlar seçmek maliyetlidir.

8 bayt

#~{~1?+/

9 bayt

(1?+/){#~

açıklama

?@+/{#~
?        Choose random number in range
  +/     Sum of the array
    {    Select that element from
     #~  The elements duplicated as many times as their value

?@+/olduğu (?@+)/; Korkarım bunu 8'e kadar tekrar çarpmak zorunda kalacaksın ...
FireFly

@FireFly Daha fazla test etmeliydim, iyi yakaladım.
cole

3

JavaScript (ES6), 50 bayt

a=>a.sort((a,b)=>b-a)[Math.random()**2*a.length|0]

Umarım bunun nasıl çalıştığı açıktır, ancak yine de burada açıklayacağım. Tam sayıları azalan düzende sıralar, ardından bir beta dağılımı ile rastgele birini seçer (1 / 2,1) .


Bunun doğru bir dağıtım olacağını sanmıyorum. Benim testleri ile olduğunu göstermektedir a=[4,1,5], sen% 18 yaklaşık alırsınız 1,% 24 4ve% 58 5size uzunluğu 3. herhangi girişi olan bu dağıtımı alırsınız önerir
Giuseppe

Bu benim için doğru görünüyor. Daha yüksek tamsayı, daha yüksek olasılık.
kamoroso94

Ah anlıyorum. Soruyu yanlış okudum. Mükemmel çözüm, +1!
Giuseppe


2

PowerShell , 27 bayt

($args[0]|%{,$_*$_})|Random

Çevrimiçi deneyin!

Girdiyi $args[0]değişmez dizi olarak alır. Her öğeyi döngüler |%{...}ve her yineleme yeni bir öğe dizisi ,$_oluşturur $_- örneğin, 4bu bir dizi oluşturur @(4,4,4,4). Bu dizi elemanları daha sonra Get-Random(sözde) eşit olasılıkla elemanlardan birini koparacak olan boru elemanlarının içine borulanır. Örneğin, bunun için @(4,1,5)bu bize @(4,4,4,4,1,5,5,5,5,5)olasılık gereksinimlerini karşıladığından.


2

C # (.NET Core) , 93 89 87 76 + 18 = 94 bayt

a=>{int i=-1,r=new Random().Next(a.Sum());while(r>=0)r-=a[++i];return a[i];}

Çevrimiçi deneyin!

Fazladan 18 bayt using System.Linq;

Teşekkür

Rastgele sayı uygulaması çok daha özlü olan (ayrıca inta yerine double) Nevay sayesinde 11 bayt kurtardı .

Degolfed

a=>{
    int i=-1,
    r=new Random().Next(a.Sum());
    while(r>=0)
        r-=a[++i];
    return a[i];
}

açıklama

r0 ile elemanların toplamı arasında rastgele bir sayı alın . Sonra her yinelemede geçerli öğeyi çıkarın r. Eğer rdaha az olduğu 0, daha sonra bu eleman döndürür. Fikir dizideki daha büyük sayılar için rasgele sayının daha büyük bölümleri olmasıdır.


94 bayt:a=>{int i=-1,r=new Random().Next(a.Sum());for(;r>=0;)r-=a[++i];return a[i];}
Nevay

2

Japt , 7 bayt

ËÆD
c ö

Burada test edin


açıklama

Örtülü dizi girişi U.

Ë

Her öğeyi Dgeçerli öğenin bulunduğu bir işlevden geçiren dizi üzerinden eşleştirin.

ÆD

Bir uzunluk dizisi oluşturun Dve doldurun D.

c

Düzleştirmek.

ö

Rastgele bir eleman alın.



1

Perl, 31 bayt

@a=map{($_)x$_}@ARGV;$a[rand@a]

Bu, girdinin komut satırı bağımsız değişkenleri olduğunu varsayar. Sayılar büyükse belleğin bitebileceğini unutmayın.




1

Kömür , 12 bayt

F⪪θ;FIι⊞υι‽υ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı versiyonudur. Kömür çok zeki olmaya çalıştığından, dizi için noktalı virgülle ayrılmış girdi kullanmak zorundayım. Açıklama:

  θ             Input variable as string
 ⪪ ;            Split on semicolons
F               Loop i over each string
     Iι         Cast i to integer
    F           Repeat that many times
       ⊞υι      Push i to (originally empty) list
          ‽υ    Random selection from list
                Implicitly print


1

Javascript (ES6), 61 54 bayt

@Justin Mariner sayesinde -7 bayt

a=>a.find(m=>(n-=m)<0,n=Math.random()*eval(a.join`+`))

Örnek kod snippet'i

f=
a=>a.find(m=>(n-=m)<0,n=Math.random()*eval(a.join`+`))
console.log(f([4,1,5]))


Sen kullanarak özetleyebilirim eval(a.join`+`)yerine reduce.
Justin Mariner

ES7 + ile sorun yaşıyorsanız şunları kullanabilirsiniz: [].find(m=>(n-=m)<0,n=Math.random()*eval(a.join+ ))veinput::[].find(...)
Downgoat

1

Haskell , 78 77 bayt

import System.Random
f l=randomRIO(0,sum l-1)>>=pure.((l>>= \n->n<$[1..n])!!)

Çevrimiçi deneyin! Kullanım örneği: f [1,99]muhtemelen verim 99.

Açıklama:

  • fbir tamsayı listesi alır lve rastgele seçilen tamsayıyı olarak döndürür IO Int.
  • l>>= \n->n<$[1..n]her öğenin ntekrarlandığı bir liste oluştururn .
  • randomRIO(0,sum l-1) 0'dan, yinelenen öğeler listesinin uzunluğunda, tam olarak tüm öğelerin toplamı olan eksi sınır dışı istisnadan kaçınmak için bir tamsayı verir.

Bonus: 85 bayt noktasız sürüm

import System.Random
(>>=).randomRIO.(,)0.pred.sum<*>(pure.).(!!).(>>= \n->n<$[1..n])

Çevrimiçi deneyin!



1

Java 8, 127 122 121 bayt

import java.util.*;a->{List l=new Stack();for(int i:a)for(int j=i;j-->0;Collections.shuffle(l))l.add(i);return l.get(0);}

@Nevay sayesinde -1 bayt .

Listeye öğenin çarpımını ekleyerek ve listeden rastgele birini seçerek @ErikTheOutgolfer'ın Jelly yanıtı ile benzer bir yaklaşım kullanır .nn

Açıklama:

Burada deneyin.

import java.util.*;        // Required import for List, Stack and Collections
a->{                       // Method with integer-array parameter and integer return-type
  List l=new Stack();      //  Create a List
  for(int i:a)             //  Loop (1) over the input array
    for(int j=i;j-->0;     //   Inner loop (2) from `i` down to 0
        Collections.shuffle(l))
                           //   and shuffle the List randomly after every iteration
      l.add(i);            //    Add `i` that many times to List `l`
                           //   End of inner loop (2) (implicit / single-line body)
                           //  End of loop (1) (implicit / single-line body)
  return l.get(0);         //  And then return the first item of the list
}                          // End of method

1
#shuffle1 bayt kaydetmek için çağrıyı for döngüsüne taşıyabilirsiniz for(int j=i;j-->0;Collections.shuffle(l))l.add(i);.
Nevay

@Nevay Teşekkürler! Her yinelemeden sonra Listeyi karıştırmak oldukça verimsizdir, ancak ek bir sinir bozucu bayttan kurtulabildiğimizde verimlilik, uyarılar ve benzeri şeyleri önemsiyoruz. ; p
Kevin Cruijssen


1

GNU APL 1.2, 26 23 bayt; 1.7 21 19 bayt

Outgolfer'ın Jelly cevabından esinlenen yaklaşım . Dayanır⎕IOGNU APL (varsayılan +5 bayt) için varsayılan olan 1 yerine 0 olmasına⎕IO←0 .

@ Zacharý sayesinde -3, -2 bayt

işlev formu

∇f R
S[?⍴S←∊0 0⍉R∘.⍴R]∇

Anonim lambda formu

{S[?⍴S←∊0 0⍉⍵∘.⍴⍵]}

Açıklama için kullanacağı işleve geçirilen argümanı temsil etmek, ancak eşdeğerdir Riçinde formu.

⍵∘.⍴⍵reshape ( ) operatörünü kullanarak listedeki dış ürünü hesaplar . Etkili bir şekilde, bu bir tablo oluşturur (çarpım tablosu gibi), ancak çarpmak yerine, sütundaki öğeyi satırdaki öğeye eşit sayıda tekrarlar. Soruda verilen örnek için bu:

4 4 4 4    1 1 1 1    5 5 5 5   
4          1          5         
4 4 4 4 4  1 1 1 1 1  5 5 5 5 5

0 0⍉⍵∘.⍴⍵matrisi aktarır ve sadece ana köşegenini döndürür. Bu bize sadece satır ve sütunun ⍵∘.⍴⍵aynı olduğu parçaları verir , yani değeri değerine birkaç kez tekrarladık. Örnek olarak, bu:

4 4 4 4  1  5 5 5 5 5

argümanını bir listeye dönüştürür. Transpose ( ) operatörünü kullanarak 3 vektör içeren bir vektör elde ettik. Enlist ( ), tüm öğeleri içeren tek bir vektöre dönüştürür.

S←...bu yeni vektöre vektörü atar S. ⍴Sbize bu listenin uzunluğunu verir. ?rasgele işleçtir, bu nedenle ?⍴Sbize 0 ile listenin uzunluğu (münhasır) arasında rastgele bir sayı verir (bu nedenle ⎕IO0'a dayanır ; aksi takdirde 1 ile uzunluk arasındadır). S[...]verilen dizindeki öğeyi döndürür.


İhtiyacınız yok Q, çünkü asla kullanmıyorsunuz. Ve IIRC
delline

Vay be, ben <IO> <IO>⍉ana köşegen elde etmek için hiçbir zaman yeni bir şey oldu!
Zacharý

@ Zacharý Tamam, teşekkürler. Açıkçası, ben de bu görevi denemeden kadar devrik şeyi bilmiyordum. Buldum burada
Arc676

Oh, GNU'dan çok daha iyi bir serbest APL var, buna ngn APL deniyor. Aslında oldukça havalı! ( ngn.github.io/apl/web , ancak tradfn yok)
Zacharý

@ Zacharý Ben de var :) maalesef transpoze fonksiyonu çalışmıyor (ya da bir şey kaçırdım). Nasıl çalıştığını daha iyi anladığım için şimdi tekrar test edeceğim.
Arc676

1

MATLAB, 30 bayt

@(a)datasample(repelem(n,n),1)

Bu, MATLAB R2015a veya daha yenisini ve İstatistikler ve Makine Öğrenimi araç kutusunun yüklü olduğunu varsayar.

Nasıl repelemkullanıldığını görmek için aşağıdaki açıklamaya bakın . Bu daha kısa olanla aşağıdaki olan arasındaki fark, S&ML araç kutusunun, datasamplebir diziden bir veya daha fazla öğeyi rasgele (üniform olasılıkla) almak için kullanılabilen ve anonim bir işlevin kullanılmasına izin veren işlevi içermesidir.input/disp çağırır.

MATLAB, 49 bayt

n=input('');a=repelem(n,n);disp(a(randi(nnz(a))))

Bu kod, MATLAB R2015a veya daha yenisinin repelemişlevin tanıtıldığı gibi kullanıldığını varsayar .repelemiki parametre alan bir işlevdir, birincisi çoğaltılacak sayı dizisidir ve ikincisi karşılık gelen öğenin kaç kez çoğaltılması gerektiğidir. Temel olarak işlev, sayı ve çalışma uzunluğu sağlayarak çalışma uzunluğu kod çözme işlemini gerçekleştirir.

Aynı girdiyi her iki girişe de sağlayarak, repelemeğer mantıklıysa, n öğesinden n kat daha fazla bir dizi ile sonuçlanır. Eğer [1 2 3]sağladıysanız alırsınız [1 2 2 3 3 3]. Eğer [1 2 4 2]sağladıysanız alırsınız [1 2 2 4 4 4 4 2 2]. Bunu yapmak, tekdüze olasılıklı bir eleman seçersek (tekdüze olasılıkla randi(m)1'den m'ye rastgele bir tamsayı verir), her elemanın n'nin n kat daha yüksek bir seçilme olasılığına sahip olduğu anlamına gelir. İlk örnekte [1 2 3], 1bir 6/1 şans olurdu 2bir 2/6 şans olurdu ve 3bir 6/3 şans olurdu.


Bir yan not olarak, repelemhenüz Octave için mevcut olmadığından, bir TIO bağlantısı veremiyorum. Ek olarak Octave kullanılamadığından, anonim bir işlev olarak kullanılması gereken büyük bir karakter cezası vardır input()ve disp()bu mümkün değildir. Octave destekleniyorsa repelemaşağıdakiler kullanılabilir:

@(n)a(randi(nnz(a=repelem(n,n))))

Bu 16 bayt kurtaracaktı, ama olmayacaktı.


Açıklamayı gerçekten takdir ediyorum, teşekkürler!
Ian H.
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.