代码高尔夫:蜘蛛网

36

挑战

编写最短的代码(字符数)以输出与用户输入相等数量的蜘蛛网环。

一个蜘蛛网是通过重建中心环开始的:

   \_|_/
  _/   \_
   \___/
   / | \

然后添加由用户输入的数量相等的环。 环是由 \ / |_ 组成的“蜘蛛圆圈”的另一层,并包裹中心圆。

输入始终保证为单个正整数。

测试用例

Input
    1
Output
      \__|__/
      /\_|_/\
    _/_/   \_\_
     \ \___/ /
      \/_|_\/
      /  |  \

Input
    4
Output
         \_____|_____/
         /\____|____/\
        / /\___|___/\ \
       / / /\__|__/\ \ \
      / / / /\_|_/\ \ \ \
    _/_/_/_/_/   \_\_\_\_\_
     \ \ \ \ \___/ / / / / 
      \ \ \ \/_|_\/ / / /
       \ \ \/__|__\/ / /
        \ \/___|___\/ /
         \/____|____\/
         /     |     \

Input:
    7
Output:
            \________|________/
            /\_______|_______/\
           / /\______|______/\ \
          / / /\_____|_____/\ \ \
         / / / /\____|____/\ \ \ \
        / / / / /\___|___/\ \ \ \ \
       / / / / / /\__|__/\ \ \ \ \ \
      / / / / / / /\_|_/\ \ \ \ \ \ \
    _/_/_/_/_/_/_/_/   \_\_\_\_\_\_\_\_
     \ \ \ \ \ \ \ \___/ / / / / / / /
      \ \ \ \ \ \ \/_|_\/ / / / / / /
       \ \ \ \ \ \/__|__\/ / / / / /
        \ \ \ \ \/___|___\/ / / / /
         \ \ \ \/____|____\/ / / /
          \ \ \/_____|_____\/ / /
           \ \/______|______\/ /
            \/_______|_______\/
            /        |        \

代码计数包括输入/输出(即完整程序)。


11
万圣节快乐! - LiraNuna
3
正数且大于零?这不有点多余了吗? :) - Joren
11
由冗余部门(Department of Redundancy Department)带给您。 - Jerry Coffin
@Kinopiko:是的,请查看较旧的高尔夫问题。 - LiraNuna
1
@Chris - 一个人走进酒吧,讲述一个关于一个人走进酒吧的笑话... - John La Rooy
显示剩余7条评论
15个回答

40

Perl, 164 chars

195 184 171 167 164

print@o=((map{$z=_ x($x=1+$N-$_);$"x$x." /"x$_."\\$z|$z/".'\ 'x$_.$/}0..($N=<>)),
"_/"x++$N."   ".'\_'x$N.$/);
y'/\\'\/',@o||y#_# #,$t++||y#_ # _#,print while$_=pop@o

第一条语句打印出蜘蛛网的上半部分。第二条语句使用音译操作创建了上半部分的倒影。

下一个示例更接近314个字符(有效代码),但更符合这个季节的精神。

           ;               "
         Tr                 Ic
        K|                   |t
       Re                     aT
       ",                     "H
       av                     e
        A:                    -
     )H AL                   LO  W
    ee  N"                   ,"  En
   jo    y_                 Yo    ur
   _      C&&             y";     ##
   &I      ();           $N=      1+
   <>;      $,=  $/;@O  =((     map 
    $" x($   X=$N-$_). ${   f}x$_.$
        B.${U}x$X.$P.${U}x$X.$
    F.${b}x$_,0..$N-1),${g}x$N.(${S}
   x3).${c}x$N);sub I{($F,$B,$U, $P)
  =qw         (/ \\ _ |);;         ${
 S}=        " ";$f=$S.$F;$g=$       U.
 $F     ;$b=$B.$S;$c=$B.${U};}@{    P}=
@{     O};  while($_=pop@{P}  ){     @{
 P}    ||   y:_: :;$spooky++  ||    0|
  0    ||   y@_ @ _@;y:/:8:;   ;    ;
   ;   ;;   y:\\:/:;y:8:\\:;  @O   =
    (  @O    ,$_);}print@O;   q{
       Do     !Discuss:Rel    ig
       io       n,Politi      cs
        ,&                   &T
        heG                 rea
          tP              ump
            ki           n}

感谢http://www.ascii-art.de/ascii/s/spider.txt提供的灵感。
我手工构建了蜘蛛形状的代码,但是在CPAN上可以使用Acme::AsciiArtinator模块来帮助自动化(或至少半自动化)完成此任务。请参考:Acme::AsciiArtinator

1
我认为你可能在那里有太多的字母。 - John La Rooy
通过将"\\ "更改为'\ ',并对"\\_"执行类似操作,来进行调试(Kibbitzing)-2。 - user181548
(更多的闲聊)可以将第一个“print”更改为“warn”,以便于-1。不过有点可疑。 - user181548
谢谢KP。原来您还可以使用y''',从而减少一个\\ - mob
实际上,我尝试了 y''' 但是出现了错误信息。我没有注意到你这样做也是可能的。 - user181548
2
Trick || TreaT:把玩(trick)或者甜蜜(treat)Enjoy Your C&&y:享受你的糖果Have A :-) HALLOWeeN:度过一个微笑的万圣节Do !Discuss: Religion, Politics, && The Great Pumpkin:不要讨论:宗教,政治和南瓜大魔王。 还有什么我错过了吗? :D - LiraNuna

