星号病毒


9

给定正整数N(“病毒性”),您的程序应创建一棵ASCII艺术图的树,该树的长度为N的两个分支从左上角向下和/或向右延伸。

在第一个星号之后,每个分支所采用的方向可以是向右或向下,并且此选择应在接下来的每一步中随机选择1

例如,假设输入为5,则输出可能类似于:

***
* ***
**
 **

允许两个分支接触(在相邻的单元格上),但不能重叠(在同一单元格上),因此不允许以下操作:

***
* *
*****
  *
  *

例子

对于input 1,唯一可能的输出是:

**
*

(这将出现在所有有效输出中,因为使两个分支采用相同的路径将导致它们重叠。)

输入的可能输出3包括:

***
* *
**
**
***
*
*

输入7

****
*  **
*   **
*
***
  *

输入10

****
*  *      
*********
  *
  *****

这是 ,因此最短的有效答案(以字节为单位)将获胜。

1.这应该是均匀随机的(即每个方向有50/50的机会),或者与在普通硬件上获得的均匀随机接近。


如果您在使用我的长帖子时遇到任何问题,请发表评论-也许我可以缩短一些时间(我会尽力而为)。
nicael

3
只要学会期望。有时它很忙。有时它像现在一样安静。别忘了,这也是复活节。
扎卡里

我不确定自己的帖子出了什么问题。请那些被否决的人这么善解人意吗?
nicael '18 -4-1

1
最好将IMO N描述为时间:P
ASCII码,仅适用

1
我们可以返回0s和1s 的矩阵而不是空格和星号吗?
dylnan '18

Answers:


5

CJam58 51字节

[TT]{_2_m*\f.+{:-},mR}ri*]ee{~\)S*\{'*t}/}%::a:.+N*

在线尝试!

基本思想是,我们从开始,[0 0]然后向每个元素重复添加0或1(确保除了开始时,它们永远不相等,以避免重叠),收集所有中间结果。

[[0 0] [0 1] [0 2] [0 2] [1 3]]

然后,我们创建一个大型数组,其中每个子数组都包含*原始数组中对应对所给定的索引,并在其他所有位置都留有空格。

["*"
 "**"
 "* *"
 "* * "
 " * * "]

这将产生输出矩阵的对角切片(在实际矩阵中,从左向右移动对应于从右上向左移动)。

然后,我们可以使用::a:.+“去对角线化”并获得结果行:

[ "**** "
  "*  *"
  "** "
  " *"
  ""     ]

3

木炭31 24字节

F²«J⁰¦⁰F⊕θ«¿ι*↓*≔‽²ι¿KK↗

在线尝试!链接是详细版本的代码。最初,我认为将第一步随机化会更容易,但是事实证明,要使第一分支可预测是更加高尔夫的做法。说明:

F²«

使用索引变量循环两次i。(这实际上遍历了一个隐式列表,因此i在循环内进行更改是安全的。)

J⁰¦⁰

跳到画布的原点。

F⊕θ«

循环N+1时间。

¿ι*↓*

打印a *,但根据的值,将光标留在光标的右侧或下方i

‽²ι

i内循环的下一次迭代的值随机化。

¿KK↗

如果当前字符是a *,则意味着我们是第二个分支,我们走了而不是右移,所以右移可纠正此问题。(第一个分支始终向下开始,因此第二个分支始终位于其上方,这意味着我们只需要检查垂直碰撞即可。)


这几乎是正确的,但它打印不N尺度的分支,但N-1大小:)
nicael

@nicael对不起,已修复。
尼尔

您可能已经看过太多次了,但是:23个字节
仅使用ASCII

3

爪哇10,273个 272 268 239字节

n->{var c=new char[++n][n];for(var d:c)java.util.Arrays.fill(d,' ');for(int i=0,j=0,k=0,l=0,r=0,s=0,t=0,u=0;n-->0;){c[i+=r][j+=s]=c[k+=t][l+=u]=42;do{r=t=2;r*=Math.random();t*=Math.random();s=r^1;u=t^1;}while(i+r==k+t&j+s==l+u);}return c;}

在这里在线尝试。

感谢Kevin Cruijssen打高尔夫球29个字节。

非高尔夫版本:

n -> { // lambda taking an int as argument
    var c = new char[++n][n]; // the output; increment the virality since the root does not count
    for(var d : c) // for every line
        java.util.Arrays.fill(d,' '); // initialize it with spaces
    for(int i = 0, j = 0, // coordinates of the first branch
            k = 0, l = 0, // coordinates of the second branch
            r = 0, s = 0, // offsets for the first branch, one will be 0 and the other 1 always except for the first '*' where the two branches overlap
            t = 0, u = 0; // offsets for the second branch, one will be 0 and the other 1 always except for the first '*' where the two branches overlap
        n-- > 0; ) { // decrement virality and repeat as many times
        c[i+=r][j+=s] = c[k+=t][l+=u] = 42; // move according to offsets and place an '*' for each branch, 42 is ASCII code
        do { // randomly pick offsets for both branches
            r = t = 2; // Math.random() provides results in [0,1)
            r *= Math.random(); // flip a coin for the first branch
            t *= Math.random(); // flip another coin for the second
            s = r^1; // set s to 0 if r=1, to 1 if r=0
            u = t^1; // set u to 0 if t=1, to 1 if t=0
        } while(i+r==k+t&j+s==l+u); // repeat if the branches overlap
    }
    return c; // return the output
}

