Randomisation jusqu'à 0

29

Défi

Poteau de bac à sable

Étant donné un entier positif, (K)affichez un entier uniformément aléatoire (Y)entre [0, K).

Si Y > 0supposez K = Yet répétez le processus jusqu'à Y = 0.

Règles

  • L'entrée doit être imprimée au début
  • Format de sortie comme vous le souhaitez
  • Votre programme doit se terminer.
  • 0 doit être la sortie finale, éventuellement une ligne vide à la place 0
Luis felipe De jesus Munoz
la source
Si la soumission est une fonction, peut-elle retourner 0 en plus de l'imprimer?
Adám
1
@ Adám oui, vous pouvez revenir en plus
Luis felipe De jesus Munoz
Dois-je semer mon RNG?
SIGSTACKFAULT
Pouvons-nous imprimer sans délimiteurs?
Titus
Je suis devenu curieux. Il est assez facile de prouver que le nombre moyen d'étapes que ce programme prend avant de se terminer est H (K-1) + 1 où H (K) est le Kème nombre harmonique . Pour n = 1000, cela fait 8,484 pas en moyenne.
J.Doe

Réponses:

19

Pyth , 6 5 4 octets

.uOW

Essayez-le ici!

Comment ça marche

.uOW Programme complet. Prend un entier de STDIN et sort une liste vers STDOUT.
.u Point fixe cumulatif. Appliquer la fonction donnée avec une valeur initiale donnée,
        qui est implicitement affecté à l'entrée, jusqu'à ce qu'un résultat qui se soit produit 
        avant est trouvé. Renvoie la liste des résultats intermédiaires.
   W Application conditionnelle. Si l'argument (la valeur actuelle) est vrai, alors
        appliquez la fonction ci-dessous, sinon laissez-la inchangée.
  O Entier aléatoire dans la plage [0, N).
        IOW: à chaque itération de .u, affectez une variable N à la valeur courante, en commençant
        avec l'entrée. Si N n'est pas 0, choisissez un entier aléatoire dans [0, N), sinon
        retourne N inchangé. Chaque fois que nous rencontrons un 0, la prochaine itération doit également
        entraîner un 0, et donc la boucle s'arrête là.
M. Xcoder
la source
1
J'ai vu un moyen de le faire en Pyth mais je suis un débutant. Le respect. La langue du mois d'août peut-être?
ElPedro
15

C (gcc) , 42 octets

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

Essayez-le en ligne!

Utilise les circuits logique et court-circuités.

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 octets (sans impression de la valeur initiale)

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

Essayez-le en ligne!

Utilise les circuits logique et court-circuités.

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
la source
4
rand()%_n'est pas uniforme
njzk2
(si vous n'êtes pas convaincu, essayez d'utiliser un dé à 6 faces pour générer une valeur [1,5] en utilisant cette méthode.)
njzk2
3
Je suis pleinement conscient que rand () est presque toujours biaisé (en raison de la troncature), mais la norme ne le garantit pas (RAND_MAX pourrait en théorie être un multiple de tous nos nombres, juste par chance: P bien que généralement il soit ~ 65k ). Dans la pratique, pour les plages que nous traitons, il apparaîtra suffisamment aléatoire pour ne pas se démarquer des soumissions similaires dans ce défi.
LambdaBeta
1
cela vient du défi "Afficher un entier uniformément aléatoire", donc, à proprement parler, ce n'est pas valide
njzk2
3
À proprement parler, toutes les langues utilisent ici des prng. Aucun d'eux ne donnera un vrai nombre aléatoire uniforme (ce qui nécessiterait une source parfaite d'entropie). Bien que beaucoup soient plus uniformes que cela, cela n'est pas perceptible dans les itérations log (k).
LambdaBeta
10

R , 66 60 56 43 41 octets

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

Essayez-le en ligne!

ngm
la source
Je ne pense pas que vous en ayez besoin >0et cat(n,"")(chaîne vide) fonctionnera également.
Giuseppe
Mais je pense que printc'est plus efficace ici, car il renvoie son argument: 56 octets
Giuseppe
Aussi 56 octets:k=scan();while(x<-sample(1:k-1,1))k=c(x,k);cat(rev(k),0)
JAD
1
J'ai oublié de supprimer les accolades, vous pouvez donc économiser 2 octets de plus;) Essayez-le en ligne!
digEmAll
2
39 octets:n=scan();while(print(n))n=sample(n,1)-1
djhurio
6

