二叉树分形


25

今天的挑战是像这样的示例一样绘制一幅美丽的二叉树

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

您将得到一个正整数作为输入。此输入是高度。上面的示例的高度为六。

您可以提交完整程序或函数,也可以自由使用我们的任何默认IO方法。例如,将允许打印树,返回带换行符的字符串,返回2d char数组,将树保存到文件等。

允许在每行尾随空格。

以下是一些输入及其对应输出的示例:

1:
/\

2:
 /\
/\/\

3:
   /\
  /  \
 /\  /\
/\/\/\/\

4:
       /\
      /  \
     /    \
    /      \
   /\      /\
  /  \    /  \
 /\  /\  /\  /\
/\/\/\/\/\/\/\/\

5:
               /\
              /  \
             /    \
            /      \
           /        \
          /          \
         /            \
        /              \
       /\              /\
      /  \            /  \
     /    \          /    \
    /      \        /      \
   /\      /\      /\      /\
  /  \    /  \    /  \    /  \
 /\  /\  /\  /\  /\  /\  /\  /\
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

不幸的是,输出呈指数增长,因此很难显示更大的示例。这是到8的输出的链接

像往常一样,这是一个挑战,因此存在标准漏洞,并尝试使用您选择的任何语言编写最短的程序。

打高尔夫球快乐!


可以有尾随空格使所有行的长度相同吗?
xnor

@xnor是的,很好。
DJMcMayhem

Answers:


5

Python 2,77个字节

S=s=i=2**input()
while s:print S/s*('/'+' '*(s-i)+'\\').center(s);i-=2;s/=s/i

用尾随空格打印,并以错误终止。

我将此代码从提交的内容中带到了我对无政府状态高尔夫提出的挑战,以及xsot发现的1字节改进。硬编码值128更改为2**input()

这个想法是输出的每一行都是一个段,被复制了一次或多次。输入拆分之后的一半有每个段的一个副本,下一个拆分之后的四分之一有两个副本,依此类推,直到最后一行包含许多段/\

每个段都有一个/\,中间和之间都有空格,以填充到正确的长度。外部填充使用进行center

变量s跟踪每个分段的电流,分段的数目为,S/s因此总宽度为树的宽度S。行号i递减2,并且每当其值为s一半时,就会发生拆分,并且段宽度减半。这是通过表达式完成的s/=s/i。当i到达时0,这将给出一个终止程序的错误。

由于anagolf仅允许程序提交,因此我没有探讨递归函数的可能性,我认为这可能更短。


4

V,32字节

é\é/À­ñLyPÄlx$X>>îò^llÄlxxbPò
|

在线尝试!

十六进制转储:

00000000: e95c e92f c0ad f116 4c79 50c4 6c78 2458  .\./....LyP.lx$X
00000010: 3e3e eef2 5e6c 6cc4 6c78 7862 50f2 0a7c  >>..^ll.lxxbP..|

4

画布,11 字节

/║╶╷[l\;∔↔║

在这里尝试!

说明:

/║          push `/\` ("/" palindromized so this is a Canvas object)
  ╶╷[       repeat input-1 times
     l        get the width of the ToS
      \       create a diagonal that long
       ;∔     prepend that to the item below
         ↔    reverse the thing horizontally
          ║   and palindromize it horizontally

3

Haskell中140个138 135字节

e n=[1..n]>>" "
n!f=(e n++).(++e n)<$>f
f 0=[]
f n=1!f(n-1)++['/':e(2*n-2)++"\\"]
b n|n<2=f 1|t<-b$n-1,m<-2^(n-2)=m!f m++zipWith(++)t t

在线尝试!用调用b 5,返回字符串列表。

漂亮的打印用法:

*Main> putStr . unlines $ b 5
               /\
              /  \
             /    \
            /      \
           /        \
          /          \
         /            \
        /              \
       /\              /\
      /  \            /  \
     /    \          /    \
    /      \        /      \
   /\      /\      /\      /\
  /  \    /  \    /  \    /  \
 /\  /\  /\  /\  /\  /\  /\  /\
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

(部分)说明:

  • e n 产生一个字符串 n空格
  • n!ffn左,右空格填充字符串列表中的每个字符串
  • f n在绘制一个“峰” n2n矩形
  • b n 通过串联两个较小的树并在其上方的新峰居中来绘制二叉树

编辑:-3字节感谢Zgarb!


我认为1!f(n-1)并且m!f m应该节省几个字节。
Zgarb

@Zgarb感谢您指出,这些优先规则有时会造成混乱。
Laikoni '17

2

J49 43 42字节

' /\'{~(|.,-)"1@(=@i.@#,-)^:(<:`(,:@,&*-))

这将得出一个带数字并返回2D字符数组的动词。 在线尝试!

说明

我首先通过迭代辅助动词构造值-1、0和1的矩阵,然后用字符替换数字。辅助动词构造下一个迭代的右半部分,然后水平镜像以生成其余部分。在下面的说明中,,垂直连接2D阵列,水平连接1D阵列。

