Pengacakan hingga 0


29

Tantangan

Posting kotak pasir

Diberikan bilangan bulat positif (K)Output bilangan bulat seragam acak (Y)antara [0, K).

Jika Y > 0Asumsikan K = Ydan ulangi prosesnya sampai Y = 0.

Aturan

  • Masukan harus dicetak terlebih dahulu
  • Format output sesuai keinginan
  • Program Anda harus selesai.
  • 0 harus menjadi hasil akhir, sebagai gantinya opsional baris kosong 0

Jika kiriman adalah fungsi, dapatkah ia mengembalikan 0 selain untuk mencetaknya?
Adám

1
@ Adám ya, Anda dapat kembali sebagai tambahan
Luis felipe De jesus Munoz

Apakah saya perlu seed RNG saya?
SIGSTACKFAULT

Bisakah kita mencetak tanpa pembatas?
Titus

Saya jadi penasaran. Sangat mudah untuk membuktikan bahwa jumlah rata-rata langkah yang diambil program ini sebelum berakhir adalah H (K-1) + 1 di mana H (K) adalah bilangan harmonik K'th . Untuk n = 1000, itu rata-rata 8,484 langkah.
J.Doe

Jawaban:


19

Pyth , 6 5 4 byte

.uOW

Coba di sini!

Bagaimana itu bekerja

.uOW Program lengkap. Mengambil bilangan bulat dari STDIN dan menampilkan daftar ke STDOUT.
.u Poin tetap kumulatif. Terapkan fungsi yang diberikan dengan nilai awal yang diberikan,
        yang secara implisit ditugaskan ke input, hingga hasil yang telah terjadi 
        sebelum ditemukan. Mengembalikan daftar hasil antara.
   Aplikasi bersyarat W. Jika argumen (nilai saat ini) benar, maka
        terapkan fungsi di bawah ini, jika tidak biarkan tidak berubah.
  O Bilangan bulat acak dalam kisaran [0, N).
        TKI: pada setiap iterasi .u, tetapkan variabel N ke nilai saat ini, dimulai
        dengan input. Jika N bukan 0, maka pilih bilangan bulat acak di [0, N), jika tidak
        return N tidak berubah. Setiap kali kita menemukan 0, iterasi berikutnya juga harus
        menghasilkan 0, dan karenanya loop berhenti di sana.

1
Saya melihat cara untuk melakukan ini di Pyth tapi saya pemula. Menghormati. Bahasa bulan Agustus mungkin?
ElPedro

15

C (gcc) , 42 byte

f(_){printf("%d\n",_);(_=rand()%_)&&f(_);}

Cobalah online!

Menggunakan hubung singkat dan logis.

f(_){                 // f(int _) {
    printf("%d\n",_); // print argument and a newline
    (_=rand()%_)      // set _ to rand()%_
    &&f(_);}          // short-circuit AND to recursively call f if _ not zero

C (gcc) , 40 byte (tanpa mencetak nilai awal)

f(_){printf("%d\n",_=rand()%_);_&&f(_);}

Cobalah online!

Menggunakan hubung singkat dan logis.

f(_){              // f(int _) {
    printf("%d\n", // print an integer and a newline 
    _=             // The integer is _ which we set to...
    rand()%_);     // a random value modulo the input _
    _&&f(_);}      // short-circuit AND to recursively call f if _ not zero

4
rand()%_tidak seragam
njzk2

(jika Anda tidak yakin, coba gunakan dadu 6 sisi untuk menghasilkan nilai [1,5] menggunakan metode ini.)
njzk2

3
Saya menyadari sepenuhnya bahwa rand () hampir selalu bias (karena pemotongan), tetapi standar tidak menjaminnya (RAND_MAX secara teori dapat menjadi kelipatan dari semua angka kami, hanya karena keberuntungan: P meskipun biasanya itu ~ 65k ). Dalam praktiknya untuk rentang yang kami hadapi, akan muncul cukup acak untuk tidak menonjol terhadap pengajuan serupa dalam tantangan ini.
LambdaBeta

1
itu dari tantangan "
Keluarkan

