26
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ Can we assume the built-in random function in our language of choice is random? \$\endgroup\$ – Mr. Xcoder Jul 17 '17 at 15:14
  • \$\begingroup\$ @Mr.Xcoder within reason, yes. \$\endgroup\$ – Skidsdev Jul 17 '17 at 15:21
  • \$\begingroup\$ 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? \$\endgroup\$ – Kamil Drakari Jul 17 '17 at 16:15
  • 1
    \$\begingroup\$ @KamilDrakari correct. \$\endgroup\$ – Skidsdev Jul 17 '17 at 16:27
  • 1
    \$\begingroup\$ 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... \$\endgroup\$ – Socratic Phoenix Jul 17 '17 at 17:18

45 Answers 45

1
\$\begingroup\$

Java (OpenJDK 8), 40 38 bytes

s->s[5551>>2*(int)(Math.random()*8)&3]

Try it online!

5551 in base 10 is 01112233 in base 4. So let's randomly pick one of those base-4 digits using bit shift and selection, then pick the n-th character from the originating char[].

\$\endgroup\$
  • \$\begingroup\$ I've been outgolfed! I figured there was a way to do it with bitwise operators, but I don't really know much about them... Nice job! \$\endgroup\$ – Socratic Phoenix Jul 18 '17 at 12:11
  • \$\begingroup\$ @SocraticPhoenix Thank you! I figured the algorithms were different enough that I should make another answer. However, while I came up with this myself, I had not seen until this morning that the same idea had already been posted. \$\endgroup\$ – Olivier Grégoire Jul 18 '17 at 12:20
1
\$\begingroup\$

Mathematica, 25 bytes