239个字节(我只改变了事物的内部do{},一个位(并放置在整数的for循环)PS的第一部分:在您最初的答案0.5可能已经golfed来.5为好。
凯文Cruijssen

@KevinCruijssen似乎我需要进行数学运算。谢谢:-)
OOBalance

3

Perl 5中208个 124 122 118字节

118个字节,没有换行符,缩进和注释。从stdin中取N

@b=1..2;                            #number of branches is 2
for(1..<>){                         #add length <> (the input) to each branch
  ($x,$y)=@$_                       #get where current branch has its tip now
 ,.5>rand?$x++:$y++                 #increase either x or y
 ,$o[$y][$x]++&&redo                #try again if that place is already occupied
 ,$_=[$x,$y]                        #register new tip of current branch
   for@b                            #...and do all that for each branch 
}
say map$_||!$i++?'*':$",@$_ for@o;  #output the branches

在线尝试!


很好,但是它打印的分支比其应有的短1星号:)
nicael

请再次查看我的问题中的示例:)
nicael '18

哦,我已更改2..$N1..shift现在,还减少了一些字节。
Kjetil S.

1
好答案!您可以使用<>和输入(而不是shift和)参数来保存一些字节,也可以rand为避免调用parense而重新排序。您不需要将您的作业包装到@o任何一个。我尝试使用@b=([],[]);似乎可以使用的方法,但是我没有做太多实验,因此我可能错过了一个边缘情况。希望他们能有所帮助!
Dom Hastings

1
在Perl页面打高尔夫球技巧有一些很好的建议,请务必检查一下!祝好运并玩得开心点!
Dom Hastings

2

Python 2,204字节

from random import*
N=input()
s=eval(`[[' ']*-~N]*-~N`)
s[0][0]='*'
I=x,y=1,0
J=X,Y=0,1
exec"s[y][x]=s[Y][X]='*';i,j,k,l=choice((J+I,I+I,I+J,J+J)[x-2<X:]);x+=i;y+=j;X+=k;Y+=l;"*N
for i in s:print`i`[2::5]

在线尝试!



1

PHP,118字节

for($r="*",$w=$argn+2;$argn--;$r[$q+=rand(0,$r[$q+1]<"*")?:$w]=$r)$r[$p+=rand(!$i++,1)?:$w]=$r;echo wordwrap($r,$w-1);

Elvis运算符需要PHP 5.4或更高版本。更换?:?1:老年人PHP。

与管道一起运行-nR在线尝试


1
如何在那里查看不同的输入?
nicael

@nicael:您可以在网上更改参数$argBak=$argn=
Galen Ivanov

好!不确定这是否是一种“接受”这种输入方式的好方法,但是让社区通过投票来决定
nicael

@nicael在TiO中,只需替换的值$argn。在实际环境中,$argn如果使用将它作为管道运行,则来自STDIN -R。然后它将为输入的每一行执行代码(但我可以肯定PHP不会取消设置它们之间的变量;因此,明确的连续运行更有可能避免令人惊讶的事情。)
Titus

0

红色195190字节

func[n][g: func[s][i: 0 d: s while[i < n][b/(d): #"*"until[r: 1 if 1 = random 2[r: n + 1]b/(d + r) =#" "]d: d + r
i: i + 1]]b:""loop n[loop n[append b" "]append b"^/"]b/1: #"*"g n + 2 g 2 b]

在线尝试!

可读性:

f: func[n][
    g: func[s][
        i: 0
        d: s
        while[i < n][
            b/(d): #"*"
            until[
                r: 1 if 1 = random 2[r: n + 1]
                b/(d + r) = #" "
            ]
            d: d + r
            i: i + 1
        ]
    ]
    b: ""
    loop n[loop n[append b " "]append b "^/"]
    b/1: #"*"
    g n + 2
    g 2
    b
]

0

果冻50 43 41字节

2ḶẊ⁸С+\‘Ṗ
⁸ÇU;Ǥ⁻Q$¿
‘,þ`⁼€þÇS+»þ`Ị$ị⁾* 

在线尝试!

这是一个非常有趣的人。可能会有更多的最佳方法。此方法中也可能需要打高尔夫球。

在发布此消息后,我立即意识到可以,þ`代替aþ,""oþ`Ɗ


0

R148142字节

n=scan();`~`=sample;o=r=k=1;l=c(1,n);for(i in 1:n){r=r+l~1;t=l~1;k=k+"if"(k+t-r,t,l[l!=t]);o=c(o,r,k)};write(c(" ","*")[1:n^2%in%o+1],1,n,,"")

在线尝试!

此外,尽管它不符合输出规范,但是您可以区分两个分支:在线尝试!

说明:

从index开始1,我们分别r通过n或随机选择分支的右移或左移1。然后,我们为branch选择另一个向右或向左移动k,如果它与r行进方向相交,则选择另一个方向。然后,我们使用rk作为索引m,将这些值设置为"*"。迭代n-1时间,然后打印结果。


0

果冻39 38字节

ḣ2+\€Ẏ
2Rd¤ṗẊÇ⁻Q$$¿Ç0,0ṭ‘Ṭ€×þ/$€Sị⁾* Y

在线尝试!

尽管看似无关,但d在这里可以节省一个字节(与我以前的方法相比)。


0

Python 2中191个 187 176字节

from random import*
n=input()
p,q=c=1,1j;s={p,q,0}
exec'z=choice(c);q,p=p+[z,1+1j-z][p+z in s],q;s|={q};'*2*~-n
R=range(n+1)
for y in R:print''.join(' *'[y+x*1jin s]for x in R)

在线尝试!

Python具有对复数形式的本机支持a+bj;这使得一些二维问题更容易处理...

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.