【问题标题】:Code Golf: Sierpinski's Triangle代码高尔夫:谢尔宾斯基三角
【发布时间】:2010-12-16 03:36:08
【问题描述】:

挑战

最短的代码,按字符数输出由以下 ASCII 三角形组成的 N 次迭代的谢尔宾斯基三角形的 ASCII 表示:

 /\
/__\

输入是单个正数。

测试用例

Input:
    2
Output:
       /\
      /__\
     /\  /\
    /__\/__\

Input:
    3
Output:
           /\
          /__\
         /\  /\
        /__\/__\
       /\      /\
      /__\    /__\
     /\  /\  /\  /\
    /__\/__\/__\/__\

Input:
    5
Output:
                                   /\
                                  /__\
                                 /\  /\
                                /__\/__\
                               /\      /\
                              /__\    /__\
                             /\  /\  /\  /\
                            /__\/__\/__\/__\
                           /\              /\
                          /__\            /__\
                         /\  /\          /\  /\
                        /__\/__\        /__\/__\
                       /\      /\      /\      /\
                      /__\    /__\    /__\    /__\
                     /\  /\  /\  /\  /\  /\  /\  /\
                    /__\/__\/__\/__\/__\/__\/__\/__\
                   /\                              /\
                  /__\                            /__\
                 /\  /\                          /\  /\
                /__\/__\                        /__\/__\
               /\      /\                      /\      /\
              /__\    /__\                    /__\    /__\
             /\  /\  /\  /\                  /\  /\  /\  /\
            /__\/__\/__\/__\                /__\/__\/__\/__\
           /\              /\              /\              /\
          /__\            /__\            /__\            /__\
         /\  /\          /\  /\          /\  /\          /\  /\
        /__\/__\        /__\/__\        /__\/__\        /__\/__\
       /\      /\      /\      /\      /\      /\      /\      /\
      /__\    /__\    /__\    /__\    /__\    /__\    /__\    /__\
     /\  /\  /\  /\  /\  /\  /\  /\  /\  /\  /\  /\  /\  /\  /\  /\
    /__\/__\/__\/__\/__\/__\/__\/__\/__\/__\/__\/__\/__\/__\/__\/__\

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

【问题讨论】:

  • 很抱歉,这是一个“通用”高尔夫球,我的想法开始用完了......
  • 我昨晚开始在javascript中使用canvas标签实现这个,所以我认为这不会在这里工作。
  • “我的想法开始枯竭了……” 您一直在努力挖掘“控制台输出数据”的脉络。也许是时候休息一下了。使 Lasers 与众不同的一件事是输入非常重要。或者甚至在整个事情上休息一下,但我已经习惯了星期四的开球时间。即使我没有提交很多解决方案,我也会解决您的大多数问题。
  • LiraNuna,你做得很棒。迄今为止,您的挑战获得最多选票是有原因的。如果您从未发布过另一个帖子,您仍然会是 Stack Overflow 的传奇人物。感谢所有的乐趣!
  • @dmckee:那我会尝试更多地思考激光的方式。尽管设计激光器很困难。我有一些想法,但没有完善。我总是可以开始“反向”系列! (反向蜂箱!)

标签: language-agnostic code-golf rosetta-stone


【解决方案1】:

J

46 个字符,从标准输入读取。