3
Sebenarnya semua bahasa di sini menggunakan bahasa prng. Tak satu pun dari mereka akan memberikan angka acak seragam yang benar (yang akan membutuhkan sumber entropi yang sempurna). Meskipun banyak yang lebih seragam dari ini, itu tidak terlihat dalam iterasi log (k).
LambdaBeta

10

R , 66 60 56 43 41 byte

function(n)while(print(n))n=sample(n,1)-1

Cobalah online!


Saya tidak berpikir Anda perlu >0dan cat(n,"")(string kosong) juga akan berfungsi.
Giuseppe

Tapi saya pikir printlebih efisien di sini, karena mengembalikan argumennya: 56 byte
Giuseppe

Juga 56 byte:k=scan();while(x<-sample(1:k-1,1))k=c(x,k);cat(rev(k),0)
JAD

1
Saya lupa menghapus kurung keriting, sehingga Anda dapat menyimpan 2 byte lebih banyak;) Cobalah online!
digEmAll

2
39 byte:n=scan();while(print(n))n=sample(n,1)-1
djhurio

6

MATL , 6 byte

`tYrqt

Cobalah online!

Penjelasan

`        % Do...while
  t      %   Duplicate. Takes input (implicit) the first time
  Yr     %   Uniform random integer from 1 to n, included
  q      %   Subtract 1
  t      %   Duplicate. This will be used as loop condition
         % End (implicit). Proceeds with next iteration if non-zero
         % Display stack (implicit)

6

Pepe , 25 byte

Pepe adalah bahasa pemrograman yang dibuat oleh pengguna Soaku .

REeErEErReEEreeEREEeEEree 

Cobalah online!

Penjelasan:

REeErEErReEEreeEREEeEEree # full program

REeE                      # input as num, in stack 1
    rEE                   # create loop in stack 2 with name 0
       rReEE              # - output and preserve the number in stack 1
            reeE          # - output a newline "\n"
                REEeEE    # - random number by 0 to input
                      ree # goto loop with name 0 if stack 1 is not equal
                            to stack 2

5

Perl 6 , 18 byte

{$_,(^*).pick...0}

Cobalah online!

Blok kode anonim yang mengembalikan daftar nilai. Jika Anda tidak keberatan angkanya berkisar, Anda dapat melakukan:

{^$_,^*.pick...0}

selama 17 byte. Lucunya, fungsi acak builtin lain roll,, memiliki perilaku yang sama dalam hal ini untuk jumlah byte yang sama.



5

Jelly ,  4  3 byte

XƬ0

Ini adalah tautan monadik (fungsi) yang mencetak array dan mengembalikan 0 .

Cobalah online!

Bagaimana itu bekerja

XƬ0  Monadic link. Argument: n

XƬ   Pseudo-randomly pick (X) an integer k in [1, ..., n], set n = k, and repeat.
     Do this 'til (Ƭ) the results are no longer unique and return the array of
     unique results, including the initial value of n.
     This stops once X returns k with argument k. The second k will be omitted
     from the return value.
  0  Print the resulting array and set the return value to 0.

Dicoret sangat bagus dari 4!
ngm

1
Kami tidak ingin mencoret 4 agar terlihat seperti 4 biasa, bukan?
Dennis

4

Brachylog , 8 byte

ẉ?ℕ₁-₁ṙ↰

Cobalah online!

Penjelasan

ẉ          Write the input followed by a linebreak
 ?ℕ₁       The input must be in [1, …, +∞)
    -₁ṙ    Generate an integer in [0, …, input - 1] uniformly at random
       ↰   Recursive call with that random integer as the new input

Rekursi akan berhenti setelah ?ℕ₁gagal, yaitu saat input 0.


4

05AB1E , 8 7 byte

Δ=L<Ω0M

Cobalah online!

Penjelasan

Δ         # loop until value doesn't change
 =        # print current value
  L<Ω     # push a random number in ([1 ... X] - 1)
          # will return -1 when X=0
     0M   # push max of that and 0

1
Δ=ݨΩ0Msetara.
Magic Gurita Guci

4

