随机选择plinko样式的字符


27

让我们看看您选择的语言在选择性随机方面的表现如何。

给定4个字符,ABC,和D,或4个字符的字符串ABCD 作为输入,具有以下概率的字符输出之一:

  • A 应该有1/8(12.5%)的机会被选中
  • B 应该有3/8(37.5%)的机会被选中
  • C 应该有2/8(25%)的机会被选中
  • D 应该有2/8(25%)的机会被选中

这与以下Plinko机器布局一致:

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

您的答案必须真正地尝试遵守所述的概率。正确解释您的答案中的概率是如何计算的(以及为什么它们尊重规范,而忽略伪随机和大数问题)就足够了。

计分

这是因此每种语言中最少的字节会获胜!


我们可以假设我们选择的语言中内置的随机函数是随机的吗?
Xcoder先生

@ Mr.Xcoder是有原因的,是的。
Skidsdev

因此,为清楚起见,输入始终正好是4个字符,并且应该根据提供的Plinko布局为每个字符正确分配概率吗?只要概率在您的随机源提供的精度范围内是正确的,就完全不需要生成Plinko布局或对其进行仿真?
卡米尔·德拉科里

1
@KamilDrakari正确。
Skidsdev

2
由于它的长度,它不是很有用,但是我发现该表达式ceil(abs(i - 6)/ 2.0)会将索引from映射0-7到具有0-3适当分布(0 111 22 33)的索引from 来应对这一挑战……
Socratic Phoenix

Answers:


14

精瘦豆机55 43 42字节

-13个字节,感谢Alex Varga

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

希望你们不要介意我仅在2小时后回答我自己的问题,但是我非常怀疑其他人是否打算在LMBM中发布答案。

从字面上看,这仅反映了OP中显示的Plinko布局,可水平翻转以减少不必要的空白。


我不知道该如何测试,但这可能有用
Alex Varga

@AlexVarga ooh起作用了
Skidsdev'17



9

Cubix39 24 22 21 19字节

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

在在线翻译中查看!

这映射到以下多维数据集网:

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

随机分布实现说明

Cubix是一种语言,指令指针在该语言中绕着立方体的面运行,执行它遇到的命令。随机性的唯一形式是命令D,它沿随机方向发送IP:1/4每种方式的机会均等。

但是,我们可以使用它来生成正确的加权概率:使用D两次。第D一个1/4走向第二个DD但是,第二个方向有两个被箭头(> D <)遮挡的方向,这些方向将指令指针发送回D以选择另一个方向。这意味着从那里只有两个可能的方向,每个方向都有1/8发生的可能性。可以用来生成正确的字符,如下图所示:

该图显示了每个方向的概率

(请注意,在实际代码中,右侧的箭头已替换为镜像,|

代码说明

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

指令指针从右边的字符开始i,朝右。它i以第一个字符作为输入执行此操作,然后移至D,开始上述随机过程。

  • 字符A:如果第一个D将我们发送到东方,第二个将我们发送到南方,我们需要打印字符A。这已经从第一个字符开始堆叠了i。执行以下命令:

    • \ -反映IP,让它向东
    • i; -进行输入,然后再次弹出(无操作)
    • U -掉头,将IP左移两次
    • o -输出TOS,字符A
    • @ -终止程序
  • 字符B:如果第一个或第二个D向北,我们需要生成字符B,这将是下一个输入。这两个路径都执行以下命令:

    • ^ -往北走
    • < -往西走,绕到...
    • i -再次输入字符B
    • o -输出TOS,字符B
    • ; -弹出TOS
    • @ -终止程序
  • 字符C:如果第一个D将我们送往西部,则将执行以下操作:

    • i -再次输入字符B
    • i -再输入一个字符C
    • o -输出TOS,字符C
    • @ -终止程序
  • 字符D:如果第一个D将我们送往南方,则将执行以下操作:

    • i -再次输入字符B
    • .. -两个人
    • i -再输入一个字符C
    • | -此镜像反射了东西方向,但是IP向北移动,因此我们通过了它。
    • ^ -这与字符B的路径结合在一起。但是,由于我们已经进行了两次输入,因此第四个字符(字符D)将最终被打印出来。

2
这太壮观了!我简直不敢相信您设法将适当的概率所有四个路径都放在2号立方体上。我想知道我是否可以订阅Cubix答案的提要,这样我就不会错过他们...
ETHproductions

@ETHproductions谢谢,我确定有办法减少一两个字节,但是我也为这个答案感到骄傲:)
FlipTack

