Randomisieren bis 0

29

Herausforderung

Sandkastenpfosten

Bei einer positiven Ganzzahl (K)Geben Sie eine gleichmäßig zufällige Ganzzahl (Y)zwischen aus [0, K).

Wenn Y > 0Angenommen , K = Yund wiederholen Sie den Vorgang , bis Y = 0.

Regeln

  • Die Eingabe muss zuerst gedruckt werden
  • Ausgabeformat wie Sie möchten
  • Ihr Programm muss beendet sein.
  • 0 muss die endgültige Ausgabe sein, optional eine Leerzeile 0
Luis Felipe De Jesus Munoz
quelle
Wenn die Übermittlung eine Funktion ist, kann sie zusätzlich zum Drucken 0 zurückgeben?
Adám
1
@ Adám ja, du kannst dazu zurückkehren
Luis felipe De jesus Munoz
Muss ich mein RNG aussäen?
SIGSTACKFAULT
Dürfen wir ohne Trennzeichen drucken?
Titus
Ich wurde neugierig. Es ist ziemlich einfach zu beweisen, dass die durchschnittliche Anzahl der Schritte, die dieses Programm benötigt, um zu beenden, H (K-1) + 1 ist, wobei H (K) die K'te harmonische Zahl ist . Für n = 1000 sind das durchschnittlich 8,484 Schritte.
J.Doe

Antworten:

19

Pyth , 6 5 4 Bytes

.uOW

Probieren Sie es hier aus!

Wie es funktioniert

.uOW Volles Programm. Nimmt eine Ganzzahl aus STDIN und gibt eine Liste an STDOUT aus.
.u Kumulativer Fixpunkt. Wenden Sie die gegebene Funktion mit einem gegebenen Anfangswert an,
        die implizit dem Eingang zugeordnet ist, bis ein Ergebnis vorliegt 
        bevor gefunden wird. Gibt die Liste der Zwischenergebnisse zurück.
   W Bedingte Anwendung. Wenn das Argument (der aktuelle Wert) wahr ist, dann
        Wenden Sie die unten stehende Funktion an, andernfalls lassen Sie sie unverändert.
  O Zufällige ganze Zahl im Bereich [0, N).
        IOW: Ordnen Sie bei jeder Iteration von .u dem aktuellen Wert beginnend eine Variable N zu
        mit der Eingabe. Wenn N nicht 0 ist, wählen Sie eine zufällige ganze Zahl in [0, N), sonst
        N unverändert zurückgeben. Immer wenn wir auf eine 0 stoßen, muss auch die nächste Iteration erfolgen
        führen zu einer 0, und daher stoppt die Schleife dort.
Mr. Xcoder
quelle
1
Ich habe in Pyth einen Weg gefunden, dies zu tun, aber ich bin ein Anfänger. Respekt. Sprache des Monats im August vielleicht?
ElPedro
15

C (gcc) , 42 Bytes

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

Probieren Sie es online!

Verwendet kurzgeschlossene logische und.

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 Bytes (ohne Druckanfangswert)

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

Probieren Sie es online!

Verwendet kurzgeschlossene logische und.

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
LambdaBeta
quelle
4
rand()%_ist nicht einheitlich
njzk2
(Wenn Sie nicht überzeugt sind, verwenden Sie einen 6-seitigen Würfel, um mit dieser Methode einen [1,5] -Wert zu generieren.)
njzk2
3
Ich bin mir völlig bewusst, dass rand () (aufgrund von Kürzungen) fast immer voreingenommen ist, aber der Standard garantiert es nicht (RAND_MAX könnte theoretisch ein Vielfaches aller unserer Zahlen sein, nur zum Glück: P, obwohl es normalerweise ~ 65k sind ). In der Praxis wird es für die Bereiche, mit denen wir uns befassen, ausreichend zufällig erscheinen, um sich bei dieser Herausforderung nicht von ähnlichen Einsendungen abzuheben.
LambdaBeta
1
Das ist von der Herausforderung "Ausgabe einer einheitlich zufälligen Ganzzahl", also genau genommen ist dies nicht gültig
njzk2
3
Genau genommen verwenden alle Sprachen hier PRNGs. Keiner von ihnen gibt eine echte einheitliche Zufallszahl (für die eine perfekte Entropiequelle erforderlich wäre). Während viele einheitlicher sind, fällt dies in log (k) -Iterationen nicht auf.
LambdaBeta
10

R , 66 60 56 43 41 Bytes

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

Probieren Sie es online!