J, 13 byte

[:}:? ::]^:a:

Di kereta bawah tanah, jadi minta maaf karena kurangnya TIO (mudah-mudahan tidak ada kekurangan kebenaran).

Menghasilkan daftar nilai.

Agaknya pendekatan APL akan lebih pendek, tetapi inilah yang saya pikirkan.

Bagaimana itu bekerja

^:a: terapkan berulang kali hingga konvergensi, menyimpan hasil antara dalam array.

?integer acak dalam kisaran [0, K)untuk Klebih besar dari 0. Untuk 0, itu memberikan integer acak dalam kisaran (0,1). Untuk angka floating point, kesalahan.

::]menangkap kesalahan untuk input ?dan bukannya kesalahan , output input yang menyebabkan kesalahan.

}: singkirkan nilai terakhir dalam array (ini adalah agar angka floating point bukan output).

Cobalah online!


Hanya saya atau kode mengembalikan output yang sama?
Luis felipe De jesus Munoz

@LuisfelipeDejesusMunoz seseorang yang mengenal J lebih baik daripada yang saya bisa jelaskan tetapi saya pikir RNG selalu dimulai dengan seed yang sama. Ada juga seed tetap ?., tapi saya rasa saya tidak menggunakannya.
cole

@cole Anda benar.
Jonah

4

JavaScript (ES6), 38 37 byte

-1 byte terima kasih kepada @Arnauld

f=n=>[n,...n?f(Math.random()*n|0):[]]


Bisakah Anda mengurangi math.random sama sekali? mis. dengan codegolf.stackexchange.com/a/35648/67066
Marie

1
@Marie menggunakan new Date%ntidak benar-benar berfungsi di sini, karena itu tidak berubah cukup cepat untuk menjadi berguna untuk menghasilkan beberapa nomor acak
Herman L

4

C, 38 byte

f(k){printf("%d ",k);k?f(rand()%k):0;}

Cobalah online

Tidak disatukan

void f(int k){
    printf("%d ",k);
    if(k)
        f(rand()%k);
}

1
Anda dapat menyimpan byte dengan mengganti operator ternary dengan &&; juga, Anda mungkin ingin mempertimbangkan untuk menaburkan RNG di mainfungsi Anda : Cobalah online!
ErikF

1
Anda juga dapat menyingkirkan terner sama sekali dan mengakhiri kesalahan. 34 byte
Jo King

4

Pyth , 4 byte

W
~O

Cobalah online!

Ini pada dasarnya mengimplementasikan algoritma:

QinputRepeat1.tempQ2.Qunif{0,Q1}3.Print(temp)Untiltemp=0

To translate the Pyth into the algorithm, we can mostly just examine what each character means. Since Pyth is written in prefix notation (i.e. * + 1 2 3 is (1 + 2) * 3) we can start from the left and fill in the arguments as we go.

Wmemulai loop sementara tradisional. Pernyataan pertama setelah itu adalah kondisi loop dan pernyataan kedua setelah itu adalah loop body. Jika pernyataan kedua kosong itu menjadi no-op . Ini sementara bekerja persis seperti Python sementara, sehingga akan mengevaluasi bilangan bulat bukan nol sebagai Benar dan nol sebagai salah.

Pernyataan pertama setelah beberapa saat dimulai dengan karakter baris baru. Ini sesuai dengan fungsi "cetak dan kembali dengan baris baru" Pyth. Ini membutuhkan satu argumen, yang kemudian dicetak dan juga dikembalikan tanpa dimodifikasi. Ini memungkinkan kami untuk mencetak langkah-langkah perantara sambil juga melakukan operasi yang diperlukan.

Argumen yang diteruskan ke fungsi cetak ini dimulai dengan ~yang agak spesial. Jika karakter segera setelah ~variabel, dibutuhkan dua argumen, jika tidak maka diperlukan satu. Karena Obukan variabel ~akan mengkonsumsi hanya satu argumen. ~fungsi sedikit seperti +=tidak dalam banyak bahasa konvensional, meskipun operator terdekat akan menjadi operator pasca-kenaikan ++dari C. Anda mungkin tahu itu x++akan seperti menggunakan xsebagai nilai saat ini, tetapi sesudahnya xakan seperti itu x+1. ~adalah ide yang sama, tetapi digeneralisasi untuk apa pun hasil dari argumen pertama. Bagaimana cara memilih variabel yang akan ditugaskan akan dibahas nanti.