MATL , 6 octets

`tYrqt

Essayez-le en ligne!

Explication

`        % 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
la source
6

Pepe , 25 octets

Pepe est un langage de programmation créé par l'utilisateur Soaku .

REeErEErReEEreeEREEeEEree 

Essayez-le en ligne!

Explication:

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
indéfini
la source
5

Perl 6 , 18 octets

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

Essayez-le en ligne!

Bloc de code anonyme qui renvoie une liste de valeurs. Si cela ne vous dérange pas que les nombres soient des plages, vous pouvez faire:

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

pour 17 octets. Curieusement, une autre fonction aléatoire intégrée,, rolla le même comportement dans ce cas pour la même quantité d'octets.

Jo King
la source
5

Gelée ,  4  3 octets

XƬ0

Il s'agit d'un lien monadique (fonction) qui imprime un tableau et renvoie 0 .

Essayez-le en ligne!

Comment ça marche

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
la source
Très joli barré des 4!
ngm
1
Nous n'aimerions pas 4 barré pour ressembler à un 4 normal, n'est-ce pas?
Dennis
4

Brachylog , 8 octets

ẉ?ℕ₁-₁ṙ↰

Essayez-le en ligne!

Explication

ẉ          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

La récursivité s'arrêtera en cas d' ?ℕ₁échec, c'est-à-dire lorsque l'entrée est 0.

Fatalize
la source
4

05AB1E , 8 7 octets

Δ=L<Ω0M

Essayez-le en ligne!

Explication

Δ         # 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
la source
1
Δ=ݨΩ0Mest équivalent.
Magic Octopus Urn
4

J, 13 octets

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

Dans le métro, donc excuses pour le manque de TIO (j'espère qu'il n'y a pas de manque de justesse).

Affiche une liste de valeurs.

On peut supposer que l'approche APL sera plus courte, mais c'est ce à quoi j'ai pensé.

Comment ça marche

^:a: appliquer à plusieurs reprises jusqu'à la convergence, en stockant les résultats intermédiaires dans un tableau.

?entier aléatoire dans la plage [0, K)pour Ksupérieure à 0. Pour 0, il donne un nombre entier aléatoire dans la gamme (0,1). Pour un nombre à virgule flottante, il génère des erreurs.

::]attraper une erreur pour une entrée ?et au lieu de l'erreur, sortir l'entrée qui a causé l'erreur.

}: se débarrasser de la dernière valeur du tableau (c'est pour qu'un nombre à virgule flottante ne soit pas affiché).

Essayez-le en ligne!

cole
la source
C'est juste moi ou le code renvoie la même sortie?
Luis felipe De jesus Munoz
@LuisfelipeDejesusMunoz quelqu'un qui connaît mieux J que je pourrais être en mesure d'expliquer, mais je pense que RNG commence toujours par la même graine. Il y a aussi la graine fixe ?., mais je ne pense pas que j'utilise ça.
cole
@cole vous avez raison.
Jonah
4

JavaScript (ES6), 38 37 octets

-1 octet grâce à @Arnauld

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

Herman L
la source
Pouvez-vous réduire le math.random du tout? par exemple avec codegolf.stackexchange.com/a/35648/67066
Marie
1
L'utilisation de @Marie new Date%nne fonctionne pas vraiment ici, car elle ne change pas assez rapidement pour être utile pour générer plusieurs nombres aléatoires
Herman L
4

C, 38 octets

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

Essayez-le en ligne

Non golfé

void f(int k){
    printf("%d ",k);
    if(k)
        f(rand()%k);
}
Géo
la source
1
Vous pouvez enregistrer un octet en remplaçant l'opérateur ternaire par un &&; aussi, vous voudrez peut-être envisager d'amorcer le RNG dans votre mainfonction: Essayez-le en ligne!
ErikF
1
Vous pouvez également vous débarrasser complètement du ternaire et terminer par une erreur. 34 octets
Jo King
4

Pyth , 4 octets

W
~O

Essayez-le en ligne!

Cela implémente essentiellement l'algorithme:

QcontributionRepeunet1.tempQ2.Qunif{0,Q-1}3.Prjent(temp)Untjeltemp=0

Pour traduire le Pyth dans l'algorithme, nous pouvons principalement examiner ce que signifie chaque caractère. Puisque Pyth est écrit en notation préfixe (c'est-à * + 1 2 3- dire est (1 + 2) * 3), nous pouvons commencer par la gauche et remplir les arguments au fur et à mesure.