8

Python,50个字节

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

一个未命名的函数,用于接收和返回字符串(或字符列表)。

在线尝试!

怎么样?

random.choice从列表中选择一个随机元素,因此函数形成与正确的分配,即给定一个字符串"ABCD""ABCD"[:2] = "AB"再加上"ABCD"[1:]*2 = "BCD"*2 = "BCDBCD"这是"ABBCDBCD"


我找到了打高尔夫球的方法,然后意识到与您的方法完全相同,只是顺序相反:/
Xcoder先生

6

R,31个字节

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

stdin空格中读取字符。sample从第二个输入(so 1)的数量中抽取第一个输入的随机样本(可选的替换参数),权重由最后一个参数给出。

在线尝试!

尝试n几次!

对于后一个代码,我采样n时间(n在标头中设置),并将替换设置为True(默认情况下为false),将结果制成表格,然后除以n查看输入的相对概率。


6

PHP,28字节

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

与一起作为管道运行-nR

01112233在base-4中是5551十进制...


7030我个人最喜欢108个相同长度的可能值。
泰特斯

5

Java 8,53 44字节

s->s[-~Math.abs((int)(Math.random()*8)-6)/2]

这是一个Function<char[], Character>

在线尝试!(此测试程序运行上述功能1,000,000次并输出的实验概率选择ABC,和D)。

这里的总体思路是找到某种映射0-7到的方法0-3,例如0出现1/8时间,1出现3/8时间,2出现2/8时间和3出现2/8时间。round(abs(k - 6) / 2.0))为此工作,其中k是范围内的随机整数[0,8)。这将导致以下映射:

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

其中,你可以看到,导致指数0 111 22 33,其产生期望的概率1/83/82/82/8

可是等等!到底如何-~Math.abs(k-6)/2达到相同的结果(再次,k范围内的随机整数在哪里[0,8])?实际上,这非常简单... (x+1)/2(整数除法)与round(x/2)x + 1是相同的事物-~x。尽管x+1-~x的长度相同,但是在上面的函数中最好使用-~x它,因为它-~具有优先权,因此不需要括号。


我知道它已经有一段时间,但你可以打高尔夫球两个字节通过改变整铸的位置(因为Math.abs也接受兼作参数): s->s[-~(int)Math.abs(Math.random()*8-6)/2]42个字节)。
凯文·克鲁伊森

5

APL,14个字节

(?8)⊃1 3 2 2\⊢

输入为字符串。

怎么样?

1 3 2 2\⊢-每个字母重复x次('ABCD''ABBBCCDD'

-以索引..处的元素

(?8) -随机1-8


您介意查看我的J答案并让我知道是否可以改善它吗?
乔纳



@Uriel没有这种编码。您可以使用完整的UTF-8,或者将每个字符计为两个字节(UTF-16),或者为添加5个字节⎕U2378
亚当

@Adám哦,我明白了。然后让Dyalog将这些不需要的带有欧洲重音符号的字母替换为新符号,以节省字节!;)
Uriel

4

木炭,11字节

‽⟦εεζζηηηθ⟧

在线尝试!链接是冗长的代码版本,尽管您几乎不需要它。选择一个随机元素,⟦⟧创建一个列表,变量是那些获得适当输入字母的变量(以相反的顺序,因为我感觉很喜欢)。


4

Pyth8 7字节

O+@Q1t+

使用与我的Python答案完全相同的算法。

在这里尝试!

Pyth10 8字节

O+<Q2*2t

使用与Jonathan Allan的Python答案完全相同的算法。

在这里尝试!


说明

  • O-接受通过附加(带有+)制成的String的随机元素:

    • <Q2 -字符串的前两个字符。
    • *2t*2将第一个字符(t)除外的完整字符串()加倍。

将此算法应用于ABCD

  • <Q2需要AB
  • *2t需要BCD和双打它:BCDBCD
  • +连接两个字符串:ABBCDBCD
  • O 带有一个随机字符。

-2感谢Leaky Nun(第二个解决方案)

-1感谢助记符(第一个解决方案)


>Q1成为tQ,成为t
Leaky Nun

您可以通过更换节省第二个解决方案的一个字节*2+使用隐式输入的两倍。

@Mnemonic谢谢,我想我没有使用它,因为我想到了y,它不适用于字符串...
Xcoder先生,18年


3

C#(.NET Core)76 55字节

s=>(s+s[1]+s[1]+s[2]+s[3])[new System.Random().Next(8)]