Argumennya ~adalah Oyang sangat sederhana. Ketika satu argumennya adalah bilangan bulatO mengembalikan nilai dari 0 menjadi kurang dari integer itu secara acak.

Sekarang Anda mungkin telah memperhatikan Otidak memiliki argumen. Di sini penerjemah Pyth dengan baik mengisi duga, yang di sini adalah variabel Q. Qmemiliki arti khusus dalam Pyth: setiap kali ada dalam suatu program, program Pyth dimulai dengan menugaskan Qinput dari program. Karena ini adalah variabel pertama yang terjadi dalam ~argumen Qjuga sekarang variabel yang ~akan memberikan nilai.

Ringkas program "dapat dibaca" kami mungkin terlihat seperti:

while print_and_return( assign_variable( Q, unif(0, Q-1) ) ):
    pass

Dan satu sampel "run-through" mungkin terlihat seperti:

  1. Q = 5
  2. Omengembalikan 3, ~mengembalikan 5,\n mengembalikan dan mencetak 5 yang benar
  3. Q = 3
  4. Omengembalikan 0, ~mengembalikan 3, \nmengembalikan dan mencetak 3 yang benar
  5. Q = 0
  6. Omengembalikan sesuatu yang tidak relevan, ~mengembalikan 0, \nmengembalikan dan mencetak 0 yang salah
  7. Q = sesuatu yang tidak relevan
  8. Mengakhiri

3

APL (Dyalog Unicode) , 12 9 byte

Fungsi awalan diam-diam anonim. Diasumsikan ⎕IO( I ndex O rigin) 0, yang merupakan default pada banyak sistem. Mengembalikan nilai akhir (0) selain mencetak saat dijalankan.

{⌊?⎕←⍵}⍣=

Cobalah online!

{... }⍣= terapkan fungsi berikut sampai stabil:

⎕←⍵ Keluarkan argumen

? mengembalikan nomor acak yang terdistribusi secara merata dalam kisaran 0 hingga -1

 round down (karena ?0memberikan (0,1) float)


3

C (gcc), 40 42 bytes

Some idiot™ forgot to print the initial value first.

f(K){while(K)printf("%d\n",K,K=rand()%K);}

Don't panic.


You tied me, the question also requires that you print the initial K. Without it I also got 40. You can also get the 42 fully compliant version in a similar way: f(K){while(K)printf("%d\n",K),K=rand()%K;}. Still you got my +1 for an equal solution!
LambdaBeta

Even better: f(K){while(K)printf("%d\n",K,K=rand()%K);}
SIGSTACKFAULT

3

x86 + rdrand, 19 bytes

Straightforward implementation. Takes input K in ecx and outputs to a buffer in ebx.

0000000a <start>:
   a:   0f c7 f0                rdrand %eax
   d:   31 d2                   xor    %edx,%edx
   f:   f7 f1                   div    %ecx
  11:   89 13                   mov    %edx,(%ebx)
  13:   83 c3 04                add    $0x4,%ebx
  16:   89 d1                   mov    %edx,%ecx
  18:   85 c9                   test   %ecx,%ecx
  1a:   75 ee                   jne    a <start>
  1c:   c3                      ret  

3

Python 3, 39 bytes

f=lambda k:print(k)or f(hash('.'*k)%k)

Probably not the most cryptographically secure random number generator but to the human eye it looks random enough...

Try it online!


Notes: 1) the entry gives (usually) different results every time it's run in a new interpreter but may give the same result if run within the same python session. 2) I assume that terminating through an error without explicitly checking for k=0 is acceptable.
Luca Citi

Sorry, but functions must be reusable arbitrarily often in the same environment. Terminating in an error is acceptable though
Jo King