ngm
quelle
Ich glaube nicht, dass Sie brauchen >0und cat(n,"")(leere Zeichenfolge) wird auch funktionieren.
Giuseppe
Aber ich denke, hier printist es effizienter, da es sein Argument zurückgibt: 56 Bytes
Giuseppe
Auch 56 Bytes:k=scan();while(x<-sample(1:k-1,1))k=c(x,k);cat(rev(k),0)
JAD
1
Ich habe vergessen, die geschweiften Klammern zu entfernen, damit Sie 2 weitere Bytes sparen können;) Probieren Sie es online!
digEmAll
2
39 Bytes:n=scan();while(print(n))n=sample(n,1)-1
Djhurio
6

MATL , 6 Bytes

`tYrqt

Probieren Sie es online!

Erläuterung

`        % 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)
Luis Mendo
quelle
6

Pepe , 25 Bytes

Pepe ist eine Programmiersprache, die vom Benutzer Soaku erstellt wurde .

REeErEErReEEreeEREEeEEree 

Probieren Sie es online!

Erläuterung:

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
nicht definiert
quelle
5

Perl 6 , 18 Bytes

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

Probieren Sie es online!

Anonymer Codeblock, der eine Liste von Werten zurückgibt. Wenn es Ihnen nichts ausmacht, dass die Zahlen Bereiche sind, können Sie Folgendes tun:

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

für 17 Bytes. Komischerweise hat eine andere eingebaute Zufallsfunktion rollin dieser Instanz das gleiche Verhalten für die gleiche Anzahl von Bytes.

Scherzen
quelle
5

Jelly,  4  3 bytes

XƬ0

This is a monadic link (function) that prints an array and returns 0.

Try it online!

How it works

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.
Dennis
quelle
Very nice strikethrough of the 4!
ngm
1
We wouldn't like crossed out 4 to look like regular 4, would we?
Dennis
4

Brachylog, 8 bytes

ẉ?ℕ₁-₁ṙ↰

Try it online!

Explanation

ẉ          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

The recursion will stop once ?ℕ₁ fails, that is, when the input is 0.

Fatalize
quelle
4

05AB1E, 8 7 bytes

Δ=L<Ω0M

Try it online!

Explanation

Δ         # 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
Emigna
quelle
1
Δ=ݨΩ0M is equivalent.
Magic Octopus Urn
4

J, 13 bytes

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

On the subway, so apologies for lack of TIO (hopefully there isn’t a lack of correctness).

Outputs a list of values.

Presumably the APL approach will be shorter, but this is what I thought of.

How it works

^:a: apply repeatedly until convergence, storing intermediate results in an array.

? random integer in range [0, K) for K greater than 0. For 0, it gives a random integer in range (0,1). For a floating point number, it errors.

::] catch an error for an input to ? and instead of erroring, output the input that caused the error.

}: get rid of the last value in the array (this is so that a floating point number isn’t output).

Try it online!

cole
quelle
It is just me or the code returns the same output?
Luis felipe De jesus Munoz
@LuisfelipeDejesusMunoz someone who knows J better than I might be able to explain but I think that RNG always starts with the same seed. There is also the fixed seed ?., but I don’t think I’m using that.
Cole
@cole du hast recht.
Jonah
4

JavaScript (ES6), 38 37 bytes

-1 byte thanks to @Arnauld

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

Herman L
quelle
Can you reduce the math.random at all? e.g. with codegolf.stackexchange.com/a/35648/67066
Marie
1
@Marie using new Date%n doesn't really work here, since it doesn't change fast enough to be useful for generating multiple random numbers
Herman L
4

C, 38 bytes

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

Try it online

Ungolfed

void f(int k){
    printf("%d ",k);
    if(k)
        f(rand()%k);
}
Geo
quelle
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
FryAmTheEggman
quelle
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)

Adám
quelle
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.

SIGSTACKFAULT
quelle
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  
qwr
quelle
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!

Luca Citi
quelle
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
pizzapants184
quelle
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
TFeld
quelle
"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.

eKKiM
quelle
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
Sasha
quelle
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
aaaaa says reinstate Monica
quelle
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.

Neil
quelle
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 :)

ElPedro
quelle
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

Haskell, 74 71 bytes

-3 bytes by actually doing what the specs say it should do.

import System.Random
f 0=pure[0]
f x=randomRIO(0::Int,x-1)>>=fmap(x:).f

Try it online!

ბიმო
quelle
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

ElPedro
quelle
2

Powershell, 36 32 bytes

-4 bytes thanks AdmBorkBork

filter f{$_;if($_){Random $_|f}}

Testscript:

filter f{$_;if($_){Random $_|f}}

100 |f

Output:

100
61
20
8
6
3
0
mazzy
quelle
2
The Get- is implied, so you can remove it for -4 bytes Try it online!
AdmBorkBork
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).

AdmBorkBork
quelle
"$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 :)

Lycea
quelle
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