使硬币公平


36

您有一枚可产生0或的硬币1。但是您怀疑硬币可能有偏差,这意味着0(或1)的概率不一定是1/2。

由冯·诺伊曼(von Neumann)提出的一种众所周知的将“有偏见的硬币”“转化”为公平硬币的过程(即获得同样可能的结果)如下。产生(不重叠)两个掷硬币的区块,直到一个区块的两个值不同为止;并在该块中输出第一个值(第二个值也可以,但是出于挑战的目的,我们选择第一个)。直观地看,1可能比更容易0,但0110将同样有可能。

例如,输入1110...将丢弃第一个块,然后1从第二个块产生a ,...

此过程很昂贵,因为要消耗多个硬币才能产生单个结果。

挑战

取零和一的有限序列(代表原始硬币的抛弃),并根据上述过程产生最大数量的结果,直到消耗完所有输入为止。

如果输入值的数量为奇数,则最后一个块可能不完整。例如,输入序列11111将不产生结果(前两个块具有相等的值,而第三个块不完整)。

规则

输入可以具有任意数量的非负值,不一定是正数或偶数。

输入格式可以是:

  • 零和一的数组;
  • 一串零和一,并带有可选的分隔符。

输出格式可能是:

  • 一串零和一,带或不带分隔符;
  • 零和一的数组;
  • 包含单个零或一的字符串,以换行符分隔;
  • 适合您的语言的任何相似,合理的格式。

代码高尔夫。最少的字节数获胜。

测试用例

这里假定输入和输出为字符串。

Input         -->  Output

'1110'        -->  '1'
'11000110'    -->  '01'
'1100011'     -->  '0'
'00'          -->  ''
'1'           -->  ''
''            -->  ''
'1101001'     -->  '0'
'1011101010'  -->  '1111'

每个输入是否应该有两个可能的输出(即按位而不是当前输出)?
wizzwizz4 2016年

1
@ wizzwizz4您可以选择其中一个,但不能同时选择两者(因为这样一来,它们在统计上就不会独立)。在这个挑战我随意选择的第一个
路易斯Mendo

6
您对硬币太怀疑了。只是翻转东西;)
Geobits

2
@IGoBest 我不太确定:-D
Luis

1
@DonMuesli Man,该文件中的警告列表令人印象深刻:P
Geobits,2016年

Answers:


5

果冻,6个字节

s2Q€Ṗ€

在线尝试!

怎么运行的

s2Q€Ṗ€  Main link. Argument: S (string)

s2      Split the string into pairs of characters.
  Q€    Deduplicate each pair.
        This removes the second character iff it is equal to the first.
    Ṗ€  Pop each; remove the last character of each pair/singleton.

14

视网膜16 14字节

(.)\1|(.)?.
$2

在线尝试!

说明

这很简单。该代码定义了一个正则表达式替换,将所有(不重叠)匹配项(.)\1|(.)?.替换为第二个捕获的组。它将三种不同的情况合并为一种:

(.)\1 --> <empty>

如果两个重复的数字相等,我们将它们从字符串中删除(因为未使用组2)。

(.).  --> $2

否则,如果我们可以匹配两个字符,则通过将两个字符都替换为第一个字符来删除第二个字符。如果不是这种情况,?将忽略该组:

.     --> <empty>

仅当存在未配对的尾随字符(也将其删除)时,才会发生这种情况。


这可能是我所见过的最短的视网膜答案:-)
路易斯·门多

9
@DonMuesli ummm ...
Martin Ender

11

迷宫21 12字节

"(. :
""*$,@

紧凑的迷宫程序的罕见示例,该程序也没有禁止操作。所述|在前一版本是完全没有必要的,并且除去它大量减少了程序的大小。实际上,实验室击败了视网膜!

在线尝试!

左下角"也可以是一个空格,但在那里有一个极大的简化了说明。

说明