The task requires a uniform random number from the given range. hash() tries to maintain but doesn't guarantee this property. For that task you should use the random module.
David Foerster

With only 57 bytes you can amend your solution to use uniformly random numbers from random.randrange(): from random import*;f=lambda k:print(k)or f(randrange(k))
David Foerster

3

TI-Basic (TI-84 Plus CE), 17 13 bytes

While Ans
Disp Ans
int(randAns
End
Ans

-4 bytes from Misha Lavrov

Takes input in Ans as 50:prgmNAME.

TI-Basic is a tokenized language. All tokens used here are one byte.

Explanation:

While Ans    # 3 bytes, While the number we hold is not zero:
Disp Ans     # 3 bytes,   Display it on its own line
int(randAns  # 4 bytes,   and replace it with a number randomly
                        # chosen from 0 to one less than it (inclusive)
End          # 2 bytes, end While loop
Ans          # 1 byte,  Display (and return) zero

An 11-byte solution suggested by Misha Lavrov that requires pressing enter after each line following the first.

Ans
While Ans
Pause int(randAns
End

1
int(Ansrand is shorter. Also, using Pause instead of Disp, you can make the only statement in the loop be Pause int(Ansrand, which also updates Ans.
Misha Lavrov

3

Python 2, 64 62 60 bytes

from random import*
k=input()
while k:print k;k=randrange(k)

Try it online!


Saved

  • -2 bytes, thanks to Jonathan Allan

"Input must be printed at first"... while 1:print k;k=randint(0,~-k) should work (with an error at the end)
Jonathan Allan

...and then while 1:print k;k=randrange(k) saves two.
Jonathan Allan

1
@JonathanAllan Thanks :), The questions says I can use an empty line instead of 0, so no error.
TFeld

3

C++ (gcc), 98 bytes

#import<cstdio>
#import<cstdlib>
#define d printf("%i ",x 
int p(int x){d);while(x>0)d=rand()%x);}

Try it here!

Usage

int main() {
    p(100);
}

This is my first code golf attempt. Any feedback or remarks are welcome.

Edit: Removed the main function as suggested to make it valid.


1
Hi, and welcome to PPCG :) You do not need to include the sample call in your byte count (i.e. you don't need to write the main function) since we accept functions as valid submissions. Otherwise, your submission is technically not valid since if the input was some two or more digit number the output could be ambiguous. If you just add a space at the end of the format string in your macro you should be fine. Happy golfing!
FryAmTheEggman

Adding the compiler flag -Dd='printf("%i,",x' instead of the #define would save you some bytes (-4), and is allowed as long as you count the bytes towards your result (because it is a non-standard preprocessor directive. You can also leave out the imports (at least with -std=c++98 and -w, which don't count for bytes), and the variable types. So, you'd have p(x){d);while(x>0)d=rand()%x;} and -Dd='printf("%i,",x'.

Also, you should probably check out the Standard Loopholes and Tips for golfing in C, if you haven't already :)

3

><>, 92+2 Bytes

:nao:0=?;0_1>:{:}(?\\
}(?!\$2*1>x~\$+1$*2/\~00:{{:@}
8+1.\~:{:}\+>$1+f
~~@~~47*0.\(a2*1@@?!.

+2B for -v flag

Try it online!

><>'s only source of randomness comes from the 'x' instruction, which sets the instruction pointer's direction to a random value. As such, generating a random number from 0 to n isn't trivial.

I first calculate how many bits are required to represent a number in the range [0,n), then generate random bits to generate a random number. This leaves the possibility that it'll generate a number slightly larger than n, in which case we just discard it and try again.

Explanation:

:nao                              Print the current number followed by a newline
    :0=?;                         If the current n is 0, terminate

Calculate how many random bits we need to be generating:
         0 1                      Initialise the variables for this loop: 
                                      numberOfBits = 0, maxValue = 1
             :{:}(?\              If maxValue >= n, break out of the loop
                 *2               maxValue *= 2
             $+1$                 numberOfBits += 1

Generate the random number:
                     ~            Delete maxValue
                      00          Initialise randomNumber = 0, i = 0
}(?!\                   :{{:@}    If i >= numberOfBits, break out of the (inner) loop
     $2*                          randomNumber *= 2
          _
        1>x~\                     The random bit: If the IP goes up or 
          \+>                     left, it'll be redirected back onto the 'x', 
                                  if it goes down, it adds one to randomNumber
                                  If it goes right, it does nothing to randomNumber

             $1+                  increment i
8+1.            f                 Jump back to the start of the inner loop

After we've generated our number, check that it's actually below n
     ~                            Delete i
      :{:} (      ?               Test that the number is less than n
            a2*1    .             If it's not, jump back to the start 
                                  of the number generation section
  @~~                             Otherwise delete the old value of n, and numberOfBits
     47*0.                        Then jump back to the start of the program

Very nice! I came up with the same idea independently; without whitespace, my solution uses several characters fewer than yours, but you've managed to make a much more compact block of code.
Théophile

2
The current meta consensus is that you don't have to count the bytes used on flags
Jo King

3

MATLAB (49 46 bytes)

@(k)eval('while k;disp(k);k=randi(k)-1;end;0')

Sample output:

>> @(k)eval('while k;disp(k);k=randi(k)-1;end;0')
ans(5)

ans = 

    @(k)eval('while k;disp(k);k=randi(k)-1;end;0')

     5    
     3    
     2    
     1   

ans =    
     0

1
I suppose you can do k=randi(k)-1 for a few bytes less.
Sanchises

2

Retina, 21 bytes

.+
*
L$`.
$.`
+¶<)G?`

Try it online! Explanation:

+

Repeat until the value stops changing (i.e. 0).

¶<)

Print the value before each pass through the loop.

.+
*

Convert to unary.

L$`.
$.`

Create the range and convert to decimal.

G?`

Pick a random element.


2

Pyth, 6 7 bytes

QWQ=OQQ

Try it online!

+1 to print the initial input value.

While Q is truthy, set Q to be a random integer between 0 and Q and print Q.

Not the shortest Pyth answer but I'm just learning and only posting because of the recent discussion about no-one using Pyth any more :)


2
I managed to tie using cumulative reduce but keeping it as a procedural program. Thanks for the motivation to work on a golf :)
FryAmTheEggman

That's cool. Still trying to work out how (why) it works.
ElPedro

By default, both = and ~ use the first variable of an expression as the variable that will be assigned if one isn't specified. For example ~hT will set T to 11 while returning 10. The only other fancy trick is that the newline character prints its input and then returns that value unmodified, so we can have an empty loop body. Let me know if something else is confusing :)
FryAmTheEggman

1
@FryAmTheEggman That's beautiful.
isaacg

1
@isaacg Thanks! I originally meant for it to just be edited in here, but I decided to write something up since I wanted to try MathJax. These kinds of Pyth answers were always my favourite since they feel both intentional but also abusive :)
FryAmTheEggman


2

IBM/Lotus Notes Formula, 48 bytes

o:=i;@While(i>0;i:=@Integer(i*@Random);o:=o:i);o

Field formula that takes input from another field i.

There's no TIO for formula so here's a screenshot of a sample output:

enter image description here



2

PowerShell, 35 bytes

for($a="$args";$a;$a=Random $a){$a}

Try it online!

Full program. Takes input $args, stores it into $a, and enters a for loop. Each iteration we're checking whether $a is still positive (as 0 is falsey in PowerShell). Then we leave $a on the pipeline and move to the next iteration, where we set $a to be the result of Get-Random $a, which returns an integer in the range 0..($a-1).

(Ab)uses the fact that PowerShell outputs an additional trailing newline in lieu of outputting the final zero (allowed by the rules as currently written).


"$args" - nice. I was stuck on $args[0] in this case
mazzy

2

Lua, 58 bytes

p,r=print,...+0 p(r)while r>0 do r=math.random(0,r)p(r)end

Try it online!

For some more Lua love here :)


Hey, you can remove the +0 on the r declaration and move it to the r on the while statement, by doing so you'll use 1 less byte for the space (p,r=print,...p(r)while).
Visckmart
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.