# Randomly select a character, plinko-style

Let's see how good your language of choice is at selective randomness.

Given 4 characters, A, B, C, and D, or a string of 4 characters ABCD as input, output one of the characters with the following probabilities:

• A should have a 1/8 (12.5%) chance to be chosen
• B should have a 3/8 (37.5%) chance to be chosen
• C should have a 2/8 (25%) chance to be chosen
• D should have a 2/8 (25%) chance to be chosen

This is in-line with the following Plinko machine layout:

   ^
^ ^
^ ^ ^
A B \ /
^
C D


Your answer must make a genuine attempt at respecting the probabilities described. A proper explanation of how probabilities are computed in your answer (and why they respect the specs, disregarding pseudo-randomness and big numbers problems) is sufficient.

## Scoring

This is so fewest bytes in each language wins!

• Can we assume the built-in random function in our language of choice is random? Jul 17, 2017 at 15:14
• @Mr.Xcoder within reason, yes. Jul 17, 2017 at 15:21
• So, for clarity, the input is always exactly 4 characters, and it should assign probabilities to each in accordance with exactly the provided Plinko layout? Generating Plinko layouts or simulating them is entirely unnecessary as long as the probabilities are correct within the accuracy provided by your random source? Jul 17, 2017 at 16:15
• @KamilDrakari correct. Jul 17, 2017 at 16:27
• Not very useful due to its length, but I found out that the expression ceil(abs(i - 6)/ 2.0) will map an index from 0-7 to an index from 0-3 with the appropriate distribution (0 111 22 33) for this challenge... Jul 17, 2017 at 17:18

# Lean Mean Bean Machine, 5543 42 bytes

-13 bytes thanks to Alex Varga

  O
i
^
^ ^
\ ^ ^
i / U
ii
^
i U
U


Hope you guys don't mind me answering my own question after only 2 hours, but I highly doubt anybody else was planning on posting an answer in LMBM.

This literally just reflects the Plinko layout shown in the OP, flipped horizontally to cut down on unnecessary whitespace.

• I don't know how to test this, but this might work: gist.github.com/anonymous/e537edc8c89a72f3631ef765b352b98d Jul 18, 2017 at 14:44
• @AlexVarga ooh that works Jul 18, 2017 at 14:47
• Jul 18, 2017 at 15:50

# Jelly, 6 bytes

Ḋṁ7;ḢX


A monadic link taking a list of four characters and returning one with the probability distribution described.

Try it online!

### How?

Ḋṁ7;ḢX - Link: list of characters, s  e.g. ABCD
Ḋ      - dequeue s                         BCD
ṁ7    - mould like 7 (implicit range)     BCDBCDB
;   - concatenate                       BCDBCDBA
X - random choice                     Note that the above has 1*A, 3*B, 2*C, and 2*D

• Clever trick with the ṁ! Jul 17, 2017 at 15:30

# Cubix, 39242221 19 bytes

.<.^iD>D|@oioi.\i;U


View in the online interpreter!

This maps out to the following cube net:

    . <
. ^
i D > D | @ o i
o i . \ i ; U .
. .
. .


# Random Distribution Implementation Explanation

Cubix is a language in which an instruction pointer travels around the faces of a cube, executing the commands it encounters. The only form of randomness is the command D, which sends the IP in a random direction: an equal chance of 1/4 each way.

However, we can use this to generate the correct weighted probabilites: by using D twice. The first D has a 1/4 of heading to a second D. This second D, however, has two directions blocked off with arrows (> D <) which send the instruction pointer back to the D to choose another direction. This means there are only two possible directions from there, each with a 1/8 overall chance of happening. This can be used to generate the correct character, as shown in the diagram below:

(Note that, in the actual code, the arrow on the right is replaced with a mirror, |)

# Code Explanation

        . <
. ^
IP> i D > D | @ o i
o i . \ i ; U .
. .
. .


