Ngẫu nhiên cho đến 0


29

Thử thách

Bài Sandbox

Cho một số nguyên dương (K)Xuất ra một số nguyên ngẫu nhiên đồng nhất (Y)giữa [0, K).

Nếu Y > 0Giả sử K = Yvà lặp lại quá trình cho đến khi Y = 0.

Quy tắc

  • Đầu vào phải được in lúc đầu
  • Định dạng đầu ra như bạn muốn
  • Chương trình của bạn phải kết thúc.
  • 0 phải là đầu ra cuối cùng, thay vào đó là một dòng trống 0

Nếu đệ trình là một chức năng, nó có thể trả về 0 ngoài việc in nó không?
Adám

1
@ Adám có, bạn cũng có thể quay lại
Luis felipe De jesus Munoz

Tôi có cần phải gieo RNG không?
SIGSTACKFAULT

Chúng tôi có thể in mà không có dấu phân cách?
Tít

Tôi tò mò. Thật dễ dàng để chứng minh rằng số bước trung bình mà chương trình này thực hiện trước khi kết thúc là H (K-1) + 1 trong đó H (K) là số hài của K'th . Với n = 1000, trung bình là 8.484 bước.
J.Doe

Câu trả lời:


19

Bình thường , 6 5 4 byte

.uOW

Hãy thử nó ở đây!

Làm thế nào nó hoạt động

.uOW Chương trình đầy đủ. Lấy một số nguyên từ STDIN và xuất danh sách thành STDOUT.
.u Điểm tích lũy cố định. Áp dụng hàm đã cho với giá trị ban đầu đã cho,
        được gán ngầm cho đầu vào, cho đến khi kết quả đã xảy ra 
        trước khi được tìm thấy. Trả về danh sách kết quả trung gian.
   W Ứng dụng có điều kiện. Nếu đối số (giá trị hiện tại) là trung thực, thì
        áp dụng các chức năng dưới đây, nếu không để nó không thay đổi.
  O Số nguyên ngẫu nhiên trong phạm vi [0, N).
        IOW: tại mỗi lần lặp của .u, gán một biến N cho giá trị hiện tại, bắt đầu
        với đầu vào. Nếu N không bằng 0, thì chọn số nguyên ngẫu nhiên trong [0, N), khác
        trả về N không đổi. Bất cứ khi nào chúng ta gặp 0, lần lặp tiếp theo cũng phải
        kết quả là 0 và do đó vòng lặp dừng ở đó.

1
Tôi đã thấy một cách để làm điều này trong Pyth nhưng tôi là người mới bắt đầu. Sự tôn trọng. Ngôn ngữ của tháng 8 có lẽ?
ElPedro

15

C (gcc) , 42 byte

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

Hãy thử trực tuyến!

Sử dụng logic ngắn mạch và.

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 (w / o in giá trị ban đầu)

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

Hãy thử trực tuyến!

Sử dụng logic ngắn mạch và.

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()%_không đồng nhất
njzk2

(nếu bạn không bị thuyết phục, hãy thử sử dụng xúc xắc 6 mặt để tạo giá trị [1,5] bằng phương pháp này.)
njzk2

3
Tôi hoàn toàn biết rằng rand () hầu như luôn bị sai lệch (do bị cắt bớt), nhưng tiêu chuẩn không đảm bảo điều đó (về lý thuyết RAND_MAX có thể là bội số của tất cả các số của chúng tôi, chỉ là may mắn: P mặc dù thường là ~ 65k ). Trong thực tế cho các phạm vi chúng tôi xử lý nó sẽ xuất hiện đủ ngẫu nhiên để không nổi bật so với các bài nộp tương tự trong thử thách này.
LambdaBeta

1
đó là từ thử thách "Xuất ra một số nguyên ngẫu nhiên đồng nhất", vì vậy, nói đúng ra, điều này không hợp lệ
njzk2