在线尝试!

我的第一个答案是使用手机直接写在TIO上的。升级!

说明:如果原始字符串是“ ABCD”,则该函数将创建字符串“ ABCDBBCD”并从中获取随机元素。


您的程序应将字符作为STDIN的输入
-Skidsdev

@Mayube修复了,尽管它可能仍会打高尔夫球……
查理

3

Javascript 35字节

采用字符串ABCD作为输入,输出A的时间的1/8,B时间3 / 3/8,C的时间的1/4,和D的时间的1/4。

x=>x[5551>>2*~~(Math.random()*8)&3]

说明

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

3

05AB1E,5个字节

¦Ćì.R

在线尝试!

说明

¦Ćì.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

3

> <>25 22 19字节

i_ixio;o
ox</;
;\$o

在线尝试!或在鱼游乐场观看!

> <>的简要概述:这是一种带有鱼的2D语言,它在代码中游走,并随其执行指令。如果到达代码边缘,则换行到另一侧。鱼从左上角开始,向右移动。> <>中的随机性是棘手的:唯一的随机指令是x,它随机设置鱼的方向,上下,左右和概率均等。

在程序开始时,鱼将读取带有两个字符的输入i_i(每个鱼i从STDIN读取一个字符到堆栈,并且_是一个水平镜像,鱼现在会忽略它)。然后到达x

如果x发件人向右发送鱼,它会再读一个字符(第三个字符),然后用打印o并暂停;。左方向相似:这条鱼再读两个字符(所以我们最多到第四个字符),环绕到右边,打印第四个字符并暂停。如果鱼游动了,它会包裹并打印第二个字符,然后再被反射/并停下来。如果向下游泳,它将被反射/并撞向另一个x

这次,两个方向只是将鱼送回了x(向右带箭头,向后<带镜子_)。因此,鱼x在其他两个方向中的每个方向都有1/2的机会逃逸。向左打印堆栈上的顶部字符,这是第二个字符,但是向下$打印时,先用交换堆栈上的两个元素,所以此方向将打印第一个字符。

总之,第三个和第四个字符的打印概率分别为1/4;第一个字符的概率为1/2 x 1/4 = 1/8;第二个字符的概率为1/4 + 1/2 x 1/4 = 3/8。


2

05AB1E,8个字节

ìD1è0ǝ.R

在线尝试!

         # 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

2

MATL12个 10字节

l3HHvY"1Zr

在线尝试!运行1000次(略作修改的代码),然后检查每个字符出现的次数。

说明

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

修改后的代码中的更改: 1000:"Gl3HH4$vY"1Zr]vSY'

  • 1000:"...]是重复1000时间的循环。
  • G 确保在每次迭代开始时都推送输入。
  • 结果在迭代之间累积在堆栈上。因此v需要替换4$v为仅连接顶部4数字。
  • 在循环的最后,v1000结果连接成一个向量,对其进行S排序,然后对它进行Y'游程编码。这给出了四个字母以及它们出现的次数。

是的,现在应该解决
Skidsdev

@Mayube感谢您的关注!
路易斯·门多

2

05AB1E,6个字节

«À¨Ć.R

在线尝试!

说明

适用于列表和字符串。

«       # concatenate input with itself
 À      # rotate left
  ¨     # remove the last character/element
   Ć    # enclose, append the head
    .R  # pick a character/element at random


2

Ruby,34 33 29 27字节

@Value Inc节省了2个字节

输入为四个字符

a=$**2
a[0]=a[1]
p a.sample

构造一个数组[B,B,C,D,A,B,C,D]并对其进行采样。

在线尝试!

试试吧n(我将其转换为函数,以便更轻松地重复它,但算法相同)


$*是的别名ARGV
价值墨水

2

Pyth,7个字节

@z|O8 1

测试套件

O8生成一个从0到7的随机数。| ... 1应用逻辑或为1,将0转换为1,并使其他所有内容相同。此阶段的数字是时间的1 2/8,是时间的2、3、4、5、6、7或8 1/8。

@z在该位置索引到输入字符串。索引是按字符串长度的模数执行的,因此在位置0处有4个索引,在位置1处有5个索引,依此类推。

概率是:

  • 位置0:随机数4。1/ 8的时间。

  • 位置1:随机数字0、1或5。3/ 8的时间。

  • 位置2:随机数2或6。2/ 8的时间。

  • 位置3:时间为3或7的随机数。2/8。


2

Javascript,31个 30字节/ 23个字节