18

Golfscript - 124 字符

所有的空格都是有意义的!如果你不小心在末尾添加了一个换行符,输出结果会多出一个下划线_

~):@,{@\:&-:0' ': *& '/':/+*'\\':~'_':
0*.'|':|\/~ +&*n}%
/+@*   ~
+@*n ~+@*


@/ +*n@,{):& *@&-:( ~+*/[
 ](!=&*.|\~/ +(*n}%

Golfscript - 129 chars

~):@,{@\:&-:0' ': *&' /'*'\\':~'_':
0*.'|'\'/'~ +&*n}%'_/'@*   '\_'@*n ~+@*


@'/ '*n@,{):& *@&-:( ~+*'/'[
 ](!=&*.'|'\~'/ '(*n}%

Golfscript - 133 chars

~):@,{@\:&-:0' ': *&' /'*'\\':~'_':
0*.'|'\'/'~ +&*n}%'_/'@*3 *'\_'@*n' \\'@*3
*@'/ '*n@,{):& *@&-:( ~+*'/''_ '1/(!=&*.'|'\~'/ '(*n}%

只需要去掉63个字符就可以打败这个解决方案! - mob
只剩下 47 个字符了。小心。 - mob
1
糟糕,Perl输了37个字符。我尝试从我的解决方案中删除每四个字符,但这使它停止打印蜘蛛网。 - mob
@mobrule,就这个问题而言,您的解决方案表现更好:) - LiraNuna

9

Python - 212 chars

n=input()+1;b,f,p,u,s='\/|_ '
a=[s*(n-i)+' /'*i+b+u*(n-i)+p+u*(n-i)+f+'\ '*i+s*(n-i)for
i in range(n)]
print"\n".join(a+['_/'*n+s*3+'\_'*n,' \\'*n+u*3+'/ '*n]+[x[::-1]for
x in a[:0:-1]]+[a[0][::-1].replace(u,s)])

5

Perl: 161个字符

请注意,此代码包括源中的起始网址。(末尾的双反斜杠很遗憾。较早版本没有这个。)

$_='
 \_|_/
_/   \_
 \___/ 
 /_|_\\';
for$x(1..<>){
s|(.\S).*([/\\].)|$1$&$2|g;
s|\\(.*)/| \\_$1_/$` /$&\\ |;
s|(\s+)\K/(.*).$| \\$&/$1 /_$2_\\|
}
s|_(?=.*$)| |g;
print

$_ 中的空格是有意义的(当然),但其余部分都不是。如果您有一个小建议可以改进这个,欢迎随时编辑我的代码。例如,Kinopiko 已经巧妙地删减了6个字符!

根据命令行开关的计数方式不同,如果我能正确计算的话,这可能会更短(按照通常的 Perl 高尔夫规则为154):

#!perl -ap
$_='
 \_|_/
_/   \_
 \___/ 
 /_|_\\';
s|(.\S).*([/\\].)|$1$&$2|g,
s|\S(.*).| \\_$1_/$` /$&\\ |,
s|(\s+)\K/(.*).$| \\$&/$1 /_$2_\\|while$F[0]--;
s|_(?=.*$)| |g

将倒数第二行从 1while s|_(.*\\\n)| $1|; 改为 s/_(?=(.*)\s+$)/ /g; - user181548
s/_(?=.*\s+$)/ /g;改为s/_(?=.*\s+$)/ /g; - user181548
+1 我考虑过尝试这样做,但感觉会太长了。哇!干得好。 - John La Rooy

4

Vb.net,Windows控制台,Infer,Strict,Explicit ON。

微软Word说不带空格的442个字符

可能还可以进一步缩减,但这是我的最后更新(尝试#2)

Module z
Sub Main()
    Dim i = CInt(Console.ReadLine), j = i + 1, h = j * 2 + 1, w = h * 2, z = "_", b = " "

    For y = 0 To h
        For x = 0 To w
            Dim l = (x + y Mod 2 + i Mod 2) Mod 2, u = j + y, e = j - y, k = h + e, o = x = h Or x = h - 1
            Console.Write(If(x = h, If(y = j, b, If(y = j + 1, z, "|")), "") & If(x = w, vbLf, If(y = j, If(x Mod 2 = 0 = (x < h), If(o, b, z), If(x < h, "/", "\")), If(x < k And x > u Or (x < u And x > k Or o) And y < h, z, If(x = k Or (x < u And y < j And x > e Or x > u And y > j And x < w + e) And l = 0, "/", If(x = u Or (x > k And y < j And x < h + u Or x < k And y > j And x > y - j - 1) And l = 1, "\", b))))))
        Next
    Next
End Sub
End Module

最终字符数降至700以下,VB在这种游戏中永远不会获胜,但做起来很有趣。 - Fredou
经过重写,不超过500个字符 :-) - Fredou
C#版本肯定会更少字符,大约可以减少60到75个字符。 - Fredou

3

Python: 240个字符

这里没有太多的技巧,只是逐行打印 - 298 280 271 266 265 261 260 254 240个字符(忽略最后两个换行符)

u,b,f,s,a='_\/ |'
m=input()+1
print'\n'.join([(m-x)*s+x*' /'+b+(m-x)*u+a+(m-x)*u+f+x*'\ 'for x in
  range(0,m)]+['_/'*m+s*3+'\_'*m+'\n'+(s+b)*m+u*3+'/ '*m]+[x*s+(m-x)*
  ' \\'+f+x*u+a+x*u+b+(m-x)*'/ 'for x in range(1,m)] + [s*m+f+s*m+a+s*m+b])

1
u,b,f,s,a='_/ |' - John La Rooy
2
在Python 3中,您可以简单地说p=print(因为在Py3k中,print是一个函数而不是关键字)。但是,input必须包装在int中。节省了5个字符。 - Stephan202
1
m = int(raw_input()) + 1 因为你没有在任何地方使用 n - John La Rooy
2
现在我们等待Perl/Ruby黑客的到来,他们会让我们Python用户望尘莫及... - Smashery
3
是的,但是等到Ruby/Perl的人开始挥杆时,Python的人已经在19号洞了 ;) - John La Rooy
显示剩余5条评论

3

Ruby1.9 - 181 chars

n=gets.to_i+1;s=' '
a=0.upto(n-1).map{|i|s*(j=n-i)+' /'*i+?\\+?_*j+'|'+?_*j+?/+'\ '*i+s*j}
d=a.reverse.map{|x|x.reverse};d[-1].tr!?_,s
puts a,'_/'*n+s*3+'\_'*n,' \\'*n+?_*3+'/ '*n,d

Ruby1.8 - 185个字符
一些来自JRL的改进

n=gets.to_i+1;s=' '
u='_';a=0.upto(n-1).map{|i|s*(j=n-i)+' /'*i+'\\'+u*j+'|'+u*j+'/'+'\ '*i+s*j}
d=a.reverse.map{|x|x.reverse}
d[-1].tr!u,s;puts a,'_/'*n+s*3+'\_'*n,' \\'*n+u*3+'/ '*n,d

Ruby - 207个字符
Ruby似乎有一些关于“\”的奇特规则。

n=eval(gets)+1
b,f,p,u,s='\/|_ '.split""
a=0.upto(n-1).map{|i|s*(j=n-i)+' /'*i+b+u*j+"|"+u*j+f+"\\ "*i+s*j}
puts a,'_/'*n+s*3+'\_'*n,' \\'*n+u*3+'/ '*n,a[1..-1].reverse.map{
|x|x.reverse},a[0].reverse.tr(u,s)

3

Ruby1.8, 179

使用 ruby -n 运行

n=$_.to_i+1
u,s,c=%w{_ \  \ \\}
z=(1..n).map{|i|k=n-i
s*i+c*k+'/'+u*i+'|'+u*i+"\\"+'/ '*k+s*i}
y=z.reverse.map{|a|a.reverse}
z[-1].tr!u,s
puts y,'_/'*n+s*3+'\_'*n,c*n+u*3+'/ '*n,z

在下面的第一次尝试中,仅生成一个象限(我选择了左下角),然后镜像两次以获得整个网格似乎是个好主意。但是gnibbler通过生成顶部两个象限(上半部分)并生成而不是修补内部区域来获得更好的结果。因此,我修改了我的方法,最初也生成了另一个下方的象限,只镜像一次,并且还省略了最内层的行,在某种程度上与其他条目相交汇。
n=$_.to_i+1
m=2*n+1
u,s,b,f=%w{_ \  \\ /}
z=(0..n).map{|i|s*i+(s+b)*(n-i)+(i==0?u:f)+u*i}
q=z.reverse.map{|a|a.tr f+b,b+b+f}
q[n].gsub!' ','_'
q[n][m-1]=s
z=(q+z).map{|a|a+'|'+a.reverse.tr(f+b,b+b+f)}
z[n][m]=z[n+1][m]=s
z[m].gsub!u,s
puts z

3

Lua, 290

n = ... --获取输入参数
s = string
r = s.reverse
g = s.gsub
a = "\\|/"
j = (" /"):rep(n+1) .. a .. ("\\ "):rep(n+1)
k = j
o = k
l = n * 4 + 7
-- 循环处理字符串 for i = 1, n + 1 do k = g(k, "^(.- )/(.-)|(.*)\\(.-)$", "%1%2_|_%3%4") o = k .. o end
-- 添加反转后的字符串 o = o .. r(o)
-- 输出结果 print((g(g(g(g(r(g(o:sub(1,l), "_", " ") .. o:sub(l + 1)), j, g(j, " ", "_")), ("."):rep(l), "%1\n"), a, " "), r(a), "___"))

2

C,573个字符

很明显,就字符计数而言,它甚至无法参赛。573这个数字只是我在Windows机器上的文件大小,所以可能算了一些ctrl-M。另一方面,也许573低估了它,因为我为了节省空间而放弃了所有的#include,尽管有警告!

但是,嘿,这是我第一次尝试这种东西,尝试用更紧凑的语言重新表达它肯定是一个很好的练习。

#define B puts("");
#define K '\\'+'/'
#define F '_'+' '
#define P(s) putchar(s);
#define I int
c(I s,I f){if(s){P(f)c(s-1,f);P(f)}else P('|')} 
w(I lw,I s,I k,I f){if(s){P(' ')P(k)w(lw,s-1,k,f);P(K-k)P(' ')}else{P(K-k)c(1+lw,f);P(k)}}
h(I g,I s,I k,I f){I i;for(i=-1;i<g;++i)P(' ')w(g,s,k,f);} 
t(I g,I s){if(s)t(g+1,s-1);h(g,s,'/','_');B}
b(I g,I s){h(g,s,'\\',s?'_':' ');B;if(s)b(g+1,s-1);}
m(I s,I k,I f){if(s){P(f)P(k)m(s-1,k,f);P(K-k)P(f)}else{P(F-f)P(F-f)P(F-f)}}
main(I ac,char*av[]){I s;s=atoi(av[1]);t(0,s);m(1+s,'/','_');B;m(1+s,'\\',' ');B;b(0,s);}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接