3
Nói đúng ra tất cả các ngôn ngữ ở đây đều sử dụng prng's. Không ai trong số họ sẽ đưa ra một số ngẫu nhiên thống nhất thực sự (sẽ yêu cầu một nguồn entropy hoàn hảo). Mặc dù nhiều cái đồng đều hơn cái này, nhưng điều đó không đáng chú ý trong các lần lặp log (k).
LambdaBeta

10

R , 66 60 56 43 41 byte

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

Hãy thử trực tuyến!


Tôi không nghĩ rằng bạn cần >0cat(n,"")(chuỗi trống) cũng sẽ hoạt động.
Giuseppe

Nhưng tôi nghĩ printlà hiệu quả hơn ở đây, vì nó trả về đối số của nó: 56 byte
Giuseppe

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

1
Tôi quên xóa dấu ngoặc nhọn, vì vậy bạn có thể lưu thêm 2 byte;) Hãy thử trực tuyến!
digEmAll

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

6

MATL , 6 byte

`tYrqt

Hãy thử trực tuyến!

Giải trình

`        % 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 là ngôn ngữ lập trình được tạo bởi người dùng Soaku .

REeErEErReEEreeEREEeEEree 

Hãy thử trực tuyến!

Giải trình:

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}

Hãy thử trực tuyến!

Khối mã ẩn danh trả về một danh sách các giá trị. Nếu bạn không quan tâm đến các số là phạm vi, bạn có thể làm:

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

cho 17 byte. Thật thú vị, một hàm ngẫu nhiên dựng sẵn khác roll, có cùng hành vi trong trường hợp này với cùng một lượng byte.



5

Thạch ,  4  3 byte

XƬ0

Đây là một liên kết đơn (hàm) in một mảng và trả về 0 .

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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.

Cuộc tấn công rất hay của 4 người!
ngm

1
Chúng ta sẽ không thích gạch bỏ 4 để trông giống như 4 thông thường, phải không?
Dennis

4

Brachylog , 8 byte

ẉ?ℕ₁-₁ṙ↰

Hãy thử trực tuyến!

Giải trình

ẉ          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

Đệ quy sẽ dừng lại một lần ?ℕ₁thất bại, đó là khi đầu vào là 0.



4

J, 13 byte

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

Trên tàu điện ngầm, vì vậy, xin lỗi vì thiếu TIO (hy vọng không có sự chính xác).

Xuất ra một danh sách các giá trị.

Có lẽ cách tiếp cận APL sẽ ngắn hơn, nhưng đây là những gì tôi nghĩ.

Làm thế nào nó hoạt động

^:a: áp dụng nhiều lần cho đến khi hội tụ, lưu trữ kết quả trung gian trong một mảng.

?số nguyên ngẫu nhiên trong phạm vi [0, K)cho Klớn hơn 0. Đối với 0, nó mang lại một số nguyên ngẫu nhiên trong phạm vi (0,1). Đối với một số dấu phẩy động, nó lỗi.

::]bắt lỗi cho đầu vào ?và thay vì lỗi, hãy xuất đầu vào gây ra lỗi.

}: loại bỏ giá trị cuối cùng trong mảng (điều này sao cho số dấu phẩy động không xuất ra).

Hãy thử trực tuyến!


Nó chỉ là tôi hoặc mã trả về cùng một đầu ra?
Luis felipe De jesus Munoz

@LuisfelipeDejesusMunoz một người hiểu rõ J hơn tôi có thể giải thích nhưng tôi nghĩ rằng RNG luôn bắt đầu với cùng một hạt giống. Cũng có hạt giống cố định ?., nhưng tôi không nghĩ rằng tôi đang sử dụng nó.
cole

@cole bạn đúng rồi.
Giô-na

4

JavaScript (ES6), 38 37 byte

-1 byte nhờ @Arnauld

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


Bạn có thể giảm math.random không? ví dụ: với codegolf.stackexchange.com/a/35648/67066
Marie

1
@Marie sử dụng new Date%nkhông thực sự hoạt động ở đây, vì nó không thay đổi đủ nhanh để hữu ích cho việc tạo nhiều số ngẫu nhiên
Herman L

4

C, 38 byte

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

Dùng thử trực tuyến

Ung dung

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