' /\'{~(|.,-)"1@(=@i.@#,-)^:(<:`(,:@,&*-))  Input is n.
                          ^:(            )  Iterate this verb
                             <:             n-1 times
                               `(       )   starting from
                                    ,&*-    the array 1 -1 (actually sign(n), sign(-n))
                                 ,:@        shaped into a 1x2 matrix:
                                             Previous iteration is y.
                      #                      Take height of y,
                   i.@                       turn into range
                 =@                          and form array of self-equality.
                                             This results in the identity
                                             matrix with same height as y.
                       ,-                    Concatenate with -y, pad with 0s.
       (    )"1@(        )                   Then do to every row:
        |.,-                                 Concatenate reversal to negation.
' /\'{~                                     Finally index entry-wise into string.

1

JavaScript(ES6),105个字节

f=n=>n<2?"/\\":" "+f(n-1).split`/`[0].replace(/|/g,"$`$'$'/$`$`\\$'$'$` \n")+f(n-1).replace(/.*/g,"$&$&")

通过从基础案例递归地构建结果来工作/\。下半部分只是前面的情况,每行重复一次。上半部分比较复杂。好像您要保留前面的情况,只保留两侧,但您还必须担心将字符串填充成两倍的宽度,所以我做了一些正则表达式魔术。通过取前一个案例的前导空格并在每个点处进行拆分,我可以考虑该点之前和之后的空格。在每个匹配项中,前增加1的空间和后减少1的空间;这可以用来定位/\在正确的地方。换行符和填充也添加在这里;除了每行的尾随空格和第一行的前导空格(我必须手动添加)之外,这会处理所有填充。(后续行中的前导空格来自匹配的字符串)。


1

木炭,12字节

FN«→↗⌈X²⊖ι‖M

在线尝试!链接是详细版本的代码。说明:

 N              Input as a number
F «             Loop over implicit range
   →            Move right (because mirroring moves the cursor)
         ι      Current index
        ⊖       Decremented
      X²        Power of 2
     ⌈          Ceiling
    ↗           Draw diagonal line
          ‖M    Mirror image

线长为1、1、2、4、8 ... 2 ^(N-2),因此计算笨拙。



0

批处理,218字节

@echo off
set/a"n=1<<%1"
set s=set t=
%s%/\
set l=for /l %%i in (2,1,%n%)do call
%l% %s% %%t%% 
%l%:l
:l
echo %t%
set/an-=1,m=n^&n-1
%s%%t: /=/ %
%s%%t:\ = \%
if %m% neq 0 exit/b
%s%%t:/ =/\%
%s%%t: \=/\%

注意:第6行在空格处结束。每次通过适当地左右移动分支来工作,但从末尾开始的2 n行除外,在这种情况下,分支将被分支。


0

Haxe,181个字节

function g(n):String return(n-=2)==-1?"/\\":[for(y in 0...1<<n)[for(x in 0...4<<n)x+y+1==2<<n?"/":x-y==2<<n?"\\":" "].join("")].concat([for(y in g(n+1).split("\n"))y+y]).join("\n");

或者,使用一些可选的空格:

function g(n):String
  return
    (n -= 2) == -1
    ? "/\\"
    : [ for (y in 0...1 << n)
        [ for (x in 0...4 << n)
          x + y + 1 == 2 << n
          ? "/"
          : x - y == 2 << n
            ? "\\"
            : " "
        ].join("")
      ].concat([ for (y in g(n + 1).split("\n"))
        y + y
      ]).join("\n");

我在一个解决方案上工作了一段时间,该解决方案首先创建了一个大小正确的空格字符数组,然后迭代地将分叉的路径放得越来越低(并且每次迭代都更加密集)。不过,它仍然保留了230多个字节。这里的方法与@Laikoni的Haskell方法差不多。我不能没有它:String,因为Haxe不够聪明,无法确定返回类型始终是String。

这仅是一个函数,下面是一个完整的程序对其进行测试:

class Main {
    public static function main(){
        function g(n):String return(n-=2)==-1?"/\\":[for(y in 0...1<<n)[for(x in 0...4<<n)x+y+1==2<<n?"/":x-y==2<<n?"\\":" "].join("")].concat([for(y in g(n+1).split("\n"))y+y]).join("\n");
        Sys.println(g(Std.parseInt(Sys.args()[0])));
    }
}

将以上内容放入Main.hx,编译haxe -main Main.hx -neko frac.n并进行测试neko frac.n 44以所需的顺序替换)。


0

PHP,188字节

在线版本

function f($l,$r=0,$m=1){global$a;for(;$i<$l;$i++)$i<$l/2?$a[$i+$r]=str_repeat(str_pad("/".str_pad("",2*$i)."\\",2*$l," ",2),$m):f($l/2^0,$r+$l/2,2*$m);}f(2**$argv[1]/2);echo join("\n",$a);

展开式

function f($l,$r=0,$m=1){
global$a;    
for(;$i<$l;$i++)    
$i<$l/2
    ?$a[$i+$r]=str_repeat(str_pad("/".str_pad("",2*$i)."\\",2*$l," ",2),$m)
    :f($l/2^0,$r+$l/2,2*$m);
}
f(2**$argv[1]/2);
echo join("\n",$a);
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.