The instruction pointer starts on the right, at the character i, facing right. It executes this i, taking the first character as input, and then moves onto the D, beginning the random process shown above.

• Char A: In the case that the first D sends us east, and the second south, we need to print character A. This is already on stack from the first i. The following is executed:

• \ - Reflect the IP so it heads east
• i; - Take an input, then pop it again (no-op)
• U - Perform a U-turn, turning the IP left twice
• o - Output the TOS, character A
• @ - Terminate the program
• Char B: If either the first or second D head north, we need to generate character B, which will be the next input. Both paths execute the following commands:

• ^ - Head north
• < - Head west, wrapping round to...
• i - Take another input, character B
• o - Output the TOS, character B
• ; - Pop the TOS
• @ - Terminate the program
• Char C: If the first D sends us west, the following is executed:

• i - Take another input, character B
• i - Take another input, character C
• o - Output TOS, character C
• @ - Terminate the program
• Char D: If the first D sends us south, the following is executed:

• i - Take another input, character B
• .. - Two no-ops
• i - Take another input, character C
• | - This mirror reflects east-west, but the IP is heading north, so we pass through it.
• ^ - This joins up with the path taken for character B. However, because we have taken two inputs already, the fourth character (character D) will end up being printed.
• This is spectacular! I can't believe you managed to fit the proper probabilities and all four paths on a size-2 cube. I wonder if I can subscribe to a feed of Cubix answers so I don't miss them... Mar 13, 2018 at 1:33
• @ETHproductions Thank you, I'm sure there's a way to cut off a byte or two, but I'm also quite proud of this answer :) Mar 13, 2018 at 18:41

# Python, 50 bytes

lambda x:choice(x[:2]+x[1:]*2)
from random import*


An unnamed function taking and returning strings (or lists of characters).

Try it online!

### How?

random.choice chooses a random element from a list, so the function forms a string with the correct distribution, that is, given "ABCD", "ABCD"[:2] = "AB" plus "ABCD"[1:]*2 = "BCD"*2 = "BCDBCD" which is "ABBCDBCD".

• I found a way to golf my solution and then realised it's identical to yours, just in reverse order :/ Jul 17, 2017 at 15:44

# R, 31 bytes

sample(scan(,''),1,,c(1,3,2,2))


Reads the characters from stdin separated by spaces. sample draws random samples from its first input in quantity of the second input (so 1), (optional replacement argument), with weights given by the last argument.

Try it online!

Try it n times!

