Randomly select a character, plinko-style

27

3

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!

Skidsdev

Posted 2017-07-17T15:11:22.003

Reputation: 9 656

Can we assume the built-in random function in our language of choice is random? – Mr. Xcoder – 2017-07-17T15:14:37.393

@Mr.Xcoder within reason, yes. – Skidsdev – 2017-07-17T15:21:58.797

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? – Kamil Drakari – 2017-07-17T16:15:21.440

1@KamilDrakari correct. – Skidsdev – 2017-07-17T16:27:15.147

2Not 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... – Socratic Phoenix – 2017-07-17T17:18:31.207

Can I do a spin-off of this, potentially accepting a well-formed plinko machine to do the output? – Magic Octopus Urn – 2018-03-13T21:17:30.280

@MagicOctopusUrn Provided it's different enough to not be dupe hammered, go for it! – Skidsdev – 2018-03-15T10:00:27.987

Answers

14

Lean Mean Bean Machine, 55 43 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.

Skidsdev

Posted 2017-07-17T15:11:22.003

Reputation: 9 656

I don't know how to test this, but this might work: https://gist.github.com/anonymous/e537edc8c89a72f3631ef765b352b98d

– Alex Varga – 2017-07-18T14:44:53.720

@AlexVarga ooh that works – Skidsdev – 2017-07-18T14:47:04.647

-1 byte: https://gist.github.com/anonymous/5ae3b2529f1d981ac3b320eb330f32e3

– Alex Varga – 2017-07-18T15:50:26.163

9

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
    Ḣ  - head s                            A
   ;   - concatenate                       BCDBCDBA
     X - random choice                     Note that the above has 1*A, 3*B, 2*C, and 2*D

Jonathan Allan

Posted 2017-07-17T15:11:22.003

Reputation: 67 804

Clever trick with the ! – Erik the Outgolfer – 2017-07-17T15:30:32.433

9

Cubix, 39 24 22 21 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:

Image showing probabilities of each direction

(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.

FlipTack

Posted 2017-07-17T15:11:22.003

Reputation: 13 242

2This 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... – ETHproductions – 2018-03-13T01:33:29.447

@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 :) – FlipTack – 2018-03-13T18:41:34.167

8

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".

Jonathan Allan

Posted 2017-07-17T15:11:22.003

Reputation: 67 804

I found a way to golf my solution and then realised it's identical to yours, just in reverse order :/ – Mr. Xcoder – 2017-07-17T15:44:10.753

6

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.

Giuseppe

Posted 2017-07-17T15:11:22.003

Reputation: 21 077

6

PHP, 28 bytes

<?=$argn[5551>>2*rand(0,7)];

Run as pipe with -nR.

01112233 in base-4 is 5551 in decimal ...

Titus

Posted 2017-07-17T15:11:22.003

Reputation: 13 814

108 possible values with the same length ... 7030 is among my personal favorites. – Titus – 2017-07-17T17:15:32.083

5

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

Uriel

Posted 2017-07-17T15:11:22.003

Reputation: 11 708

Would you mind reviewing my J answer and letting me know if it can be improved?

– Jonah – 2017-07-18T21:51:43.083

17 bytes – Adám – 2017-07-18T21:56:08.280

@Uriel Try it online!

– Adám – 2017-07-18T21:59:05.283

@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 – 2017-07-18T22:02:16.473

@Adám oh, I see. then get Dyalog to replace some of these unneeded European accented letters for the new symbols, to save bytes! ;) – Uriel – 2017-07-18T22:04:27.487

@Uriel Actually, Geoff suggested building me such a golfing version. But then it wouldn't be a publicly available language, and thus it would disqualify. However, we could make a thin cover which just substitutes ö§Öçî for ⍤⌸⍠⊆⍸

– Adám – 2017-07-18T22:08:30.127

5

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.

Socratic Phoenix

Posted 2017-07-17T15:11:22.003

Reputation: 1 629

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). – Kevin Cruijssen – 2018-03-14T14:39:45.993

4

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)

Mr. Xcoder

Posted 2017-07-17T15:11:22.003

Reputation: 39 774

>Q1 becomes tQ, which becomes t. – Leaky Nun – 2017-07-17T16:00:25.797

You can save a byte on the second solution by replacing *2 with + and using the implicit input twice. – None – 2018-03-13T18:51:00.980

@Mnemonic Thanks, I think I have’t used it because I thought of y instead, which doesn’t work for strings... – Mr. Xcoder – 2018-03-13T19:11:14.417

4

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).

Neil

Posted 2017-07-17T15:11:22.003

Reputation: 95 035

3

Jelly, 8 bytes

122b4⁸xX

Try it online!

Remove the X to see "ABBBCCDD". The X chooses a random element.

Leaky Nun

Posted 2017-07-17T15:11:22.003

Reputation: 45 011

3

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.

Charlie

Posted 2017-07-17T15:11:22.003

Reputation: 11 448

Your program should take the characters as input from STDIN – Skidsdev – 2017-07-17T19:00:46.203

@Mayube fixed, though it may still be golfed... – Charlie – 2017-07-17T20:15:25.930

3

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]
]

asgallant

Posted 2017-07-17T15:11:22.003

Reputation: 309

3

><>, 25 22 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.

Not a tree

Posted 2017-07-17T15:11:22.003

Reputation: 3 106

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

kalsowerus

Posted 2017-07-17T15:11:22.003

Reputation: 1 894

2

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

Riley

Posted 2017-07-17T15:11:22.003

Reputation: 11 345

2

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.

Luis Mendo

Posted 2017-07-17T15:11:22.003

Reputation: 87 464