看到asgallant之前的Javascript答案后,我开始思考JS。正如他所说:

采用字符串ABCD作为输入,输出A的时间的1/8,B 时间3 / 3/8,C的时间的1/4,和D的时间的1/4。

我的是:

x=>(x+x)[Math.random()*8&7||1]

说明:

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
        ]

从中Math.random()*8&7分解如下:

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)

版本2,23个字节

但是要感谢Arnauld,他在我后面发帖说:

如果允许使用与时间有关的公式,我们可以这样做:

如果确实允许,则导致我:

x=>(x+x)[new Date%8||1]

其中new Date%8使用与上述相同的细分表。

并且%8也可能是&7; 选择。再次感谢,Arnauld。


2

ngn / apl,10个字节

⎕a[⌈/?2 4]

?2 4 随机选择一对数字-0 1中的第一个和0 1 2 3中的第二个

⌈/ 是“最大减少”-找到较大的数字

⎕a 是大写字母

[ ] 索引编制


注意当a∊ {0,1}和b∊ {0,1,2,3}时max(a,b)的图表:

    ┏━━━┯━━━┯━━━┯━━━┓
    ┃b=0│b=1│b=2│b=3┃
┏━━━╋━━━┿━━━┿━━━┿━━━┫
┃a=0┃ 0 │ 1 │ 2 │ 3 ┃
┠───╂───┼───┼───┼───┨
┃a=1┃ 1 │ 1 │ 2 │ 3 ┃
┗━━━┻━━━┷━━━┷━━━┷━━━┛

如果a和b随机且独立地选择,我们可以用0123 = ABCD来获得所需的概率分布


1

Python 3中64个55 51字节

-9个字节,感谢@ovs

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

在线尝试!


说明

random.choice()获取String的随机字符,同时为的输入(s*2)[1:]+s[1]创建BCDABCDB,其输入为ABCD1/8 As,2/8 Cs,2/8 Ds和3/8 Bs。


使用random.choice55个字节:lambda s:choice((s[0]+s[1:]*3)[:8])
ovs

@ovs找到了更短的方法^。choice()尽管感谢。
Xcoder先生

1

QBIC,27个字节

?_s;+;+B+B+;+C+;+D,_r1,8|,1

说明

?           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


1

芯片,60字节

)//Z
)/\Z
)\/^.
)\x/Z
)\\\+t
|???`~S
|z*
`{'AabBCcdDEefFGghH

在线尝试!

这三个?分别产生一个随机位。在第一个周期中,这些位通过上面的开关(/\)运行,以确定我们将从该表中输出哪个值:

000 a
01_ b
0_1 b
10_ c
11_ d

_可以是01)。然后,我们根据需要遍历输入,在达到正确值时打印并终止。

末尾的大字母斑点从cat程序中批量复制,此解决方案只是抑制输出并终止以获得预期的效果。



1

Applesoft,29步,32字节

一个小的“ retrocomputing”示例。忍受我,我是全新的。我收集到被指定 “输入”的内容本身不需要字节计数。如OP中所述,输入将被指定为“ ABCD”。(最初我并没有意识到我需要指定要获取的输入,该输入增加了4个字节,而其余部分则减少了一个字节。)

INPUTI$:X=RND(1)*4:PRINTMID$(I$,(X<.5)+X+1,1)

术语INPUT,RND,PRINT和MID $在内部均被编码为单字节令牌。

首先,为X分配一个随机值,范围为0 <X <4。这用于根据(X <.5)+ X + 1从I $中选择一个字符。字符位置值取为表达式的截断求值。如果X小于.5,则X <.5加1,否则加0。X的结果分解如下:

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%

欢迎来到编程难题和Code Golf!我们要求此处提交的内容至少要尽量琐碎,以便包括删除不必要的空格(如果需要此处的空格,我深表歉意)。另外,我不确定有关Applesoft的标准,但是我不相信您不能假定这些运算符是单字节令牌,除非内部表示形式是单字节。另外,您可能不会假定输入存储在变量中;相反,您实际上必须将其用作输入,命令行参数或函数参数。谢谢!
HyperNeutrino

@HyperNeutrino尽管“ INPUT”和“ PRINT”之后的空格会提高可读性,但不需要空格。确实发生过,在传统的网络语言空间中,传统上是在我拥有的地方进行展示。对于我提到的令牌,“内部表示是单个字节”确实是正确的。同时,我打了一个字节的代码。
艾伦·拉特

1

普通Lisp,198字节

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

在线尝试!

可读性:

(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"))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.