# Output a random value from the last 16 values outputted

Output the numbers 1-16 (or any other set of 16 distinct items). Then, repeatedly, output a random value chosen uniformly from the last 16 items outputted.

After the same item is printed 16 times in a row, halt.

If a number appears multiple times in the last 16 values, it should have proportionally more chance to be chosen as the next number. If a number did not appear in the last 16 elements, it can't be chosen ever again.

0 bonus points to whoever can provide the probability distribution of each number becoming the last one standing.

• Can the first 16 items be separated with a space, and then the rest separated with a newline (like this)? Feb 1 at 12:45
• @TheThonnu No, I don't think that would feel like "one sequence" Feb 1 at 12:48
• After the same item is printed 16 times in a row or more, halt. How could the same item be printed more than 16 times if we halt as soon as it has appeared 16 times? Feb 1 at 12:49
• @KevinCruijssen probably yes, because OP suggested a version which outputs a list on my Python answer. Feb 1 at 16:33
• For 0 bonus points the odds of numbers 1, 2, 3, ... , 16 being the last one standing are 1 : 2 : 3 : ... : 16 Feb 1 at 18:41

# Python, 102 88 86 85 84 bytes

from random import*;*t,=range(16)
while~-len({*(x:=t[-16:])}):t+=choice(x),
print(t)


Attempt This Online!

• -14 thanks to mousetail
• -1 thanks to loopy walt

Prints a list of numbers from 0 to 15.

#### Commented

from random import*;     # Import the random module for later
*t,=range(16)            # Set t equal to [0, 1, ..., 15]
# ([* ... ] unpacks it into a list)
while~-len(              # Loop while the number of unique items
{*(x:=t[-16:])}):  # in the last 16 elements of t is not 1
# (setting x to the last 16 elements of t)
t+=choice(x),        # Append a random element of x to t
print(t)                 # At the end, output t

• 88 bytes Feb 1 at 13:32
• @mousetail thanks! I removed the space after import and changed the +=[...] to +=..., for another two bytes saved. Feb 1 at 13:35
• I think t=[*range(16)] can be *t,=range(16) for -1. Feb 2 at 2:54

# Ruby, 55 51 48 bytes

puts x=[*1..16];_,*x=x<<p(x.sample)while(x|x)[1]


Try it online!

• That's beautiful. Feb 2 at 16:46

# R, 66 61 bytes

x=Map(show,L<-1:16)
while(sd(L))L=c(L[-1],print(sample(L,1)))


Try it online!

### Explanation outline:

1. Map the show function over 1:16 (and save the vector to variable L).
2. We assign the result of the Map to x to avoid outputting its value (ugly list of nulls).
3. Then we sample one element from L and append to L[-1] (L without the first element).
4. Loop until sd(L)==0 (this means that the last 16 numbers are all the same).
• I don't think this stops when the same value is output 16 times in a row Feb 1 at 12:47
• @TheThonnu right, I didn't read the specs carefully enough. Thanks! Feb 1 at 12:52

# R, 52 bytes

a=b=16:1;while(sd(a[b]))a=c(sample(a[b],1),a);rev(a)


Try it online!

Full program that yields an R vector containing the sequence of values.
R displays this by default with index numbers (in square brackets) at the start of each line. If this is annoying, add 5 bytes more to wrap the output into a call to cat() like this.

# Vyxal, 151312 9 bytes

k6≬℅+Ḣ↔ƒ⋎


Try it Online! Outputs characters from the string "0123456789abcdef"

-3 thanks to emanresu

## Explained (old)

k6≬℅+Ḣ↔ḣvt∑+
k6           # The string "0123456789abcdef"
≬   ↔      # apply the following and collect results while invariant:
℅+        #  append a random item of the string to the string
Ḣ       #  remove the first character
ḣvt   # separate the first item from that list and get the tail of each remaining item
∑+ # join that into a single string and append to the previously separated head

• 11 without s Feb 1 at 15:40
• 9 Feb 2 at 8:04
• Also a 10 that doesn't quite work Feb 2 at 8:05

# Brachylog, 18 bytes

15⟦ẉ₂ᵐ{=|ṛRẉ&b,R↰}


Try it online!