For the latter code, I sample n times (set n in the header) with replacement set to True (it's false by default), tabulate the results, and divide by n to see the relative probabilities of the inputs.

# PHP, 28 bytes

<?=$argn[5551>>2*rand(0,7)];  Run as pipe with -nR. 01112233 in base-4 is 5551 in decimal ... • 108 possible values with the same length ... 7030 is among my personal favorites. Jul 17, 2017 at 17:15 # Java 8, 53 44 bytes s->s[-~Math.abs((int)(Math.random()*8)-6)/2]  This is a Function<char[], Character>. Try it online! (this test program runs the above function 1,000,000 times and outputs the experimental probabilities of choosing A, B, C, and D). The general idea here is to find some way to map 0-7 to 0-3, such that 0 appears 1/8 times, 1 appears 3/8 times, 2 appears 2/8 times, and 3 appears 2/8 times. round(abs(k - 6) / 2.0)) works for this, where k is a random integer in the range [0,8). This results in the following mapping: k -> k - 6 -> abs(k-6) -> abs(k-6)/2 -> round(abs(k-6)/2) 0 -> -6 -> 6 -> 3 -> 3 1 -> -5 -> 5 -> 2.5 -> 3 2 -> -4 -> 4 -> 2 -> 2 3 -> -3 -> 3 -> 1.5 -> 2 4 -> -2 -> 2 -> 1 -> 1 5 -> -1 -> 1 -> 0.5 -> 1 6 -> 0 -> 0 -> 0 -> 0 7 -> 1 -> 1 -> 0.5 -> 1  Which, as you can see, results in the indices 0 111 22 33, which produces the desired probabilities of 1/8, 3/8, 2/8 and 2/8. But wait! How in the world does -~Math.abs(k-6)/2 achieve the same result (again, where k is a random integer in the range [0,8])? It's pretty simple actually... (x+1)/2 (integer division) is the same thing as round(x/2), and x + 1 is the same thing as -~x. Although x+1 and -~x are the same length, in the above function it is better to use -~x since it -~ takes precedence and thus does not require parenthesis. • I know it's been a while, but you can golf two bytes by changing the placement of the integer-cast (since Math.abs also accepts doubles as parameter): s->s[-~(int)Math.abs(Math.random()*8-6)/2] (42 bytes). Mar 14, 2018 at 14:39 # APL, 14 bytes (?8)⊃1 3 2 2\⊢  Input as a string. How? 1 3 2 2\⊢ - repeat each letter x times ('ABCD''ABBBCCDD') ⊃ - take the element at index .. (?8) - random 1-8 • Would you mind reviewing my J answer and letting me know if it can be improved? Jul 18, 2017 at 21:51 • 17 bytes – Adám Jul 18, 2017 at 21:56 • @Uriel Try it online! – Adám Jul 18, 2017 at 21:59 • @Uriel There is no such encoding. Either you go full UTF-8, or you count every character as two bytes (UTF-16), or you add 5 bytes for ⎕U2378. – Adám Jul 18, 2017 at 22:02 • @Adám oh, I see. then get Dyalog to replace some of these unneeded European accented letters for the new symbols, to save bytes! ;) Jul 18, 2017 at 22:04 # Charcoal, 11 bytes ‽⟦εεζζηηηθ⟧  Try it online! Link is to verbose version of code, although you hardly need it; ‽ picks a random element, ⟦⟧ creates a list, and the variables are those that get the appropriate input letters (in reverse order because I felt like it). # Pyth, 8 7 bytes O+@Q1t+  Uses the exact same algorithm as in my Python answer. Try it here! # Pyth, 10 8 bytes O+<Q2*2t  Uses the exact same algorithm as is Jonathan Allan's Python answer. Try it here! ### Explanation • O - Takes a random element of the String made by appending (with +): • <Q2 - The first two characters of the String. • *2t Double the full String (*2) except for the first character (t). Applying this algorithm for ABCD: • <Q2 takes AB. • *2t takes BCD and doubles it: BCDBCD. • + joins the two Strings: ABBCDBCD. • O takes a random character. -2 thanks to Leaky Nun (second solution) -1 thanks to mnemonic (first solution) • >Q1 becomes tQ, which becomes t. Jul 17, 2017 at 16:00 • You can save a byte on the second solution by replacing *2 with + and using the implicit input twice. – user48543 Mar 13, 2018 at 18:51 • @Mnemonic Thanks, I think I have’t used it because I thought of y instead, which doesn’t work for strings... Mar 13, 2018 at 19:11 # Jelly, 8 bytes 122b4⁸xX  Try it online! Remove the X to see "ABBBCCDD". The X chooses a random element. # C# (.NET Core), 76 55 bytes s=>(s+s[1]+s[1]+s[2]+s[3])[new System.Random().Next(8)]  Try it online! My first answer written directly on TIO using my mobile phone. Level up! Explanation: if the original string is "ABCD", the function creates the string "ABCDBBCD" and takes a random element from it. • Your program should take the characters as input from STDIN Jul 17, 2017 at 19:00 • @Mayube fixed, though it may still be golfed... Jul 17, 2017 at 20:15 # Javascript 35 bytes Takes a string ABCD as input, outputs A 1/8th of the time, B 3/8ths of the time, C 1/4th of the time, and D 1/4th of the time. x=>x[5551>>2*~~(Math.random()*8)&3]  ## Explanation x=>x[ // return character at index 5551 // 5551 is 0001010110101111 in binary // each pair of digits is a binary number 0-3 // represented x times // where x/8 is the probability of selecting // the character at the index >> // bitshift right by 2 * // two times ~~( // double-bitwise negate (convert to int, then // bitwise negate twice to get the floor for // positive numbers) Math.random() * 8 // select a random number from [0, 8) ) // total bitshift is a multiple of 2 from [0, 14] &3 // bitwise and with 3 (111 in binary) // to select a number from [0, 3] ]  # 05AB1E, 5 bytes ¦Ćì.R  Try it online! ### Explanation ¦Ćì.R Argument s "ABCD" ¦ Push s[1:] "BCD" Ć Enclose: Pop a, Push a + a[0] "BCDB" ì Pop a, Concatenate a and s "ABCDBCDB" .R Random pick  # ><>, 2522 19 bytes i_ixio;o ox</; ;\$o


Try it online!, or watch it at the fish playground!

A brief overview of ><>: it's a 2D language with a fish that swims through the code, executing instructions as it goes. If it reaches the edge of the code, it wraps to the other side. The fish starts in the top left corner, moving right. Randomness is tricky in ><>: the only random instruction is x, which sets the fish's direction randomly out of up, down, left and right (with equal probability).

At the start of the program, the fish reads in two characters of input with i_i (each i reads a character from STDIN to the stack, and _ is a horizontal mirror, which the fish ignores now). It then reaches an x.

If the x sends the fish rightwards, it reads in one more character (the third), prints it with o and halts with ;. The left direction is similar: the fish reads two more characters (so we're up to the fourth), wraps around to the right, prints the fourth character and halts. If the fish swims up, it wraps and prints the second character, before being reflected right by / and halting. If it swims down, it gets reflected left by the / and hits another x.

This time, two directions just send the fish back to the x (right with an arrow, <, and up with a mirror, _). The fish therefore has 1/2 chance of escaping this x in each of the other two directions. Leftwards prints the top character on the stack, which is the second one, but downwards first swaps the two elements on the stack with $, so this direction prints the first character. In summary, the third and fourth characters are printed with probability 1/4 each; the first character has probability 1/2 x 1/4 = 1/8; and the second character has probability 1/4 + 1/2 x 1/4 = 3/8. # 05AB1E, 8 bytes ìD1è0ǝ.R  Try it online!  # Implicit input | [A,B,C,D] ì # Prepend the input to itself | [A,B,C,D,A,B,C,D] D1è # Get the second character | [A,B,C,D,A,B,C,D], B 0ǝ # Replace the first character with this one | [B,B,C,D,A,B,C,D] .R # Pick a random character from this array | D  # MATL, 12 10 bytes l3HHvY"1Zr  Try it online! Or run it 1000 times (slightly modified code) and check the number of times each char appears. ### Explanation l3HH % Push 1, 3, 2, 2 v % Concatenate all stack contents into a column vector: [1; 3; 2; 2] Y" % Implicit input. Run-length decode (repeat chars specified number of times) 1Zr % Pick an entry with uniform probability. Implicit display  Changes in modified code: 1000:"Gl3HH4$vY"1Zr]vSY'

• 1000:"...] is a loop to repeat 1000 times.
• G makes sure the input is pushed at he beginning of each iteration.
• Results are accumulated on the stack across iterations. So v needs to be replaced by 4$v to concatenate only the top 4 numbers. • At the end of the loop, v concatenates the 1000 results into a vector, S sorts it, and Y' run-length encodes it. This gives the four letters and the number of times they have appeared. • Yep, looks to be fixed now Jul 17, 2017 at 15:40 • @Mayube Thanks for noticing! Jul 17, 2017 at 15:40 # 05AB1E, 6 bytes «À¨Ć.R  Try it online! Explanation Works for both lists and strings. « # concatenate input with itself À # rotate left ¨ # remove the last character/element Ć # enclose, append the head .R # pick a character/element at random  # C (gcc), 50 49 bytes i[8]={1,1,1,2,2,3,3};f(char*m){m=m[i[rand()%8]];}  Try it online! • ABCD is example input, your code should take 4 characters (or a string of length 4) as input Jul 17, 2017 at 15:54 • 34 bytes Aug 5, 2020 at 20:24 # Ruby, 343329 27 bytes Saved 2 bytes thanks to @Value Inc Input as four characters a=$**2
a[0]=a[1]
p a.sample


construct an array [B,B,C,D,A,B,C,D] and sample it.

try it online!

try it n times! (I converted it to a function to repeat it more easily, but the algorithm is the same)

• $* is an alias for ARGV. Jul 17, 2017 at 20:40 # Pyth, 7 bytes @z|O8 1  Test suite O8 generates a random number from 0 to 7. | ... 1 applies a logical or with 1, converting the 0 to a 1 and leaving everything else the same. The number at this stage is 1 2/8th of the time, and 2, 3, 4, 5, 6, 7 or 8 1/8 of the time. @z indexes into the input string at that position. The indexing is performed modulo the length of the string, so 4 indexes at position 0, 5 at position 1, and so on. The probabilities are: • Position 0: Random number 4. 1/8 of the time. • Position 1: Random number 0, 1 or 5. 3/8 of the time. • Position 2: Random number 2 or 6. 2/8 of the time. • Position 3: Random number 3 or 7. 2/8 of the time. # Javascript, 31 30 bytes / 23 bytes Seeing asgallant's earlier Javascript answer got me to thinking about JS. As he said: Takes a string ABCD as input, outputs A 1/8th of the time, B 3/8ths of the time, C 1/4th of the time, and D 1/4th of the time. Mine is: x=>(x+x)[Math.random()*8&7||1]  Explanation: x=>(x+x)[ // return character at index of doubled string ('ABCDABCD') Math.random()*8 // select a random number from [0, 8] &7 // bitwise-and to force to integer (0 to 7) ||1 // use it except if 0, then use 1 instead ]  From Math.random()*8&7 it breaks down as follows: A from 4 = 12.5% (1/8) B from 0,1,5 = 37.5% (3/8) C from 2,6 = 25% (1/4) D from 3,7 = 25% (1/4)  ## Version 2, 23 bytes But then thanks to Arnauld, who posted after me, when he said: If a time-dependent formula is allowed, we can just do: which, if it is indeed allowed, led me to: x=>(x+x)[new Date%8||1]  in which new Date%8 uses the same break-down table as above. And %8 could also be &7; take your pick. Thanks again, Arnauld. # ngn/apl, 10 bytes ⎕a[⌈/?2 4] ?2 4 chooses randomly a pair of numbers - the first among 0 1 and the second among 0 1 2 3 ⌈/ is "max reduce" - find the larger number ⎕a is the uppercase alphabet [ ] indexing note the chart for max(a,b) when a∊{0,1} and b∊{0,1,2,3}:  ┏━━━┯━━━┯━━━┯━━━┓ ┃b=0│b=1│b=2│b=3┃ ┏━━━╋━━━┿━━━┿━━━┿━━━┫ ┃a=0┃ 0 │ 1 │ 2 │ 3 ┃ ┠───╂───┼───┼───┼───┨ ┃a=1┃ 1 │ 1 │ 2 │ 3 ┃ ┗━━━┻━━━┷━━━┷━━━┷━━━┛  if a and b are chosen randomly and independently, we can substitute 0123=ABCD to get the desired probability distribution # Python 3, 64 55 51 bytes -9 bytes thanks to @ovs lambda s:choice((s*2)[1:]+s[1]) from random import*  Try it online! ## Explanation random.choice() gets a random character of the String, while (s*2)[1:]+s[1] creates BCDABCDB for an input of ABCD, which has 1/8 As, 2/8 Cs, 2/8 Ds and 3/8 Bs. • Use random.choice for 55 bytes: lambda s:choice((s[0]+s[1:]*3)[:8]) – ovs Jul 17, 2017 at 15:30 • @ovs Found a shorter way ^. Thanks for the choice() though. Jul 17, 2017 at 15:44 # QBIC, 27 bytes ?_s;+;+B+B+;+C+;+D,_r1,8|,1  ## Explanation ? PRINT _s A substring of ;+ A plus ;+B+B+ 3 instances of B plus ;+C+ 2 instances of C plus ;+D 2 instances of D plus ,_r1,8| from position x randomly chosen between 1 and 8 ,1 running for 1 character  # ><>, 56 bytes v ! " D C B A ; " o ! @ ! ^< x!^xv! @ v< @ o o ; ; o  Try it online! # Chip, 60 bytes )//Z )/\Z )\/^. )\x/Z )\\\+t |???~S |z* {'AabBCcdDEefFGghH  Try it online! The three ?'s each produce a random bit. On the first cycle, these bits are run through the switches above (/'s and \'s) to determine which value we are going to output from this table: 000 a 01_ b 0_1 b 10_ c 11_ d  (where _ can be either 0 or 1). We then walk along the input as necessary, printing and terminating when the correct value is reached. The big alphabetic blob at the end is copied wholesale from the cat program, this solution simply suppresses output and terminates to get the intended effect. # Ruby, 32 bytes Pretty straightforward..? ->s{s[[0,1,1,1,2,2,3,3].sample]}  Try it online! # Applesoft, 29 oops, 32 bytes A little "retrocomputing" example. Bear with me, I'm brand new at this. I gather that what is designated as the "input" need not be byte-counted itself. As stated in the OP, the input would be given as "ABCD". (I didn't initially realize that I needed to specify input being obtained, which added 4 bytes, while I golfed the rest down a byte.) INPUTI$:X=RND(1)*4:PRINTMID$(I$,(X<.5)+X+1,1)


The terms INPUT, RND, PRINT and MID$are each encoded internally as single-byte tokens. First, X is assigned a random value in the range 0 < X < 4. This is used to choose one of the characters from I$, according to (X < .5) + X + 1. Character-position value is taken as truncated evaluation of the expression. X < .5 adds 1 if X was less than .5, otherwise add 0. Results from X break down as follows:

A from .5 ≤ X < 1           = 12.5%
B from X < .5 or 1 ≤ X < 2  = 37.5%
C from 2 ≤ X < 3            = 25%
D from 3 ≤ X < 4            = 25%

• Welcome to Programming Puzzles and Code Golf! We require submissions here to be golfed as much as possible at least trivially, so that includes removing unnecessary whitespace (I apologize if the whitespace here is necessary). Additionally, I'm not sure of the standards about Applesoft, but I don't believe you are allowed to assume that those operators are single-byte tokens unless the internal representation is a single byte. Also, you may not assume that the input is stored in a variable; rather, you must actually take it as input, a command line argument, or a function parameter. Thanks! Jul 17, 2017 at 23:07
• @HyperNeutrino None of the whitespace was necessary, although space after "INPUT" and "PRINT" would've improved readability. It did happen that in this antique cybertongue spaces were traditionally displayed in the places I had them. For the tokens I mentioned it is indeed true that "internal representation is a single byte". Meanwhile, I golfed the code I had down a byte. Jul 17, 2017 at 23:55

# Common Lisp, 198 bytes

(setf *random-state*(make-random-state t))(defun f(L)(setf n(random 8))(cond((< n 1)(char L 0))((and(>= n 1)(< n 4))(char L 1))((and(>= n 4)(< n 6))(char L 2))((>= n 6)(char L 3))))(princ(f "ABCD"))


Try it online!

(setf *random-state* (make-random-state t))
(defun f(L)
(setf n (random 8))
(cond
((< n 1)
(char L 0))
((and (>= n 1)(< n 4))
(char L 1))
((and (>= n 4)(< n 6))
(char L 2))
((>= n 6)
(char L 3))
)
)
(princ (f "abcd"))