1
You can save a byte by replacing the ternary operator with a &&; also, you may want to consider seeding the RNG in your main function: Try it online!
ErikF

1
You can also get rid of the ternary altogether and terminate in an error. 34 bytes
Jo King

4

Pyth, 4 bytes

W
~O

Try it online!

This basically implements the algorithm:

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.

W begins a traditional while loop. The first statement after it is the loop condition and the second statement after it is the loop body. If the second statement is empty it becomes a no-op. This while works exactly like the Python while, so it will evaluate non-zero integers as True and zero as false.

The first statement after the while begins with the newline character. This corresponds to Pyth's "print and return with a newline" function. This takes one argument, which is then printed and also returned unmodified. This allows us to print the intermediate steps while also performing the needed operations.

The argument passed to this print function begins with ~ which is a bit special. If the character immediately after ~ is a variable it takes two arguments, otherwise it takes one. Since O is not a variable ~ will consume only one argument. ~ functions a bit like += does in many conventional languages, though the closest operator would be the post-increment operator ++ from C. You may know that x++ will be like using x as the current value, but thereafter x will be x+1. ~ is the same idea, but generalised to whatever the result of the first argument is. How it picks what variable to assign to will be addressed later.

The argument of ~ is O which is very simple. When its one argument is an integer O returns a value from 0 to one less than that integer uniformly at random.

Now you may have noticed O does not have an argument. Here the Pyth interpreter kindly fills in a guess, which here is the variable Q. Q has a special meaning in Pyth: whenever it is present in a program the Pyth program begins with assigning Q to the input of the program. Since this is the first variable occurring in ~'s argument Q is also now the variable that ~ will assign a value to.

Summed up our "readable" program might look like:

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

And one sample "run-through" might look like:

  1. Q = 5
  2. O returns 3, ~ returns 5, \n returns and prints 5 which is true
  3. Q = 3
  4. O returns 0, ~ returns 3, \n returns and prints 3 which is true
  5. Q=0
  6. O returns something irrelevant, ~ returns 0, \n returns and prints 0 which is false
  7. Q = something irrelevant
  8. Terminate

3

APL (Dyalog Unicode), 12 9 bytes

Anonymous tacit prefix function. Assumes ⎕IO (Index Origin) to be 0, which is default on many systems. Returns the final value (0) in addition to printing while run.

{⌊?⎕←⍵}⍣=

Try it online!

{}⍣= apply the following function until stable:

⎕←⍵ output the argument

? return a uniformly distributed random number in the range 0 through that–1

 round down (because ?0 gives a (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
Sự đồng thuận meta hiện tại là bạn không phải đếm các byte được sử dụng trên các cờ
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
Tôi cho rằng bạn có thể làm k=randi(k)-1cho một vài byte ít hơn.
Sanchise

2

Võng mạc , 21 byte

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

Hãy thử trực tuyến! Giải trình:

+

Lặp lại cho đến khi giá trị dừng thay đổi (tức là 0).

¶<)

In giá trị trước mỗi lần đi qua vòng lặp.

.+
*

Chuyển đổi sang unary.

L$`.
$.`

Tạo phạm vi và chuyển đổi thành thập phân.

G?`

Chọn một yếu tố ngẫu nhiên.


2

Bình thường , 6 7 byte

QWQ=OQQ

Hãy thử trực tuyến!

+1 để in giá trị đầu vào ban đầu.

Trong khi Q là trung thực, đặt Q là một số nguyên ngẫu nhiên giữa 0 và Q và in Q.

Không phải là câu trả lời ngắn nhất về Pyth nhưng tôi chỉ học và chỉ đăng bài vì các cuộc thảo luận gần đây về việc không có ai sử dụng Pyth nữa :)


2
Tôi quản lý để buộc bằng cách sử dụng giảm tích lũy nhưng giữ nó như một chương trình thủ tục. Cảm ơn vì động lực để làm việc trên một sân golf :)
FryAmTheEggman

Thật tuyệt. Vẫn đang cố gắng tìm ra cách thức (tại sao) nó hoạt động.
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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.