Yep, looks to be fixed now – Skidsdev – 2017-07-17T15:40:20.090

@Mayube Thanks for noticing! – Luis Mendo – 2017-07-17T15:40:32.830

2

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!

cleblanc

Posted 2017-07-17T15:11:22.003

Reputation: 3 360

1ABCD is example input, your code should take 4 characters (or a string of length 4) as input – Skidsdev – 2017-07-17T15:54:43.737

2

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

Emigna

Posted 2017-07-17T15:11:22.003

Reputation: 50 798

2

Ruby, 34 33 29 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)

alexanderbird

Posted 2017-07-17T15:11:22.003

Reputation: 251

$* is an alias for ARGV. – Value Ink – 2017-07-17T20:40:35.907

2

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.

Alan Rat

Posted 2017-07-17T15:11:22.003

Reputation: 31

2

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.

isaacg

Posted 2017-07-17T15:11:22.003

Reputation: 39 268

2

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

ngn

Posted 2017-07-17T15:11:22.003

Reputation: 11 449

1

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.

Mr. Xcoder

Posted 2017-07-17T15:11:22.003

Reputation: 39 774

Use random.choice for 55 bytes: lambda s:choice((s[0]+s[1:]*3)[:8]) – ovs – 2017-07-17T15:30:11.460

@ovs Found a shorter way ^. Thanks for the choice() though. – Mr. Xcoder – 2017-07-17T15:44:51.550

1

Mathematica, 25 bytes

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

input

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

-23 bytes from @MarkS!

J42161217

Posted 2017-07-17T15:11:22.003

Reputation: 15 931

1The 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. – Mark S. – 2017-07-18T01:22:17.453

Whoops, I should have used @ to save a byte: RandomChoice@{##... – Mark S. – 2017-07-18T12:24:15.287

1

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

steenbergh

Posted 2017-07-17T15:11:22.003

Reputation: 7 772

1

><>, 56 bytes

v
!

"
D
C
B
A ;
" o
! @
! ^<
x!^xv!
@  v<
@  o
o  ;
;
o

Try it online!

KSmarts

Posted 2017-07-17T15:11:22.003

Reputation: 1 830

1

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.

Phlarx

Posted 2017-07-17T15:11:22.003

Reputation: 1 366

1

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[].

Olivier Grégoire

Posted 2017-07-17T15:11:22.003

Reputation: 10 647

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! – Socratic Phoenix – 2017-07-18T12:11:59.793

@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.

– Olivier Grégoire – 2017-07-18T12:20:06.433

1

Ruby, 32 bytes

Pretty straightforward..?

->s{s[[0,1,1,1,2,2,3,3].sample]}

Try it online!

daniero

Posted 2017-07-17T15:11:22.003

Reputation: 17 193

1

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%

Alan Rat

Posted 2017-07-17T15:11:22.003

Reputation: 31

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! – HyperNeutrino – 2017-07-17T23:07:36.243

@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. – Alan Rat – 2017-07-17T23:55:58.920

1

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!

Readable:

(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"))

Cheldon

Posted 2017-07-17T15:11:22.003

Reputation: 91

1

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.

daniero

Posted 2017-07-17T15:11:22.003

Reputation: 17 193

1

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!

Jonah

Posted 2017-07-17T15:11:22.003

Reputation: 8 729

looks pretty golfy to me. though I don't know much about J.. – Uriel – 2017-07-18T21:59:37.447

@Uriel thanks. sorry i assumed you knew J since you know APL well.... – Jonah – 2017-07-18T22:02:00.953

just the basics, I mostly transpile from APL... – Uriel – 2017-07-18T22:02:50.453

-1 byte: 1 3 2 2&#{~1?8:. – cole – 2018-03-13T18:49:07.540

0

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';}

xanoetux

Posted 2017-07-17T15:11:22.003

Reputation: 435

Could you use the ternary operator ...?...:... to have only one return and drastically reduce your number of bytes? – Olivier Grégoire – 2017-07-18T12:35:14.160

0

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#'

streetster

Posted 2017-07-17T15:11:22.003

Reputation: 3 635

0

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

geokavel

Posted 2017-07-17T15:11:22.003

Reputation: 6 352

0

05AB1E, 9 bytes

•20åÝ•.Rè

Try it online!

•20åÝ•   # Push 33221110.
     .R  # Randomly selected index.
       è # Character at that index.

Magic Octopus Urn

Posted 2017-07-17T15:11:22.003

Reputation: 19 422

0

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.

rahnema1

Posted 2017-07-17T15:11:22.003

Reputation: 5 435

0

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);

Arnauld

Posted 2017-07-17T15:11:22.003

Reputation: 111 334

0

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

Jeff Freeman

Posted 2017-07-17T15:11:22.003

Reputation: 221

0

TI-Basic, 25 bytes

sub(Ans,randInt(1,8),1
If int(2rand(Ans="A
"B

Timtech

Posted 2017-07-17T15:11:22.003

Reputation: 12 038

The characters should be taken as input. – Skidsdev – 2017-07-19T06:49:39.210

Ok, fixed that. – Timtech – 2017-07-19T16:21:33.340

0

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

Olivier Dulac

Posted 2017-07-17T15:11:22.003

Reputation: 209

the space after { is mandatory. – Olivier Dulac – 2017-07-19T12:15:44.727

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];} }' – Olivier Dulac – 2017-07-19T12:21:56.727

0

Perl 5, 26 bytes

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

Try it online!

Xcali

Posted 2017-07-17T15:11:22.003

Reputation: 7 671

0

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.

12Me21

Posted 2017-07-17T15:11:22.003

Reputation: 6 110