RandomChoice@{##,##2,#2}&

input

["A", "B", "C", "D"]

-23 bytes from @MarkS!

\$\endgroup\$
  • 1
    \$\begingroup\$ The argument idea is very nice, but you don't need to introduce a random integer or use the byte-heavy StringTake. RandomChoice[{##,##2,#2}]& works in 26 bytes. \$\endgroup\$ – Mark S. Jul 18 '17 at 1:22
  • \$\begingroup\$ Whoops, I should have used @ to save a byte: RandomChoice@{##... \$\endgroup\$ – Mark S. Jul 18 '17 at 12:24
1
\$\begingroup\$

braingasm, 17 bytes

4[,>]<4r<#z[2r>].

Works like this:

4[,>]<             Input 4 bytes from stdin and stay in cell 3 (0-indexed).
        <          Move left ...
      4r           ... randomly between 0 (inclusive) and 4 (exclusive) times.
         #z[   ]   If we're at cell 0,
              >      move right ...
            2r       ... with 50% probability.
                .  Print the byte value of the cell.

Given the input ABCD, each character has 1/4 = 2/8 chance of being printed because of 4r, but if we selected A, we have 1/2 chance of printing B instead, giving A (1/4)/2 = 1/8 chance and B 1/4 + 1/8 = 3/8 chance.

\$\endgroup\$
1
\$\begingroup\$

J, 16 bytes

(1?8:){1 3 2 2&#

how?

  • 1 3 2 2&# - copy the input elementwise, ie, 1 copy of A, 3 copies of B, etc, yielding the list ABBBCCDD
  • 1?8: - choose 1 element at random from the list 0 1 2 3 4 5 6 7
  • { - "From", ie, choose from ABBBCCDD the random index generated by 1?8:

Try it online!

\$\endgroup\$
  • \$\begingroup\$ looks pretty golfy to me. though I don't know much about J.. \$\endgroup\$ – Uriel Jul 18 '17 at 21:59
  • \$\begingroup\$ @Uriel thanks. sorry i assumed you knew J since you know APL well.... \$\endgroup\$ – Jonah Jul 18 '17 at 22:02
  • \$\begingroup\$ just the basics, I mostly transpile from APL... \$\endgroup\$ – Uriel Jul 18 '17 at 22:02
  • \$\begingroup\$ -1 byte: 1 3 2 2&#{~1?8:. \$\endgroup\$ – cole Mar 13 '18 at 18:49
0
\$\begingroup\$

C, 106 bytes

int f(){int r=(int)random()%8;if(!r--)return 'A';if(--r-->0)if(r<2)return 'C';else return 'B';return 'D';}
\$\endgroup\$
  • \$\begingroup\$ Could you use the ternary operator ...?...:... to have only one return and drastically reduce your number of bytes? \$\endgroup\$ – Olivier Grégoire Jul 18 '17 at 12:35
0
\$\begingroup\$

q/kdb+, 15 13 bytes

Solution:

1?a[0],7#1_a:

Example:

q)1?a[0],7#1_a:"ABCD"
,"B"

Explanation:

This is pretty much a q version of the jelly solution. Create the list "ABCDBCDB" and then pick one item from it at random

Bonus:

Another q solution in 15 bytes, same style as the APL one:

1?(,/)1 3 2 2#'

A k version of this solution is 13 bytes:

1?,/1 3 2 2#'
\$\endgroup\$
0
\$\begingroup\$

CJam, 11 bytes

XZYY]q.*smR

Try it Online

XZYY]    e# add [1,3,2,2] to stack
q        e# add input string to stack
.*       e# element-wise multiply the two arrays. char * int in CJam = repeat character x times
s        e# flatten result to string
mR       e# pick random char from string
\$\endgroup\$
0
\$\begingroup\$

05AB1E, 9 bytes

•20åÝ•.Rè

Try it online!

•20åÝ•   # Push 33221110.
     .R  # Randomly selected index.
       è # Character at that index.
\$\endgroup\$
0
\$\begingroup\$

Octave, 30 28 bytes

@(S)S([1:4 2 2:4])(randi(8))

Try it online!

Previous answer:

@(S)S('ABBBCCDD'(randi(8))-64)

Try it online!

Input is taken as a string of 4 characters.

Explanation:

Instead of [1 2 2 2 3 3 4 4 ] we can write 'ABBBCCDD'-64 and randomly select one of indexes and use the index to extract the desired character from the string.

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 25 bytes / 30 bytes

In both following versions, we're looking for two positive integers m and n such that n MOD (m + i) MOD 4 gives us results in [0...3] at the expected frequencies for i in [0...7].


Version 1, 25 bytes

If a time-dependent formula is allowed, we can just do:

s=>s[11%(new Date%8+2)%4]

This one is using n = 11 (smallest possible value of n) and m = 2.

i | 2 + i | 11 % (2 + i) | 11 % (2 + i) % 4
--+-------+--------------+-----------------
0 |     2 |            1 |                1
1 |     3 |            2 |                2
2 |     4 |            3 |                3
3 |     5 |            1 |                1
4 |     6 |            5 |                1
5 |     7 |            4 |                0
6 |     8 |            3 |                3
7 |     9 |            2 |                2

Demo

let f =

s=>s[11%(new Date%8+2)%4]

for(stat = {A:0, B:0, C:0, D:0}, i = 0; i < 80000; i++) {
  stat[f("ABCD")]++;
}
console.log(stat);


Version 2, 30 bytes

With the native JavaScript PRNG -- which generates a floating-point number in [0...1) -- we'd rather do:

s=>s[21%(Math.random()*8|8)%4]

Here, we use n = 21 and m = 8 because it allows us to do the addition and isolate the integer part at the same time with Math.random()*8|8.

i | 8 + i | 21 % (8 + i) | 21 % (8 + i) % 4
--+-------+--------------+-----------------
0 |     8 |            5 |                1
1 |     9 |            3 |                3
2 |    10 |            1 |                1
3 |    11 |           10 |                2
4 |    12 |            9 |                1
5 |    13 |            8 |                0
6 |    14 |            7 |                3
7 |    15 |            6 |                2

Demo

let f =

s=>s[21%(Math.random()*8|8)%4]

for(stat = {A:0, B:0, C:0, D:0}, i = 0; i < 80000; i++) {
  stat[f("ABCD")]++;
}
console.log(stat);

\$\endgroup\$
0
\$\begingroup\$

PowerShell, 64 bytes

$args|%{($_-replace '(^.)(.)',"`$1`$2`$2`$2$'")[(Get-Random)%8]}

Try it online!

It replaces the string abcd with abbbcdcd using regex witchcraft and then randomizes which of the eight characters it chooses. The regex is expensive; it requires a backtick per grouping, so there may be a better method using recursive lookups.

Here's a quick explanation of the regex:

For input abcd the full match is ab, grouping $1 is 'a', grouping $2 is 'b', and $' (note quote, not backtick) returns everything after the full match. Then, the pattern $1$2$2$2$' is substituted for the full match: abcd goes to $1$2$2$2$' + cd = abbbcdcd

\$\endgroup\$
0
\$\begingroup\$

Bash, 52 bytes

f(){ c=$1$2$2$2$3$3$4$4;echo ${c:$(($RANDOM%8)):1};}

Usage exemple:

$ f a b c d
b
$ f a b c d
d
$ f a b c d
b
$ f a b c d
a
\$\endgroup\$
  • \$\begingroup\$ the space after { is mandatory. \$\endgroup\$ – Olivier Dulac Jul 19 '17 at 12:15
  • \$\begingroup\$ on 100000 iterations : a:12.41% , b 37.65%, c 24.93%, d 24,99% . with for i in $(seq 1 100000); do f a b c d ; done | awk '{ t[$1]++ } END { for(i in t){ print i " : " t[i];} }' \$\endgroup\$ – Olivier Dulac Jul 19 '17 at 12:21
0
\$\begingroup\$

TI-Basic, 25 bytes

sub(Ans,randInt(1,8),1
If int(2rand(Ans="A
"B
\$\endgroup\$
  • \$\begingroup\$ The characters should be taken as input. \$\endgroup\$ – Skidsdev Jul 19 '17 at 6:49
  • \$\begingroup\$ Ok, fixed that. \$\endgroup\$ – Timtech Jul 19 '17 at 16:21
0
\$\begingroup\$

Perl 5, 26 bytes

say((A..D,B..D,B)[rand 8])

Try it online!

\$\endgroup\$
0
\$\begingroup\$

SmileBASIC, 31 bytes

LINPUT S$N=RND(8)?S$[N+!N*2>>1]

Pick a number from 0 to 7, add 2 if it's 0, then divide by 2.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.