15⟦                  The list [0, …, 15]
ẉ₂ᵐ               Map writeln
{           }  If
=               All elements of the list are equal, then stop
|            Else
ṛR            R is a random element of the list
Rẉ           writeln R
&b         Remove the first element of the list
,R       Append R to the list
↰      Recursive call on this list


# C (gcc), 105 bytes

j,k;a[16];f(i){for(k=i=16;a[--i]=i;);for(;k;j-(a[i++%16]=a[rand()%16])?k=16:--k)printf("%d ",j=a[i%16]);}


Try it online!

# Japt, 20 19 bytes

Far too long but seeing as Japt has no infinite loops and can't loop until invariant, it'll have to do for now.

Go
@òÎÌÊ¨G}a@pUsX ö


Test it

Go\n@òÎÌÊ¨G}a@pUsX ö
G                        :16
o                       :Range [0,G)
\n                     :Assign to variable U
@                    :Left function
ò                   :  Partition U between elements where
Î                  :    Sign of difference is truthy (non-zero)
Ì                 :  Last element
Ê                :  Length
¨G              :  >=16
}             :End function
a            :Run right function until left function returns true and return final result
@           :Right function, taking 0-based iteration index X as argument
p          :  Push to U
UsX       :    Slice U from index X
ö     :    Random element

• I never knew you could use a that way, I'll have to see if I can use that next time I try a "repeat until condition" challenge. Feb 1 at 21:10

# JavaScript (ES7), 74 bytes

Same algorithm as the other version, but using the weirder set "5368709124,false".

f=(s=2**29+[4,k=!1])=>/(.)\1{15}/.test(s)?s:f(s+s[Math.random()*16+k++|0])


Try it online!

### How?

$$\2^{29}=536870912\$$ contains all digits from $$\0\$$ to $$\9\$$ exactly once, except $$\4\$$. Adding [4,!1] forces a coercion to a string and appends "4", followed by a comma, followed by "false".

# JavaScript (ES6), 83 bytes

Uses the hexadecimal characters 0-9 and A-F.

f=(s=(k=0)+'123456789ABCDEF')=>/(.)\1{15}/.test(s)?s:f(s+s[Math.random()*16+k++|0])


Try it online!

### Commented

f = (                 // f is a recursive function taking:
s = (k = 0) +       //   s = output string
'123456789ABCDEF' //   k = counter
) =>                  //
/(.)\1{15}/.test(s)   // if s contains the same character repeated
?                     // 16 times in a row:
s                   //   stop and return s
:                     // else:
f(                  //   do a recursive call:
s +               //     append to s
s[                //     the character from s
Math.random()   //     whose index is randomly chosen in
* 16 + k++ | 0  //     [k .. k+15] (increment k afterwards)
]                 //     i.e. one of the last 16 characters
)                   //   end of recursive call


# 05AB1E--no-lazy, 15 14 bytes

