精瘦的豆子机


26

向人们介绍离散概率分布概念的经典示例是bean机器。这台机器有大量的大理石从顶部狭窄的通道掉落,然后它们撞到交错的销钉行,在每个销钉处,大理石撞件可能会落到销钉的左侧或右侧。最终,将销钉收集到机器底部的垂直箱中。这台机器的简单图如下所示:

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |
|_|_|_|_|_|_|

在此图中,O表示大理石掉落的位置。每个^都是钉子,大理石在该钉子处有50%的机会移动到钉子左侧或右侧的正方形。然后,大理石聚集在设备底部的垃圾箱中,对于足够多的大理石,垃圾箱中的大理石堆叠高度将类似于离散的二​​项分布。

挑战

对于这一挑战,您将基于上图来计算bean机器的最终概率分布。这些图被解释为大理石通过的二维“程序”,即朝向侧场或当前场下方的场。当弹珠到达机器底部时,它们会被计算为概率分布。为了使它有趣,这些图将包含比简单的源代码和引脚更多的字段。一个示例图是:

|     O     |
|     ^     |
|    ^ /    |
|   ^ | ^   |
|  <^- =  v |
| ^ ^ ^ ^ ^ |

此外,大理石现在各自具有旋转方向。此方向由某些字段设置,并确定大理石在其他几个字段中移动到下一个字段。

定义了以下字段:

  • O: 资源。在其正下方产生大理石。这些弹珠的方向向左50%,向右50%。每个来源生产相同数量的大理石。
  • U:水槽。进入此字段的所有大理石都将从豆子机中移除。
  • : 空的空间。如果大理石到达此区域,它将移动到下面的区域。
  • -:地板。如果大理石到达此区域,它将根据其当前方向移动到左侧的区域或右侧的区域。
  • ^:分离器。如果大理石到达此区域,则它有50%的位置移动到分割器的右侧或左侧。这也决定了大理石的方向。
  • v:加入。如果大理石到达此区域,它将移动到下面的区域。
  • /:倾斜的垫子。如果大理石到达此区域,它将移动到垫板左侧的区域,设置大理石的方向。
  • \:与上一个相同,但在右侧。
  • |:反射镜。如果大理石到达此区域,它将反转大理石的方向,并根据此反向将大理石向右或向左移动。
  • =:大炮。如果一个大理石到达这个领域后,将其移动到左边的电流方向向右或,直到大理石遇到一个字段不是-O
  • <:与上一个相同,但是将始终设置方向并向左移动。
  • >:与上一个相同,但在右侧。

关于该图,提供以下保证。

  • 每个输入行在字段中的长度将完全相同。
  • 每行的最左侧和最右侧字段始终为|
  • 该图将不包含任何可能的路径,通过这些路径,大理石可以在不确定的迭代次数(例如\/或)中卡入机器^^
  • 该图将仅包含上述字段。
  • 有一个或多个来源

结果

您的任务将是生成概率分布的16行高ASCII条形图,其中大理石从图的底部离开,并按比例缩放,以便最大的概率覆盖所有16个字符。因此对于以下问题:

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |

您的程序应产生以下解决方案(请注意,其宽度应与输入程序相同,包括侧面的管道:

     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
 # # # # # #
 # # # # # # 

例子

下面是一个示例,应测试所有不同字段类型的功能:

|     O     O         |
|  O  ^ /  <^\\\      |
|    ^ >            ^ |
|   ^ ^ ^            =|
|  ^ ^ | ^    <^   O  |
| ^ > ^ | ^   O ^> v  |
||  ^U  ^  |  =    ^\ |
|  ^ ^ ^ ^U ^\ ---^   |
| = ^   ^     =    v  |

它应该导致以下输出:

                     # 
                     # 
                     # 
                     # 
                   # # 
                   # # 
                   # # 
       # #         # # 
       # #         # # 
       # #         # # 
       # #         # # 
      ## #         # # 
      ## # #       # # 
   # ### # #       # # 
 # # ### # #       # # 
 # # ### # #       # # 

规则

功能和完整程序都构成了对此挑战的有效答案。您将以换行符分隔的字符串形式收到该图,并应以给定格式返回输出图。默认输入/输出规则适用。尽管在输出中允许使用尾随和前导的换行符,但每行的宽度应与输入的宽度完全相同。

为了提供更多有创意的解决方案,仅要求您的程序在90%的时间内为同一张图输出正确的结果。毕竟这是一个概率模拟。

计分

这是,因此以字节为单位的最低分数获胜。


简单得多但又相关
彼得·泰勒

评论不作进一步讨论;此对话已转移至聊天
丹尼斯

所以v= [space]
l4m2

@ l4m2 v[space]不同之处在于大炮在它们周围的互动方式。
CensoredUsername

Answers:


8

Python 3中431个 429 410字节

def t(a):e=enumerate;p=a.split("\n");o=[0]*len(p[0]);{m(i,j,p,o,1):m(i,j,p,o,-1)for i,r in e(p)for j,c in e(r)if"O"==c};[print("".join(" #"[round(16*r/max(o)+i)>15]for r in o))for i in range(16)]
def m(r,k,p,o,l,x=1):
 while r<len(p):
  c=p[r][k]
  if"^"==c:x/=2;m(r,k-l,p,o,l,x)
  if"U"==c:return
  if c in" vO":r+=1;continue
  l=[1,l,-1,l,-l,1][ord(c)%6];k-=l
  while";"<c<"?"and p[r][k]in" O-":k-=l
 o[k]+=x

在线尝试!

这个答案是Wheat Wizard和CensoredUsername之间的共同努力。供参考,是非高尔夫算法。

Xcoder先生的-2字节

来自CensoredUsername的-19个字节


如果切换到Python 2(打印语句),则为-2个字节?
caird coinheringaahing

1
为此有人说:but I can confirm it's doable in 519 characters of python 3 code ;) I don't think I can golf mine much more- CensoredUsername
斯蒂芬·

我说那话真是绝望。就是说,确保高尔夫比赛十分有趣。同样@ cairdcoinheringaahing,python 2的print语句是一个语句,而不是表达式,因此不能在列表推导中使用。这意味着必须将位于顶部的oneliner分成几行缩进的行,这将使从2个字节删除的空字节无效。
CensoredUsername

4

Python 2,731字节

i=raw_input
l=i()
c=[]
while l:c,l=c+[l],i()
p=[[0]*len(l)for l in c]+[[0]*max(map(len,c))]
S=lambda r,C,p:r>=0and C>=0and r<len(p)and C<len(p[r])
def U(r,C,P,D,N=0):
 if S(r,C,p):p[r][C]+=P
 if S(r,C,c):
	K=c[r][C]
	if K in' O':U(r+1-N,C+D*N,P,D,N)
	elif'v'==K:U(r+1,C,P,D)
	elif'-'==K:U(r,C+D,P,D,N)
	elif'^'==K:U(r,C-1,P/2,-1);U(r,C+1,P/2,1)
	elif'/'==K:U(r,C-1,P,-1)
	elif'\\'==K:U(r,C+1,P,1)
	elif'='==K:U(r,C+D,P,D,1)
	elif'>'==K:U(r,C+1,P,1,1)
	elif'<'==K:U(r,C-1,P,-1,1)
	elif'|'==K:U(r,C-D,P,-D)
for r in range(len(c)):
 for C in range(len(c[r])):
	if'O'==c[r][C]:U(r+1,C,1.,1);U(r+1,C,1.,-1)
p=p[-1][::-1]
s=16/max(p)
f=['#'*min(int(n*s),16)+' '*min(int(16-n*s),16)for n in p]
print('\n'.join(map(''.join,zip(*f)))[::-1])

在线尝试!

-17字节归功于Caird coinheringaahing

-12字节感谢Nathan Shiraini

通过切换到混合缩进来-56字节(Python 2)

-28多亏了CensoredUsername,因为最终对概率进行了归一化,因此最终概率不必总等于1。

-7个字节,这要归功于猫计算器,因为它使用了较短的结尾elif语句。

通过合并两个功能来实现-218字节



@cairdcoinheringaahing对,谢谢。
HyperNeutrino

2
R和之L类的R(r+1-N,C+N,P,N=N)呼叫(首次呼叫R)中,您不需要N=在末尾;应该是R(r+1-N,C+N,P,N)
Nathan.Eilisha Shiraini

@NathanShiraini对,谢谢。
HyperNeutrino

...你忘了一些。最后2行的都LR^^还有,你的缩进的第二个层次是4位无处不在,我想你可以把2
Nathan.Eilisha Shiraini

3

C,569个 568个 556字节

打高尔夫球

#define A s[1]
#define c(i,j,k) break;case i:x=j;y=k;
w,S,i,j,d,x,y,z;main(int*a,char**s){w=strchr(&A[1],'|')+2-A;a=calloc(w,4);for(;i++<'~~';j=0){for(;A[j];){if(A[z=j++]==79){d=rand()%2;x=4;y=7;z+=w;for(;z<strlen(A);){z+=x%3-1+(y%3-1)*w;switch(A[z]){case 85:goto e;c(32,x/3*(3+1),y/3*(3+1))c(45,d*2+3,7)c(94,(d=rand()%2)*2+3,7)c(118,4,8)c(47,3,7)d=0;c(92,5,7)d=1;c(124,(d=!d)*2+3,7)c(60,x,y)case 62:d=A[z]/2%2;case 61:x=d*8;y=4;}}a[z%w]++;e:;}}}for(i=-1;++i<w;S=a[i]>S?a[i]:S);for(j=17;j-->1;puts(""))for(i=0;i<w-1;printf("%c",a[i++]*16./S+0.6<j?32:35));}

不打高尔夫球

//Variable Definitions
//direction - marbles current direction, 0 -> left, 1-> right
//arrwidth - width of array
//x - change in x of marble in base 3 - 0 -> Left, 1 -> stay, 2-> right
//y - change in y of marble in base 3 - 0 -> Up, 1 -> stay, 2-> Down
//z - position of marble
//i - iterator on runs of program
//j - iterator on string
//k - iterator on outputstring
//argc - array holding all buckets

#define c(i,j,k) break;case i:x=j;y=k;

arrwidth,scale,i,j,direction,x,y,z;

main(int *argc, char**argv){
  arrwidth=strchr(&A[1],'|')+2 - A; //get width
  argc=calloc(arrwidth,4);
  for(;i++<'~~';j=0){
    for(;A[j];){
      if(A[z=j++] == 79){ //if it finds an O, start sim
        direction=rand()%2;
        x=4;
        y=7;
        z+=arrwidth;
        for(;z<strlen(A);){
          z+=x%3-1 + (y%3-1)*arrwidth;
          switch (A[z]){
            case 85://marble dies dont record
              goto e;
            c(32,x/3*(3+1),y/3*(3+1)) //case ' '
            c(45,direction*2+3,7)    //case -
            c(94,(direction=rand()%2)*2+3,7)    //case ^
            c(118,4,8)    //case v
            c(47,3,7)    //case /
              direction=0;
            c(92,5,7)   //case '\'
              direction=1;
            c(124,(direction=!direction)*2+3,7)
            c(60,x,y)    //case <
            case 62:    //case >
              direction=A[z]/2%2;
            case 61:  //case =
              x=direction*8;
              y=4;
          }
        }
        argc[z%arrwidth]++;
        e:;
      }
    }
  }
  //get output answer in terms of '#'
  for(i=-1;++i<arrwidth;scale=argc[i]>scale?argc[i]:scale);
  for(j=17;j-->1;puts(""))
    for(i=0; i < arrwidth-1;printf("%c",argc[i++]*16./scale+0.6<j?32:35));
}

编辑

通过更改case宏节省了12个字节。

笔记

我的代码使用一个由3个整数组成的系统来确定大理石的前进方向和前进方向(对于大炮和其他东西)。

我确实尝试过击败该python解决方案,但确实做到了。


1
我数了568个字节;也许您数了尾随换行符?该死的,我很难过。在C语言中超越Python?Jeez ...:P
HyperNeutrino

您是正确的,我在文件中留下了结尾的结尾。谢谢!
dj0wns
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.