这有点棘手,因此会附带图像。但是首先,快速入门:

  • 迷宫是一种基于堆栈的2D语言。内存由一个主堆栈和一个辅助堆栈组成。
  • 迷宫的堆栈是无底的,并用零填充,因此对空堆栈执行操作不会出错。
  • 在每个结点处,有两个或两个以上指令指针可以通过的路径,将检查主堆栈的顶部以找出下一步的位置。负数是左转,零是正数,正数是右转。如果转弯失败,则指针会尝试朝另一个方向转弯。

设定

在此处输入图片说明

该程序从左上方开始",这是一个无操作。然后我们执行:

(        Decrement a bottom zero to -1. Since -1 is negative we try to turn 
         left at this junction, fail, and turn right instead.
"        No-op junction, turn left
*        Multiply top of stack (-1) with a 0 at bottom of stack, giving 0.
         This makes us go straight ahead at this junction.
$        Bitwise xor (of 0 and 0)

这样就在堆栈上留下了一个0,就迷宫而言,它和空一样好。

读取输入和终止

在此处输入图片说明

,从输入中读取一个字符,分别为0或返回48或49 1,在EOF上返回-1。由于这是非零值,因此无论哪种方式,我们都将变成:,它会复制堆栈的顶部。

:是一条死胡同,所以我们回过头来执行,一次。现在,如果最后一个输入是EOF,那么我们向左@转,以结束,否则我们向右转,堆栈看起来像[a a b](其中ab是两个字符)。

抛硬币

在此处输入图片说明

如果我们没有终止,那么下一步就是再次执行$(按位异或)。如果输入字符相同,则结果为0,否则为1。然后a,我们将此结果相乘,得出0或a。由于*处于交界处,因此该顶部堆栈值确定接下来将发生什么。

在0的情况下,我们先执行并执行三个"无操作,然后再执行(递减操作。像设置一样,这使我们转身执行"*$,使我们可以阅读更多字符。

在此处输入图片说明

否则,在这种a情况下,由于a为正数(48或49),所以我们在路口处右转。.输出char,使堆栈为空,并(递减堆栈的顶部,将0变为-1。再次,这使我们向左转,"*$像在设置中一样执行,也使我们准备阅读更多输入。


...哇。只是,哇。出于好奇...如果您删除每一行的前导报价,会发生什么?
ETHproductions 2016年

@ETHproductions第二列不再是连接,因此IP开始执行,(然后.输出char 255(-1模256)。因此,不幸的是,从那里开始已经是错误的:P
Sp3000 '16

8

CJam,10 8个字节

l2/{)-}%

在这里测试。

说明

这是一个非常简单的解决方案:在每对中,删除最后一个字符的所有实例。重复的数字和不成对的尾随数字将被删除,任何不等对数字中的第二个数字也将被删除:

"0"  --> ""
"1"  --> ""
"00" --> ""
"01" --> "0"
"10" --> "1"
"11" --> ""

这只剩下我们要查找的数字。代码是如何计算出的:

l     e# Read input.
2/    e# Split into pairs. Odd inputs will yield a single-character string at the end.
{     e# Map this block over the pairs...
  )   e#   Pull the last character off the string.
  -   e#   Remove all occurrences of that character from the remainder (which is either
      e#   an empty string to begin with or a single-digit string).
}%

当列表在程序末尾自动打印时,空字符串将被简单地省略。


3
除了代码本身,您和@DonMuesli是唯一在答案中有任何解释的人。谢谢。
Rɪᴋᴇʀ

7

Perl,19 18 17字节

@MartinBüttnerRetina解决方案激发了2字节的增益

包括+1的 -p

使用STDIN上的输入运行,例如 perl -p fair.pl <<< 11000110

fair.pl

s/(.)\1|.?\K.//g

这里没有太多解释,因为它是规范的(间接)翻译:

  • (.)\1 如果前两位数字相同,则将其删除
  • .\K. 否则前两位数字不同。保留(\K)第一个
  • .?\K.除了第一个.是可选的。这允许在字符串的末尾进行单个匹配,然后将其丢弃,因为保留的部分为空

5

Mathematica,36 38字节

-2在窃取@ LegionMammal978的用于确定2元素列表是{0,1}或{1,0}的函数之后

#&@@@Select[#~Partition~2,Tr@#==1&]&

参数应为整数列表。


哦,不,一个问题有3个Mathematica答案!
CalculatorFeline

5

六边形23 21字节

,){,/;(_\/'%<\{)/>~$>

展开:

    , ) { ,
   / ; ( _ \
  / ' % < \ {
 ) / > ~ $ > .
  . . . . . .
   . . . . .
    . . . .

这会以错误终止,但是错误消息将发送至STDERR。

在线尝试!

从后视镜的数量来看,可能有可能将其安装在边长3的范围内,但到目前为止我还没有运气。

说明

这是用Timwi的HexagonyColorer生成的普通图表:

在此处输入图片说明

该程序仅使用三个内存边,此处标记为ABC(图由Timwi的EsotericIDE提供):

在此处输入图片说明

执行从蓝色路径开始。的/是重定向指令指针(IP)只是反射镜,实际的代码是:

,   Read character from STDIN into memory edge A.
)   Increment.
{   Move to memory edge B.
,   Read character from STDIN into memory edge B.
)   Increment.
'   Move to memory edge C.
%   Compute A mod B in memory edge C.

如果我们点击了EOF ,,则会将边缘设置为,-1而不是字符代码。由于我们要递增两个不变的输入,因此无论EOF是否相等,它都会将EOF变为0

我们使用模来检查是否相等,因为不相等字符和相等字符为149(正)0。它也用作程序的结尾,因为当我们0从EOF中获得源代码时,尝试除以零将导致错误。

现在,<将零与阳性结果区分开。首先简单地说:如果字符相等,则IP采用红色路径。_是一面镜子,\也是一面镜子,但被忽略了,并且>使IP偏转,使其环绕边缘并再次从顶部开始。但是,在此迭代中,ABC的角色循环交换(C现在担任A的角色,依此类推)。

如果字符不同,则采用绿色路径。这有点麻烦。它首先跳过一个无操作符$,然后/在左侧边缘环绕,然后从右到左遍历倒数第二行,最后在处重新输入源代码中有趣的部分{。在$使IP跳过并>再次合并两条路径之前,有一段基本上是线性的代码,我将在稍后解释。

这是线性代码:

{    Move to memory edge A.
(    Decrement to recover the actual character we read.
;    Print the character back to STDOUT.
'    Move to memory edge B.
~    Multiply the value there by -1, making it negative. This is
     necessary to ensure that the path correctly wraps back to the top.

请注意,在这种情况下,下一次迭代的边的角色也会循环交换,但是B充当A,依此类推。



4

> <>,11个字节

i:i:0(?;-?o

> <>非常适合一次读取字符的挑战:) 在线尝试!

i:            Read char and duplicate
i             Read char
:0(?;         Halt if last char was EOF
-             Subtract
?o            Output first char if the subtraction was non-zero (i.e. not equal)

这一切都是在循环中发生的,因为指令指针一旦到达一行的末尾就会回绕。


-1表示不包含>或包含以下内容的> <>程序<
Luis Mendo

3

Python,42个字节

f=lambda L:L[1:]and L[:L[0]^L[1]]+f(L[2:])

递归和按位异或的乐趣。将1和0的列表作为输入。


3

JavaScript(ES6),33个字节

s=>s.filter((c,i)=>++i%2&c!=s[i])

怎么运行的

s=>s                // Take the input array.
.filter((c,i)=>   ) // Filter to only the chars that are both:
++i%2&              //  on an even index, and
c!=s[i]             //  not equal to the one after them.

您可以通过要求输入为数组来节省一些字节。(允许提问)
Mama Fun Roll

@MamaFunRoll感谢您的提示!
ETHproductions 2016年

3

前奏,12字节

11(-(#!)?^?)

假设有一个解释器可以读取和打印字符。您可以在网上尝试一下。但是,这个解释器中打印整数,因此每个0你会得到48和每个1你会得到49来代替(换行)。

说明

可以在Prelude的单行上编写非平凡的程序非常罕见(因为Prelude需要多于一行才能完成图灵完成)。

11      Push two 1s. We need something non-zero on the stack to enter the loop, and by
        pushing the same value twice, we make sure that the loop doesn't print anything
        on the first iteration.
(       Main loop...
  -       Subtract the last two values. This will be zero for equal values, and non-zero
          otherwise...
  (       This "loop" is simply used as a conditional: if the last two values were
          were equal, skip the code inside...
    #       Discard the conditional.
    !       Print the value below.
  )       The loop is exited because the value below is always zero.
  ?       Read the first character of the next pair from STDIN.
  ^       Duplicate it, so the lower copy can be printed.
  ?       Read the second character of the pair. This returns 0 at EOF, which
          terminates the loop.
)

3

Perl,27个 21字节

say grep$_-chop,/../g

-n标志添加的字节。

                /../g  match groups of two chars
    grep       ,       select/filter on...
           chop        remove the last character, mutating the string
        $_-            is it different than the remaining char?
                         (subtract it, empty string is falsy)
say                    output if so

测试:

llama@llama:~$ perl -nE 'say grep$_-chop,/../g'
1110
1
11000110
01
1100011
0
00

1



1101001
0
1011101010
1111

感谢@TonHospel提供6个字节!


您可以通过缩短测试来获得一些字节:say grep$_-chop,/../g
Ton Hospel

@TonHospel非常好,谢谢!
门把手

3

Befunge 93,16个字节

~:~:0`!#@_->#,_$

紧凑的单线。使用此在线解释器进行了测试。

~:                     Read input char a and dup
  ~                    Read input char b (-1 on EOF)
   :0`!                Push 1 if b <= 0, 0 otherwise
       #@_             Halt if b <= 0 (i.e. EOF)
          -            Subtract to check whether a != b
           >#,_$       Output a if so

最后一部分利用了一个事实,即从一个空的Befunge-93堆栈弹出会产生0

如果a != b,我们执行

>                      Move rightward
#                      Bridge: skip next
_                      Horizontal if - go right if 0, else left. But a != b, so we go left
,                      Output a
#                      Bridge: skip next
-                      Subtract (0 - 0 = 0)
_                      If: go right since 0 is popped
>#                     Go right and skip next
_                      If: go right since 0 is popped
$                      Pop top of stack, stack is now empty

否则,如果a == b,我们执行:

>                      Move rightward
#                      Bridge: skip next
_                      If: go right since a == b (i.e. a-b is 0)
$                      Pop top of stack and discard, keeping stack empty


2

Python 2,48个字节

lambda n:[s for s,t in zip(*[iter(n)]*2)if s!=t]

在线尝试

感谢Dennis和vaultah指出我错过的东西


我认为您可以使用良好的旧“石斑鱼”食谱:zip(*[iter(n)]*2)
Vault

lambda不会工作吗?
丹尼斯

2

Mathematica,41个 39字节

Select[#~Partition~2,Tr@#==1&][[1]]&

比其他答案要复杂和短。该框是转置字符。


2

JavaScript(ES6),33个字节

s=>s.replace(/(.)\1|(.)?./g,"$2")

无聊的视网膜答案。


2

sed,34 33字节

s/../& /g;s/00\|11//g;s/.\b\| //g

测试:

llama@llama:~$ sed 's/../& /g;s/00\|11//g;s/.\b\| //g'             
1110
1
11000110
01
1100011
0
00

1



1101001
0
1011101010
1111

1
我尝试使用fold(1)命令拆分成对。那也34岁了!fold -s2|sed 's+01+0+p;s+10+1+p;d'
joeytwiddle

@joeytwiddle fold -s2等价于fold -2,使它成为33个字节...这也是我刚刚将纯sed解决方案压缩到的内容。:P
门把手

我结合了第二个和第三个替换来剃除另外4个字节:s/../& /g;s/00\|11\|.\b\| //g
Toby Speight

2

迷宫,31字节

不像Sp3000的解决方案那么短而整洁,但是我认为无论如何我还是会发布此方法:

"" @
,, :{"
)  { $;
*"})";.
 ""

说明

第一个循环很简单

""
,,

一次读取两个字符("无操作)。EOF之后,,将返回-1,但仅每隔一个字符检查一次EOF。这意味着在任何情况下,堆栈的顶部都将是-1,而下面的值是-1我们不关心的某个或某些字符代码,因为这是不成对的投掷硬币。

然后)*-1下面的和值变成单个0,我们需要a)摆脱这两个值,b)正确进入下一个循环。下一个循环就是

"}
""

这会将所有值移至辅助堆栈。这是必需的,因为我们要开始处理我们首先读取的对。现在是最后一个循环:

:{"
{ $;
)";.

)刚刚增加了一些虚值,以确保它的正面和指令指针转向北方。{跳过下一对的第一位并:重复。现在,当我们完成处理后,这将从0辅助堆栈的底部开始。否则为4849。如果为零,则退出循环并终止于@,否则IP向东旋转。

{拉过当前货币对的另一位数字。$在它们之间进行XOR。如果该值为0,即两个相等,则IP继续向南移动,;丢弃零,然后IP向西进入下一个迭代。如果XOR是1,即它们不同,则IP向西,丢弃1with ;并用来打印第一个数字.


2

MATL11 9 8字节

`-?6MD]T

输入和输出是用换行符分隔的数字。使用完所有输入后,将以错误(默认为允许)结束。

在线尝试!

`         % do...while loop
  -       %   take two inputs implicitly. Compute difference
  ?       %   if nonzero
    6M    %     push first of the two most recent inputs again
    D     %     display (and remove from stack)
  ]       %   end if
  T       %   true. Used as loop condition, so the loop is infinite
          % end loop implicitly

旧方法,11个字节

2YCd9L)Xz0<

输入是一个字符串。输出是用换行符分隔的数字。

在线尝试!

2YC      % implicitly take input as a string. Generate 2D array of length-2
         % overlapping blocks as columns, padding with a zero if needed.
d        % difference of the two values in each column of that array
9L       % predefined literal [1 2 0]. This corresponds to "1:2:end" indexing
)        % keep only values at indices 1, 3, 5, ... This reduces the set of blocks
         % to non-overlapping, and discards the last (padded) block if the input had
         % odd length
Xz       % keep only nonzero entries, corresponding to blocks that had different values
0<       % 1 if negative, 0 if possitive. Implicitly display

2

Ruby,46个字节

它分隔l[0]l[1]l[2..{end}]abc。然后,它使用aif a!=b''else以及f[c]if c[0]存在或''其他方式创建一个字符串。

f=->l{a,b,*c=l;"#{a!=b ?a:''}#{c[0]?f[c]:''}"}

取消高尔夫:

def f(l)
  a = l[0]
  b = l[1]
  c = l[2..l.length]
  s = ''
  if a!=b
    s += a.to_s
  end
  if c[0]       # equivalent to !c.empty?
    s += f[c]   # no .to_s because the output will be a string
  end
  puts s
end

2

Brainfuck,33个字节

,>,[<[->->+<<]>[[-]>.<]>[-]<<,>,]

与Java相比,它非常紧凑,但是,我担心使用Brainfuck-golfer应答器。如果有错误,请随时提及。假设EOF为0,则输入不包含无效输入,单元格最初为零,并且单元格的值范围是有限且循环的。没有其他假设。

说明:

存储器单元图

+---------+---------+-----------------+
|1st input|2nd input|copy of 1st input|
+---------+---------+-----------------+

指令

,>,                               read two instruction at once | first to first cell |
                                  second to second cell
   [                              Until the input is EOF
    <                             look at first cell
     [->->+<<]                    move the first cell to additional cells while
                                  subtracting the second cell with this at same
                                  time
              >[                  if the second cell is nonzero (it means that first cell and
                                  the second cell is the same)
                [-]>.<            Print the copied first input
                      ]
                       >[-]       clear the first input to prevent it polluting next input
                           <<,>,  continue with next two input
                                ]

1
非常好!我一直在尝试自己写BF answr。但是我也发现它是BF-ing
Luis Mendo


1

Pyth,10个字节

hMf!qFTcz2

测试套件


您可以替换!q通过n,然后过滤fnFT通过nF#。(hMnF#cz2;这是我看到挑战时想到的东西,但是您的位置足够接近我,无法单独发布)
PurkkaKoodari

@ Pietu1998我尝试过了。它在例如1
isaacg

1

C,66字节

main(char*p,char**x){for(p=x[1];*p&p[1];p+=2)write(1,p,*p^p[1]);}

假设 sizeof(int) == sizeof(char *)

“聪明”的解决方案-84 81字节

main(int c,short**x){while(!((c=*x[1]++-12336)&~511))c>>8^c&1&&putchar(48|c&1);}

假设short为2字节,可在little-endian机器上工作。输入作为参数传递。该程序遍历字符对,并为0x3130打印0,为0x3031打印1。在big-endian上,结果将相反(48|c&149^c&1修复此问题)。


1

C,57字节

f(char*p,char*r){for(;*p*p[1];)*r=*p++,r+=*r!=*p++;*r=0;}

我们暂时将一个字符从输入复制p到结果r,但仅在r指针与下一个字符不同时才向前移动指针。如果不是,那么我们将在下一个不匹配的对或NUL末尾将其覆盖。

测试程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
    while (*++argv) {
        char *result = malloc(1+strlen(*argv));
        f(*argv, result);
        printf("%s => %s\n", *argv, result);
        free(result);
    }
    return EXIT_SUCCESS;
}

测试输出:

$ ./74864 1110 11000110 1100011 00 1 "" 1101001 1011101010
1110 => 1
11000110 => 01
1100011 => 0
00 => 
1 => 
 => 
1101001 => 0
1011101010 => 1111


1

DOS / Windows批处理,201个 162字节

@echo off
set/pi=
:a
for /f "tokens=2" %%a in ("%i%") do goto l
exit/b
:l
for /f "tokens=1,2" %%a in ("%i:~0,4%") do if %%a neq %%b echo %%a
set "i=%i:~4%"
goto a

输入是一个用空格分隔的字符串,例如1 0 0 1 1。从cmd开始,否则屏幕立即退出


1

蜂蜡45 35字节

我可以将它压缩10个字节-不错。

pgy~1z;L?gAF1<<?V_
>&?@yg&?~@ KQd{b

阅读了一整串抛硬币的方法,这使程序很大。仅逐个读取单个整数会使程序更小(大约22字节左右),但使用起来非常不便。

例子:

julia> beeswax("FairCoin.bswx")
s1110
1
Program finished!

julia> beeswax("FairCoin.bswx")
s11000110
01
Program finished!

julia> beeswax("FairCoin.bswx")
s1100011
0
Program finished!

julia> beeswax("FairCoin.bswx")
s00

Program finished!

julia> beeswax("FairCoin.bswx")
s10101001010111111100000010011001110100010110101110100001011
1110001010000111100
Program finished!

我的beewax GitHub存储库。

我在Rosetta Code上的蜂蜡示例。

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.