16L€=[DΩ=ª¦DË#


Try it online!

• -1 thanks to Kevin Cruijssen

### Alternative 15 bytes solution (thanks to Kevin Cruijssen)

16L[D16.£©Ωª®Ë#


Try it Online!

#### Explanation

16L             # Push [1..16]
€=           # Print each item
[          # Start an infinite loop:
DΩ        #  Duplicate and push a random element of the list
=ª      #  Print and append to the list
¦     #  Remove the first item
DË#  #  If all items are equal, break

• Outputting as a list is apparently 15 bytes as well: 16L[D16.£©Ωª®Ë# Feb 1 at 16:34
• You can golf D», to €= (although does require the --no-lazy flag since we're printing inside a map) for -1 byte: try it online. Feb 1 at 16:35

# Python, 77 bytes

from random import*
t=range(16)
while t:T,*s=*t,choice(t);t=s[t==s:];print(T)


Attempt This Online!

Prints one number per line.

### How?

The two mildly clever bits are

1. the rolling tail end of the sequence is all equal if and only if it's equal to its next iteration
2. for the winding down it doesn't matter whether we truncate from the right (more logical) or the left (shorter) since all elements are equal

# Nibbles, 10 bytes (20 nibbles)*

/.,16>>:$=#$16$:/  *Nibbles is a pure functional language and has no random number capability. So, this program uses the hash-modulo-16 of the last 16 values after each pick to select the next index. This is pseudo-random, but obviously will be the same on each run of the program. To more-closely mimic PRNGs from other programming languages, we can select a 'salt' value for the hash, to act as a 'seed': this needs to be appended to the program, and, additionally, the otherwise-implicit variables of the program then need to be explicitly specified, costing +3 nibbles (+1.5 bytes, so 11.5 bytes not including the 'seed' itself). /.,16>>:$=#$16$:/
.                     # iterate while unique
,16                  # starting with 1..16:
:$# join the last list to =$       #   its element at index
## itself hashed 16 # modulo-16 / # now, fold over this list from the right: : # joining / # the (implicit) first element of the (implicit) left argument # to the (implicit) right argument  # J, 31 bytes (,1}._1{"1(}.,?@#{])^:a:)@i.@16  Try it online! 0 bonus points to whoever can provide the probability distribution of each number becoming the last one standing. ┌──┬──────┐ │0 │1/136 │ ├──┼──────┤ │1 │2/136 │ ├──┼──────┤ │2 │3/136 │ ├──┼──────┤ │3 │4/136 │ ├──┼──────┤ │4 │5/136 │ ├──┼──────┤ │5 │6/136 │ ├──┼──────┤ │6 │7/136 │ ├──┼──────┤ │7 │8/136 │ ├──┼──────┤ │8 │9/136 │ ├──┼──────┤ │9 │10/136│ ├──┼──────┤ │10│11/136│ ├──┼──────┤ │11│12/136│ ├──┼──────┤ │12│13/136│ ├──┼──────┤ │13│14/136│ ├──┼──────┤ │14│15/136│ ├──┼──────┤ │15│16/136│ └──┴──────┘  Proof: For example, the system of equations you'd solve for the n=3 case is: \begin{align} x_1 &= \frac{x_3}{3} \\ x_2 &= x_1 + \frac{x_3}{3} \\ x_3 &= x_2 + \frac{x_3}{3} \\ x_1 + x_2 + x_3 &= 1 \end{align} where $$\x_1\$$ is the chance that number in positon 1 wins, etc -- where 1, if it is not picked the first round, vanishes forever. The first equation represents that 1/3 of the time $$\x_1\$$ will be picked and move into position 3, and the rest of the time of vanish. Thus its "value" is 1/3 of $$\x_3\$$'s. Similarly, $$\x_2\$$ will always move into slot 1, where it has $$\x_1\$$ chance of winning, and 1/3 of the time will also move into slot 3, giving it $$\x_3\$$ chance of winning. And so on... • Surely (i+1)/136 would be a golfer way to express the probability:) – Simd Feb 2 at 7:40 • I can’t pass up a chance to use J’s box drawing… Feb 2 at 15:12 # Excel (ms365), 109 bytes I do hope that this could get OP's approval. Since volatility would stand in the way of using a list of elements, the only way I could think about a repetitive function that would auto-stop when last 16 elements are exactly the same is to use a custom function made with the name-manager. In this case my function is called 'Z': =LAMBDA(x,LET(y,RIGHT(x,16),IF(y=REPT(RIGHT(y),16),x,Z(x&MID(y,RANDBETWEEN(1,16),1)))))  Formula in A1: =Z("ABCDEFGHIJKLMNOP")  This would make for a combined total of 87 + 22 = 109 bytes. • I was really rooting for L. but K pulled through. Feb 1 at 20:56 # TI-Basic, 54 bytes For(I,1,16 Disp I End cumSum(1 or rand(16 While max(Ans≠max(Ans augment(ΔList(cumSum(Ans)),{Ans(randInt(1,16 Disp Ans(16 End  max(abs(ΔList(Ans can be used instead of max(Ans≠max(Ans alternatively. • Where does 54 bytes come from? I only calculated 7+2+1+7+6+15+5+1=44 tokens and 7 linebreaks, resulting in 51 bytes. Feb 3 at 13:43 • @user694733 ΔList( and cumSum( are worth 2 bytes each. Feb 3 at 13:49 # Pyth, 16 15 bytes pK<TGWt{=t+KpOK  Try it online! Thanks @isaacg for -1 byte ### Explanation  K<TG # K = "abcdefghijklmnop" (all but the last ten elements of the alphabet) p # print(K) Wt{ # while deduplicated K has more than one element pOK # print a random element of K +K # append this to K =t # remove the first element of K  • Switching from numbers to letters saves 1 byte: Try it online! Feb 2 at 18:25 # Retina, 43 bytes  16*. Y.L /(.)\1{15}/^+-16,@v(.).*
$&$1


Try it online! Uses ABCDEFGHIJKLMNOP. Explanation:


16*.


Insert 16 .s.

Y.L


Transliterate them to uppercase letters using a different letter each time.

/(.)\1{15}$/^+  Repeat until the last 16 letters are identical. -16,@v  Randomly choose between one of the last 16 overlapping matches. (.).*  Match any character and the rest of the string. $&$1  Append the initial character to the match, i.e. append it to the string. # Go, 177 bytes import."math/rand" func f(){N,M,l:=[]int{},1,16;for i:=1;i<17;i++{N=append(N,i);println(i)} for M<16{k:=Intn(16) x:=N[k] println(x) N=append(N[1:],x) if x!=l{l=x;M=1}else{M++}}}  Attempt This Online! # Charcoal, 24 bytes ≔…α¹⁶θθＷ∧⁻θ⌊θ‽θ«ι≔⁺Φθλιθ  Try it online! Link is to verbose version of code. Uses ABCDEFGHIJKLMNOP. Explanation: ≔…α¹⁶θθ  Get and print the first 16 uppercase letters. Ｗ∧⁻θ⌊θ‽θ«ι  While there is a choice of at least two different letters, pick and output a random letter from those remaining. ≔⁺Φθλιθ  Update the string of available letters. 23 bytes if the last letter does not need to be printed (it will be the same as the preceding 15): ≔…α¹⁶θＷ⁻θ⌊θ«→Ｐθ≔⁺Φθλ‽θθ  Try it online! Link is to verbose version of code. # Pip, 21 bytes P*Y,16T$=yY SyAE PRCy


Uses 0 to 15. Attempt This Online!

### Explanation

P*Y,16T$=yY SyAE PRCy ,16 ; Range(16) Y ; Yank, storing in y variable P* ; Print each T ; Loop till$=y             ; all elements of y are equal:
RCy  ;  Choose a random element of y
P     ;  Print it
AE       ;  Append that element to
Sy         ;  y without its first element
Y            ;  Yank that list as the new value of y


# Julia, 78 bytes

+_=(~x=last(x,16);s=rand(1:16,16);while(!allequal(~s));push!(s,rand(~s))end;s)


Attempt This Online! (Currently, the site doesn't seem evaluate any Julia code properly. Since last(x,n) postdates Julia 1.0, I don't know of any other online interpreter that would work.)

# Factor, 69 bytes

16 iota [ dup 16 tail* dup all-eq? ] [ random suffix ] until drop ...


Try it online!

# Raku, 56 bytes

|(1..16),{@_.tail(16).pick}...{~@_~~/(\d+)[' '$0]**15$/}


Try it online!

This is a sequence of the form initial-elements, { generator } ... { termination-check }.

• The initial elements are from the range 1..16, flattened with |.
• The generator takes the entire sequence generated so far in @_, then randomly picks an element from the last sixteen of them.
• The termination check stringifies the sequence, then checks that the string satisfies a regex: a space-separate sequence of digits that repeats sixteen times before the end of the string.

# Arturo, 74 70 bytes

a:0..15prints a until[prints[a\0]0=deviation a][a:@[sample a]++chop a]


Try it

a: 0..15              ; assign the range [0..15] to a
prints a              ; print the elements of a separated by spaces without a newline
until [               ; until the first block returns true, run the second block
prints [a\0]      ; print the first element of a followed by a space
0 = deviation a   ; is the standard deviation of a zero? i.e. are all elements equal?
] [
a:                ; to a, assign...
@[sample a]       ; a random element of a (as a list)
++                ; prepended to
chop a            ; a without its last element
]                     ; end until


## Zsh, 73 bytes

set {a..p};<<<${(F)@};while 17=$@[RANDOM%16+1];shift;<<<$16;((${#@:#$1}))  Try it online! I use single letters instead of up-to-two-digit numbers as the “16 distinct items”, which saves a byte. (It also gives extra flexibility, which I took advantage of in an earlier version of this answer with a more complex termination condition.) Expanded and commented: set {a..p} # set positional arguments 1=a, 2=b, ... <<<${(F)@}                    # join arguments with newline, call implicit cat
while
17=$@[RANDOM%16+1]; # append a random element shift; # remove the first element <<<$16;                     # print the last element
((${#@:#$1}))               # termination condition (see below)
# no loop body = empty loop body


For those unfamiliar with zsh: the positional arguments can be accessed through $1, $2, … like in other shells, and also through the variable @ which mostly behaves like an array. Zsh array indexes start at 1. RANDOM is a special variable that returns a random number each time it's accessed; fortunately the range 0..32767 is dividible by 16 so all values are equally likely modulo 16.

Now for the termination condition. It's the arithmetic expression ${#@:#$1}: the command is true if the integer expression has a nonzero value. The expression uses several parameter expansion features. From the outside in, first, we have ${#spec} to count the number of elements in the parameter expansion of spec. Inside, we have ${name:#pattern} which, when name is an array, removes the elements that match pattern. The name is @, i.e. the positional parameters. The pattern is $1. Thus we count the number of positional parameters that are not equal to the first one: this is 0 if and only if all the positional parameters are equal. • Nice. So the while condition exits if the anonymous function receives 0 arguments and thus evaluates to "false"? Feb 5 at 23:11 • @roblogic That's right. But since then I've realized that by using ${name:#pattern} instead of ${name#pattern}, I don't need the empty parameter elimination, and so I don't need an auxiliary function, which saves 3 characters (minus 1 lost for the extra :). Feb 6 at 0:05 # Swift 5.6+, 107 bytes var a=[_](1...16),i=0 a.map{print($0)}
while Set(a).count>1{a[i]=a.randomElement()!
print(a[i])
i=(i+1)%16}


Uses a as a circular buffer, overwriting a different position each run through the loop. For lack of a builtin "all elements are the same" operation, the loop condition converts it to a Set to count the number of unique elements.

Ungolfed:

var arr = Array(1...16)

for el in arr {
print(el)
}

var i = 0
while Set(arr).count > 1 {
let x = arr.randomElement()!
print(x)
arr[i] = x
i = (i + 1) % arr.count
}


# PHP 8, 110 bytes

$o=range(1,16);do$o[]=$o[count($o)-rand(1,16)];while(count(array_unique(array_slice($o,-16)))>1);print_r($o);


I wish PHP's array syntax was a little less verbose...

Works by building up an array by appending a random element from the last 16 elements, then printing it all at once, when the last 16 elements are all the same.

# Zsh, 101 bytes

seq 16|tee a;set shuf a
while shift;16=shuf -n1 a;<<<$16;s=(${(n)@});((s[1]<s[16]))&&<<<${(F)@}>a  Writes/reads from file a. Uses the shell $argv array to randomise and pick new values, and a sorted array $s to check equality. Whoops, the initial version incorrectly ran forever. And then the second version was not uniformly random. Fixed now. Thanks to @Gillies for -13 bytes. • Some local optimizations: set shuf a instead of assigning to argv; <<<${(F)@} instead of print -l $@; make the whole loop body the loop condition while shift;…;((s[1]<s[16]))&&<<<${(F)@}>a, for 101 bytes. But I found a different approach that's significantly shorter. Feb 4 at 20:40
• Thanks! So many great tips. Feb 5 at 8:40

# Java 8, 135 bytes

()->{int a,m=16,i=0,c=1,t[]=new int[m];for(;c<m;c=a==t[(i+++15)%m]?c+1:1)System.out.println(t[i%m]=a=i<m?i:t[(int)(Math.random()*m)]);}


Try it online!

Even if Java always loses by far, it was still a fun challenge to code!

• The best answer in each language wins. As long as there is no shorter answer in Java specifically you are a winner Feb 3 at 14:12

# CJam, 24 23 bytes

G,_:p;{_mR_p+(;__|,(}g;


Try it online!

Explanation

G,_:p;                        create and print an array [0-16)
{             }g        do...
_mR                      pick a random number from the last 16
_p+(;                 print, add to the list, and remove the oldest number
__|,(          ...while the number of unique numbers in the last 16 != 1
;       cleanup


(-1 byte) replacing 1- with (, courtesy of my bestie