(,.~,~[,.~' '$~#,#)^:(<:>

\n 总是分隔句子,这使得它无法放入 S3 中(只能使用 54 个字符)。 S4 在 162 处有点大,所以我填充它以适应。巧合的是,/\ 是一个法律副词。 ☺

/\ 我=:3 /\ /\ %r=:1!:1 /\ /\ t=:] [r+i /\ /\ /\ /\ b=:'/\',:'/__\' /\ /\ i=:1 -".t /\ /\ /\ /\ h=:(' '$ ~#,#),.] /\ /\ /\ /\ s=:( h^:1 ,d=: ,.~) /\ /\ /\ /\ /\ /\ /\ /\ (,,&(10{a.)"1[s^:(-i)b)(1!:2)(4)

【讨论】:

  • 60 个字符。挑战需要完整的程序。
  • 哇,那里有两个昏昏欲睡的表情符号 (~,~) 和一个微笑的表情符号! (=])。这太可爱了!
  • 我居然看到了另一个:(
  • 我已经在星期五给你 +1 了:p,但是三角形太棒了
【解决方案2】:

对不起,我迟到了。这是基于 A. Rex 的 Perl 解决方案:

                           &I                               
                          ;for                              
                         $x  (2                             
                        ..<>){$E                            
                       .=      $E                           
                      ;my$    y;3*                          
                     33  +3  **  3;                         
                    s".+"$y.=$n.$&x2                        
                   ,$              E.                       
                  $&.$            E"ge                      
                 ;;  $_          .=  $y                     
                }print;;        sub I{($                    
               E,      $n      ,$      F,                   
              $B,$    U)=(    $",$    /,qw                  
             (/   \   _  ))  ;$  _=  $E  .$                 
            F.$B.$E.$n.$F.$U.$U.$B};33333333                

【讨论】:

  • 我打算为 golfscript 做这个,但我没有足够的字符
【解决方案3】:

Golfscript - 46

' /\ /__\ '4/{).+: ;.{ \ ++}%\{.+}%+~ ]}@~(*n*

Golfscript - 47

' /\ /__\ '4/): ;{  +: ;.{ \ ++}%\{.+}%+}@~(*n*

Golfscript - 48

' ': '/\ /__\\'+4/{2 *: ;.{ \ ++}%\{.+}%+}@~(*n*

Golfscript - 51

~' ': '/\ /__\\'+4/\(,{;2 *: ;.{ \ ++}%\{.+}%+}%;n*

与我较短的 python(和 ruby​​)答案相同的算法

Golfscript - 78

2\~(?,{-1*}$1: ;{"  ":$*. 2base.{[$$+' /\ ']=}%n+@@{[$$+"/__\\"]=}%n .2*^: ;}%

与我更长的 python 解决方案相同的算法

这个有重要的换行符

2\~(?,{-1*}$1: ;{"  ":
*. 2base.{[
2*' /\ ']=}%n+@@{[
2*"/__\\"]=}%n .2*^: ;}%

【讨论】:

  • 感谢您的辛勤工作,您推动我尽可能多地剥离我的解决方案 - 我仍然无法击败您的解决方案 :)
  • 这个被选中是因为它是第一个达到 46 个字符标记的。
【解决方案4】:

Go,273 个字符

package main
import(f"fmt";"os";s"strconv";)func main(){var
t=[2]string{" /\\ ","/__\\"};
n,_:=s.Atoi(os.Args[1]);a:=1;N:=a<<uint(n);for
N>0{N-=2;for
k:=0;k<2;k++{for
j:=0;j<N;j++{f.Print(" ")}b:=a;for
b>0{o:=t[k];if
b&1==0{o="    "}f.Print(o);b>>=1}f.Print("\n")}a^=a*2}}

空格很重要。

使用gofmt sierpinski-3.go | perl -p -e's/\t/ /g' 取消最小化:

package main

import (
    "fmt";
    "os";
    "strconv";
)

func main() {
    var t = [2]string{" /\\ ", "/__\\"};
    n, _ := strconv.Atoi(os.Args[1]);
    a := 1;
    N := a << uint(n);
    for N > 0 {
        N -= 2;
        for k := 0; k < 2; k++ {
            for j := 0; j < N; j++ {
                fmt.Print(" ")
            }
            b := a;
            for b > 0 {
                o := t[k];
                if b&1 == 0 {
                    o = "    "
                }
                fmt.Print(o);
                b >>= 1;
            }
            fmt.Print("\n");
        }
        a ^= a * 2;
    }
}

我得到了一个很好的提示去打高尔夫here

【讨论】:

  • 我猜“Go”不是“Golfing Language”的缩写
  • @mobrule:我昨天才开始学习围棋。我确信更有经验的 Go 程序员可以做得更好。不幸的是,由于该语言仅在两天前宣布,因此经验丰富的 Go 程序员并不多。见stackoverflow.com/questions/1712172
  • @LiraNuna:可能只是我一天大的围棋很丑。如果b 包含偶数,则b&amp;1==0 为真。它从 b 中取出底部位并测试它是否为零。这直接来自 Gnibbler 的算法。
  • := 让我觉得我回到了高中 Turbo Pascal 课程。
  • 我不知道 Turbo Pascal,但在 Go 中,x:=1var x int = 1 的缩写,y:="moo"var y string = "moo" 的缩写。它从变量中提取类型。
【解决方案5】:

Python - 102

a=" /\ ","/__\\"
j=' '
for n in~-input()*j:j+=j;a=[j+x+j for x in a]+[x*2for x in a]
print"\n".join(a)

Python - 105

a=" /\ ","/__\\"
j=' '
for n in(input()-1)*j:j+=j;a=[j+x+j for x in a]+[x+x for x in a]
print"\n".join(a)

Python - 109

a=" /\ ","/__\\"
for n in range(1,input()):j=' '*2**n;a=[j+x+j for x in a]+[x+x for x in a]
print"\n".join(a)

Python2.6 - 120

N=1<<input()
a=1
while N:
 N-=2
 for s in" /\ ","/__\\":print' '*N+bin(a)[2:].replace('0',' '*4).replace('1',s)
 a=a^a*2

【讨论】:

【解决方案6】:

Perl,82 笔

此版本不再打印尾随换行符。只需要第一个换行符:

$_=' /\ 
/__\\';
for$x(2..<>){
my$y;
$".=$";
s#.+#$y.=$/.$&x2,$".$&.$"#ge;
$_.=$y
}
print

如果允许命令行切换,那么按照传统的 Perl 高尔夫评分,这是 77+3 杆(第一个换行符是文字):

#!perl -p
$\=' /\ 
/__\\';
$y="",
$".=$",
$\=~s#.+#$y.=$/.$&x2,$".$&.$"#ge,
$\.=$y
for 2..$_

如果您发现改进,请随时编辑我的答案。

【讨论】:

  • 如果您要广泛使用开关,通常将其编写为 shell 调用:perl -pae'code here'(计算 shell 调用的所有字符和 shell 引号作为答案的一部分,这也将禁止您在答案中使用单引号)。但这实际上可能会变得更长。
  • @Chris Lutz:传统的 Perl 高尔夫评分是您的代码长度加上您必须在通常的 perl 上添加的字符数。所以在我的情况下,我认为是 77 笔加上额外的 `-pa` 的 4。
  • @ephemient:我没有计算你刚刚删除的换行符;它们只是出于可读性的原因(如果您可以在这种情况下说“可读性”)。在确定您完成编辑后,我将更改答案以使其清楚。不过,感谢您的帮助。
  • @A.雷克斯 - 我一直计算调用。 (并且#!perl 在我的系统上不是有效的 shebang 行。)
  • 而且(几乎)您在 J 中需要了解的所有内容都链接自一个网页 jsoftware.com/help/dictionary/vocabul.htm
【解决方案7】:

Haskell,153 149 137 125 118 112 个字符: H1>

使用尾递归:

(%)=zipWith(++)
p="  ":p
g t _ 1=t
g t s(n+1)=g(s%t%s++t%t)(s%s)n
main=interact$unlines.g[" /\\ ","/__\\"]p.read

早期版本,@118 个字符:

(%)=zipWith(++)
f 1=[" /\\ ","/__\\"]
f(n+1)=s%t%s++t%t where t=f n;s=replicate(2^n)' ':s
main=interact$unlines.f.read

使用(刚刚弃用!)n+k pattern 节省了 4 个字符。

我喜欢它即使以压缩形式也能读到一半。

编辑:旧主

main=do{n<-getLine;putStr$unlines$f$read n}

【讨论】:

  • 我刚刚在前奏曲中发现的东西可能对main=readLn&gt;&gt;=putStr.unlines.f有帮助
  • zipWith!我知道有更好的方法来做到这一点
【解决方案8】:

Perl

删除换行符时为 94 个字符。

$c=2**<>;$\=$/;for$a(0..--$c){print$"x($c-$a&~1),
map$_*2&~$a?$"x4:$a&1?'/__\\':' /\ ',0..$a/2}

【讨论】:

  • 如果需要,您可以通过使用&lt;&gt; 从标准输入读取来节省 5 个字符。如果您不这样做,pop 仍会保存字符。无论哪种方式,您都可以使用荒谬的构造 $c=2**~-&lt;&gt;;$c=2**~-pop; 来节省 /2 周围的括号。
【解决方案9】:

红宝石 - 85

a=' /\ ','/__\\'
j=' '
2.upto(gets.to_i){j+=j;a=a.map{|x|j+x+j}+a.map{|x|x+x}}
puts a


101 个字符 — /\-modified solution from Rosetta Code
(a=2**gets.to_i).times{|y|puts" "*(a-y-1)+(0..y).map{|x|~y&x>0?'  ':y%2>0?x%2>0?'_\\':'/_':'/\\'}*''}

【讨论】:

    【解决方案10】:

    Python,135 个字符

    S=lambda n:[" /\\ ","/__\\"]if n==1 else[" "*(1<<n-1)+x+" "*(1<<n-1)for x in S(n-1)]+[x+x for x in S(n-1)]
    for s in S(input()):print s
    

    【讨论】:

    • 这可以通过将 int(raw_input()) 更改为 input() 来稍微缩短
    【解决方案11】:

    MATLAB - 64 个字符(脚本版本)

    这假设您已经在工作区中定义了变量 N

    A=[' /\ ';'/__\'];for i=1:N-1,B=32*ones(2^i);A=[B A B;A A];end;A
    

    MATLAB - 78 个字符(m 文件函数版本)

    N 作为参数传递给函数s

    function A=s(N),A=[' /\ ';'/__\'];for i=1:N-1,B=32*ones(2^i);A=[B A B;A A];end
    

    【讨论】:

      【解决方案12】:

      C

      Perl 答案的算法相同,但权重更大,有 131 个必要字符。

      a,b;main(c,v)char**v;{c=1<<atoi(v[1]);for(a=0;a<c;a++,puts(""))
      for(b=c;b--;write(1,b&~a?"    ":a&1?"/__\\":" /\\ ",4-2*(b>a)))--b;}
      

      我认为write(1,…) 是 UNIX API,但这似乎也可以在 Windows 上编译和运行。

      如果将char 替换为int,它会节省一个字符并且仍然有效,但它的合法性值得怀疑。

      【讨论】:

      • write() 是一个 Unix API,也是 POSIX 的一部分,但是 Windows 提供了很多 POSIX 函数。它们都被“弃用”了,所以要在 Windows 上“正确”,你应该使用_write() 但是a)这是代码高尔夫,b)不推荐使用 POSIX 的想法让我咯咯笑。
      【解决方案13】:

      徽标(不完全符合要求):47 个字符

      to F:n if:n[repeat 3[F(:n-1)fd 2^:n rt 120]]end
      

      我只用http://www.calormen.com/Logo/ 对此进行了测试,所以我不知道它是否可移植。它不符合要求,但肯定徽标必须是这里的适当语言吗? :) 我喜欢在写 logo 的时候比 Golfscript 和 J 少一个字符。

      【讨论】:

        【解决方案14】:

        Lua,139 个字符

        t={" /\\ ","/__\\"}for i=2,(...)do for j=1,#t do
        t[#t+1]=t[j]:rep(2)k=(" "):rep(#t[j]/2)t[j]=k..t[j]..k end end
        print(table.concat(t,"\n"))
        

        【讨论】:

          【解决方案15】:

          Nroff, 542

          $ nroff -rn=5 file.n

          .pl 1
          .nf
          .de b
          . nr i 0
          . while d\\$1\\ni \{\
          .   \\$3 \\$1\\ni \\$2\\ni
          .   nr i +1
          . \}
          ..
          .de push
          . nr i 0
          . while d\\$2\\ni \{\
          .   nr i +1
          . \}
          . nr j 0
          . while d\\$1\\nj \{\
          .   ds \\$2\\ni \&\\*[\\$1\\nj]
          .   nr i +1
          .   nr j +1
          . \}
          ..
          .ds l0 \& /\[rs] \&
          .ds l1 "/__\[rs]
          .ds s \&\ 
          .de o
          . ds \\$2 \&\\*s\\*[\\$1]\\*s
          ..
          .de p
          . ds \\$2 \&\\*[\\$1]\\*[\\$1]
          ..
          .de assign
          . ds \\$2 \&\\*[\\$1]
          ..
          .nr a 2
          .while \na<=\nn \{\
          . ds s \&\*s\*s
          . b l m o
          . b l n p
          . b m l assign
          . push n l
          . nr a +1
          .\}
          .de t
          \\*[\\$1]
          ..
          .b l zz t
          

          【讨论】:

            【解决方案16】:

            F#,225 个字符

            let rec p n=if n=1 then" "else p(n-1)+p(n-1)
            and S n=if n=1 then[" /\\ ";"/__\\"]else let s=S(n-1)in List.append(List.map(fun s->p(n)+s+p(n))s)(List.map(fun x->x+x)s)
            for s in S(int(System.Console.ReadLine()))do printfn"%s"s
            

            【讨论】:

            • 必须有办法缩短这个糟糕的 System.Console.ReadLine...多么浪费字节 ;)
            【解决方案17】:

            Clojure:174 个字符

            从上面的其他人那里窃取的算法。

            (doseq[q((fn f[n](if(= n 1)[" /\\ ""/__\\"](let[z(f(dec n)))](concat(map #(let[y(repeat(Math/pow 2(dec n))\ )](apply str(concat y % y)))z)(map str zz))))))(read))](println q ))

            这些字符中有 38 个是括号。 : (

            (doseq [q ((fn f [n]
                       (if (= n 1)
                         [" /\\ " "/__\\"]
                         (let [z (f (dec n))]
                           (concat
                            (map #(let [y (repeat (Math/pow 2 (dec n))\ )]
                                    (apply str (concat y % y))) z)
                            (map str z z))))) (read))] 
              (println q))
            

            【讨论】:

              【解决方案18】:

              Python,120 个字符(递归解法)

              S=lambda n:n<2and[" /\ ","/__\\"]or[" "*n+x+" "*n for x in S(n/2)]+[x+x for x in S(n/2)]
              print"\n".join(S(1<<input()-1))
              

              我开始在@fserb 停止的地方穿上果岭...

              【讨论】:

                【解决方案19】:

                GolfScript(45 44 个字符)

                ~(' /\ /__\ '4/)@{.+\.{[2$.]*}%\{.+}%+\}*;n*
                

                类似于 gnibbler 的解决方案。我最初的尝试已经很相似了,然后我看了他的一些想法。

                【讨论】:

                  【解决方案20】:

                  Python,186 个字符(UNIX 行终止)

                  for j in range(1,n):
                   for s in p:
                    print s
                   x=2**j;y=2*x;p.extend(['']*x)
                   for i in range(y-1,-1,-1):
                    if i<x:
                     s=' '*x;p[i]=s+p[i]+s
                    else:
                     q=p[i-x];p[i]=q+q
                  

                  【讨论】:

                    【解决方案21】:

                    序言,811 个字符

                    :- module(sierpinsky, [draw/1]).
                    
                    % draw(+Level)
                    draw(N) :- K is 2^(N+1)-1,
                      for(Line, 0, K),
                      draw2(N, Line, true, nl),
                      fail.
                    draw(_).
                    
                    % draw2(+Level, +Line, +Before, +After)
                    draw2(0, 0, Before, After) :- !,
                      Before, write(' /\\ '), After.
                    draw2(0, 1, Before, After) :- !,
                      Before, write('/__\\'), After.
                    draw2(N, Line, Before, After) :- N>0, K is 2^N, Line < K, !, M is N-1,
                      draw2(M, Line, (Before, tab(K)), (tab(K), After)).
                    draw2(N, Line, Before, After) :- N>0, K is 2^N, Line >= K, !, M is N-1,
                      Line2 is Line - K,
                      draw2(M, Line2, Before, draw2(M, Line2, true, After)).
                    
                    % for(+Variable, +Integer, +Integer)
                    for(V, N, M) :- N =< M, V = N.
                    for(V, N, M) :- N < M, K is N+1, for(V, K, M).
                    
                    % tab(+Integer)
                    tab(N) :- for(_, 1, N), write(' '), fail.
                    tab(_).
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2015-01-12
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-10-24
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多