Wcommence une boucle while traditionnelle. La première instruction après c'est la condition de boucle et la deuxième instruction après c'est le corps de boucle. Si la deuxième instruction est vide, elle devient un no-op . Cela tandis que fonctionne exactement comme le tout Python, il évaluera donc les entiers non nuls comme Vrai et zéro comme faux.

La première instruction après le moment commence par le caractère de nouvelle ligne. Cela correspond à la fonction "imprimer et retourner avec une nouvelle ligne" de Pyth. Cela prend un argument, qui est ensuite imprimé et retourné non modifié. Cela nous permet d'imprimer les étapes intermédiaires tout en effectuant les opérations nécessaires.

L'argument passé à cette fonction d'impression commence par ~ce qui est un peu spécial. Si le caractère immédiatement après ~est une variable, il prend deux arguments, sinon il en prend un. Puisque On'est pas une variable ~ne consommera qu'un seul argument. ~fonctions un peu comme le +=fait dans de nombreuses langues classiques, bien que l'opérateur le plus proche serait l'opérateur de post-incrémentation ++de C. Vous savez peut-être que ce x++sera comme utiliser xcomme valeur actuelle, mais ce xsera le cas par la suite x+1. ~est la même idée, mais généralisée à quelque soit le résultat du premier argument. La façon dont il choisit la variable à attribuer sera traitée ultérieurement.

L'argument de ~est -ce Oqui est très simple. Lorsque son seul argument est un entier Oretourne une valeur de 0 à un de moins que cet entier uniformément au hasard.

Maintenant, vous avez peut-être remarqué qu'il On'a pas d'argument. Ici, l'interpréteur Pyth remplit gentiment une supposition, qui est ici la variable Q. Qa une signification particulière en Pyth: chaque fois qu'il est présent dans un programme, le programme Pyth commence par l'affectation Qà l'entrée du programme. Puisque c'est la première variable apparaissant dans ~l'argument de, Qc'est aussi maintenant la variable qui ~assignera une valeur à.

En résumé, notre programme "lisible" pourrait ressembler à ceci:

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

Et un échantillon "run-through" pourrait ressembler à:

  1. Q = 5
  2. Orenvoie 3, ~renvoie 5,\n retourne et imprime 5, ce qui est vrai
  3. Q = 3
  4. Oretourne 0, ~retourne 3, \nretourne et imprime 3 ce qui est vrai
  5. Q = 0
  6. Orenvoie quelque chose de non pertinent, ~retourne 0, \nretourne et imprime 0 ce qui est faux
  7. Q = quelque chose de non pertinent
  8. Mettre fin
FryAmTheEggman
la source
3

APL (Dyalog Unicode) , 12 9 octets

Fonction de préfixe tacite anonyme. Suppose que ⎕IO( I ndex O rigin) est 0, ce qui est le cas par défaut sur de nombreux systèmes. Renvoie la valeur finale (0) en plus de l'impression pendant l'exécution.

{⌊?⎕←⍵}⍣=

Essayez-le en ligne!

{}⍣= Appliquez la fonction suivante jusqu'à ce qu'elle soit stable:

⎕←⍵ sortir l'argument

? retourner un nombre aléatoire uniformément distribué dans la plage de 0 à ce – 1

 arrondi (car ?0donne un flottant (0,1))

Adam
la source
3

C (gcc) , 40 42 octets

Certains idiots ont oublié d'imprimer la valeur initiale en premier.

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

Pas de panique.

SIGSTACKFAULT
la source
Vous me ligoté, la question exige également que l' impression de la première K. Sans lui , je suis aussi 40. Vous pouvez également obtenir la version complète 42 conforme d'une manière similaire: f(K){while(K)printf("%d\n",K),K=rand()%K;}. Vous avez toujours mon +1 pour une solution égale!
LambdaBeta
Encore mieux:f(K){while(K)printf("%d\n",K,K=rand()%K);}
SIGSTACKFAULT
3

x86 + rdrand, 19 octets

Mise en œuvre simple. Prend l'entrée K ecxet les sorties dans un tampon 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
la source
3

Python 3 , 39 octets

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
la source
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
la source
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
la source
"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
la source
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
la source
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
la source
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
la source
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
la source
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!

ბიმო
la source
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
la source
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
la source
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
la source
"$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
la source
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