马修飓风和闪电


27

挑战

受此挑战和令人讨厌的马修飓风的启发,我们将动态生成一些闪电。

n = 15:

   \
   /\
  /  \
 /   /
/\  /\
 /  \ \
/   / /\
   /\ \
  / /  \
 /\ \  /\
  /  \ \
 /\  /  
   \
    \
    /\

输入项

正整数n确定闪电轮的深度。

规则与约束

  • /并且\应该使用
  • 指导闪电方向的概率如下:
    • 25%分成2条路径
    • 25%的路径到达死角
    • 剩下25%
    • 25%正确
    • 以下是有关重叠和死角的一些例外情况:
  • 代码不应是确定性的,每次应随机生成一个新的闪电
  • 螺栓不应重叠:例如,如果当前螺栓的左侧已经有一个螺栓,则当前螺栓应末端或向右移动,但不应向左或分裂(概率仍然适用,在这种情况下,变为50%末端/ 50%正确)
  • 如果不存在另一个可用的拆分路径,则该路径不应结束:例如,在只有1条路径的开始处,该路径应在拆分之前不结束,在有多条路径但除一条路径之外的所有路径均已失效的情况下也适用,(概率变为33%分裂/ 33%向左/ 33%向右),您的目标是达到最低点
  • 可以在左侧添加空格(您只需要将height-1设置为空白)
  • 但是,要生成的螺栓由您自己决定,则可以从下向上,从左到右等方向移动。只要满足上述所有规则,

另一个例子

n = 10

 \
 /
 \
 /\
  /\
 / /
/\ \
 / /\
 \   \
 /

马修飓风显然在向天空发射红色螺栓,称为精灵

保持安全并打高尔夫球! 请仅在安全区域内负责任地打高尔夫球!!


7
Stay safe and have fun golfing!也许还指定如果EAS罢工,放弃一切并遵守命令!在这种情况下,打高尔夫球不是您的优先事项。
Erik the Outgolfer '16

17
@EriktheGolfer你不是一个真正的高尔夫球手。
蓝色,

4
我不认为“最中心的路径应该是到达地面的路径”与其余的随机生成描述相一致。例如,原始螺栓可能会随机分裂两次,然后中间的两个螺栓会终止。在保留指定的概率的同时,如何克服这种可能性?
格雷格·马丁

此外,如果(例如)前两个步骤都被拆分,会发生什么情况?然后中间的两个螺栓相互接触,这似乎有问题,但特殊情况也不能排除。
格雷格·马丁

@GregMartin最中心的一点,本来我希望它能生成平衡的螺栓,但是现在,即使没有这种约束,我也考虑了它,大约有50%的时间应该在中间某个深度15个中的最右边或最左边的路径到达的机会只有1-2%。我将删除该规则。对于2个步骤的拆分部分,唯一要防止的是\/在任何时候都不应有2条路径连接2条路径。
祖卡伯格'16

Answers:


6

Perl,92 90 89 84字节

包括+1的 -n

给出STDIN的高度:

perl -M5.010 bolt.pl <<< 15

bolt.pl

#!/usr/bin/perl -n
map{$_=$;until$;=$_,s/.6|3.?/53|16*rand/eg,/3|6/>/36/;say y|3615|\\/ |r}(1x$_.6)x$_

说明

如果您将起始点的偏移量称为0(点位于字符框的拐角处),则在下一行中,您可以向左或向右(或不行)移动,并且可以在offsets上结束-1,1。下一行给出-2,0,2可能的偏移量等。它们的总和为2。如果您随后将字符称为点的左下角,而将字符称为右下角的奇数,则可以扩展为将每个字符位置分配为偶数或奇数以偶数和奇数交替的方式排列(实际上,整个平面以棋盘图案平铺)。偶数位置可以具有/,奇数位置可以具有\

a之前的字符/处于奇数位置,因此可以是\,但\/被禁止,因此只能是可能。类似地,a后面的字符\ 必须为a (假设该行在左侧和右侧填充了足够的空格,因此该行的边界没有问题)。因此,闪电始终在a的正下方\或a的正下方继续在下一行上继续/。在任一情况下点是在中间和下一行可以具有一个/\/\直接在顶部2个字符以下。因此,要生成下一行,我可以简单地替换任何\/通过任何这些4个膨胀以相等的概率的(您也可以独立地通过替换的第一个字符/与由第二字符\)。在perl中,您可以使用以下方法执行此操作:

s#\\ | /#("  "," \\","/ ","/\\")[rand 4]#eg

如果结果行然而包含\/(禁止连接)或没有/\根本(螺栓模具和没有到达底部)的结果是无效的。在这种情况下,我将整个行扔掉,然后再试一次。一个有效的延续总是存在的,并且如果您尝试的次数足够多,将会发现一个延续(例如,除了1个流,其他所有事物都消失了)。这与建议的反重叠算法的概率分布略有不同,但我认为实际上更好,因为它没有方向偏差。有效性可以通过打高尔夫球的方式使用

m#\\|/#>m#\\/#

这里的问题是随机替换是如此繁琐,所有这些\转义也占用了字节。因此,我决定使用数字字符串来构建行/\在打印之前用替换相应的数字。基本的随机替换是

53|16*rand

这给之一53556163以相等的概率。然后我解释5,并1作为3作为\6作为/。那解释了行打印:

say y|3615|\\/ |r

在一场严肃的高尔夫比赛中,我现在将开始系统地探索替代的魔术公式,但这应该是相当不错的(在3个字节以内)

该程序的其余部分:

1x$_.6

这将初始化$_(请参见下一张地图)为高度空间,然后是/。这是第一个要打印的上方的不可见行,并确保该字段足够宽,以使螺栓永远不会耗尽左侧的空间

map{ ... ; say ...}(1x$_.6)x$_

我将处理相同的初始字符串高度,每次打印新行

$_=$;until$;=$_,...

将当前行保存在中$;。如果替换结果无效,请$_$;

s/.6|3.?/53|16*rand/eg

进行实际替换。我不必检查前后是什么/\因为它必须是一个空格。这很方便,因为空间可以用1或表示5。由于我只将字符串填充到了左边\,所以仍然缺少空格,因此请将该字符设置为可选

/3|6/>/36/

检查新行是否有效


+1整洁!您应该包括这个在线测试仪 perl -M5.010 main.pl <<< 25,我得到了一些不错的输出!
祖卡伯格'16

介意一下它是如何工作的?产生它们的过程我玩得很开心哈哈,老实说,我没想到会有这么好的结果。
祖卡伯格'16

不幸的是,您需要为添加3个字节-n,因为空格和破折号也是如此。命令行参数使用相同的规则。请参阅第二个要点“特殊调用”:我把那些作为字符计数与没有它们的最短等效调用之间的差异进行计数。
Erik the Outgolfer '16

1
@EriktheGolfer否,+ 1是可以的,因为该程序在命令行上可以正常工作,因为该命令行-nE比仅多1个字符-E。(请参阅您所引用的文章。这也摆脱了需要。-M5.010)我总是将我的代码显示为文件,因为更加方便,但是我总是这样计数选项:如果可以从命令行运行它,则不计算空格和破折号。如果必须在文件中(例如因为使用do$0),我计算空格和破折号
Ton Hospel

@TonHospel哦,我不知道您使用过-E。如果是这样,那你就很好。
Erik the Outgolfer

0

JavaScript(ES6),154个字节

f=(n,r=[],s=" ".repeat(n)+"/",t=s.replace(/ \/|\\ |\\$/g,_=>"  /  \\/\\".substr(Math.random()*8&6,2)))=>n?/^ +$|\\\//.test(t)?f(n,r,s):f(n-1,[...r,t],t):r
<input type="number" min=1 oninput=o.textContent=f(this.value).join`\n`><pre id=o>

我一直在为实现而苦苦挣扎,直到看到@TonHospel的回答,这时它才退化为端口。样本输出:

         /\
        / /\
       /\   \
        /\   \
         /\  /
          / /\
         / / /\
            / /\
            \   \
             \
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.