Cây nhị phân


25

Thử thách ngày nay là vẽ một cây nhị phân đẹp như như ví dụ này:

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

Bạn sẽ được cung cấp một số nguyên dương làm đầu vào. Đầu vào này là chiều cao của cây . Ví dụ trên có chiều cao sáu.

Bạn có thể gửi một chương trình đầy đủ hoặc một chức năng và bạn có thể tự do sử dụng bất kỳ phương thức IO mặc định nào của chúng tôi . Ví dụ, in cây, trả về một chuỗi với dòng mới, trả về mảng char 2d, lưu cây vào tệp, v.v ... đều được phép.

Không gian lưu trữ trên mỗi dòng được cho phép.

Dưới đây là một số ví dụ về đầu vào và đầu ra tương ứng của chúng:

1:
/\

2:
 /\
/\/\

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

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

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

Thật không may, đầu ra tăng theo cấp số nhân, vì vậy thật khó để hiển thị các ví dụ lớn hơn. Đây là một liên kết đến đầu ra cho 8.

Như thường lệ, đây là một thử thách , vì vậy các sơ hở tiêu chuẩn được áp dụng và cố gắng viết chương trình ngắn nhất có thể bằng bất kỳ ngôn ngữ nào bạn chọn.

Chúc bạn chơi golf vui vẻ!


Có thể có dấu cách để làm cho tất cả các dòng có cùng độ dài không?
xnor

@xnor Vâng, thế là tốt.
DJMcMayhem

Câu trả lời:


5

Python 2, 77 byte

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

In với dấu cách, dấu chấm hết.

Tôi đã lấy mã này từ bài nộp của mình cho một thử thách tôi đặt ra trên Anarchy Golf , cộng với cải tiến một byte được tìm thấy bởi xsot. Giá trị mã hóa của 128 đã được thay đổi thành 2**input().

Ý tưởng là mỗi hàng của đầu ra là một phân đoạn được sao chép một hoặc nhiều lần. Một nửa sau khi phân tách đầu vào có một bản sao của mỗi phân khúc, quý sau lần phân chia tiếp theo có hai bản sao, và cứ như vậy cho đến dòng cuối cùng có nhiều phân đoạn /\.

Mỗi phân đoạn có một /\, với các khoảng trống ở giữa, cũng như ở bên ngoài để đệm theo đúng chiều dài. Các lớp đệm bên ngoài được thực hiện với center.

Biến stheo dõi dòng điện với từng phân đoạn và số lượng phân khúc S/ssao cho tổng chiều rộng là chiều rộng của cây S. Số dòng iđếm ngược xuống 2 giây và bất cứ khi nào giá trị sbằng một nửa thì sẽ xảy ra sự phân tách và độ rộng phân đoạn giảm một nửa. Điều này được thực hiện thông qua các biểu thức s/=s/i. Khi iđạt đến 0, điều này đưa ra một lỗi kết thúc chương trình.

Vì anagolf chỉ cho phép đệ trình chương trình, tôi đã không khám phá khả năng của hàm đệ quy, mà tôi nghĩ có khả năng ngắn hơn.


4

V , 32 byte

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

Hãy thử trực tuyến!

Hexdump:

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

4

Canvas , 11 byte

/║╶╷[l\;∔↔║

Hãy thử nó ở đây!

Giải trình:

/║          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 byte

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

Hãy thử trực tuyến! Gọi với b 5, trả về một danh sách các chuỗi.

Cách sử dụng in đẹp:

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

(một số) Giải thích:

  • e ntạo ra một chuỗi các nkhoảng trắng
  • n!fđệm từng chuỗi trong danh sách các chuỗi fnkhoảng trắng trái và phải
  • f nrút ra một "đỉnh" trong một ncủa 2nhình chữ nhật
  • b n vẽ cây nhị phân bằng cách ghép hai cây nhỏ hơn và đặt một đỉnh mới phía trên chúng

Chỉnh sửa: -3 byte nhờ Zgarb!


Tôi nghĩ 1!f(n-1)m!f mnên tiết kiệm một vài byte.
Zgarb

@Zgarb Cảm ơn bạn đã chỉ ra, những quy tắc ưu tiên đôi khi gây nhầm lẫn.
Laikoni

2

J , 49 43 42 byte

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

Điều này ước tính cho một động từ lấy một số và trả về một mảng ký tự 2D. Hãy thử trực tuyến!

Giải trình

Trước tiên tôi xây dựng một ma trận gồm các giá trị -1, 0 và 1 bằng cách lặp một động từ phụ, sau đó thay thế các số bằng các ký tự. Động từ phụ trợ xây dựng nửa bên phải của lần lặp tiếp theo, sau đó phản chiếu nó theo chiều ngang để tạo ra phần còn lại. Trong phần giải thích sau đây, ,ghép các mảng 2D theo chiều dọc và các mảng 1D theo chiều ngang.

' /\'{~(|.,-)"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 byte

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

Hoạt động bằng cách xây dựng kết quả lên đệ quy từ trường hợp cơ sở /\. Nửa dưới chỉ là trường hợp trước với mỗi dòng được nhân đôi. Nửa trên là một chút khó khăn hơn; Có vẻ như bạn muốn lấy trường hợp trước và chỉ giữ hai bên nhưng bạn cũng phải lo lắng về việc đệm dây để tăng gấp đôi chiều rộng, vì vậy thay vào đó tôi thực hiện một số phép thuật regex. Bằng cách lấy các khoảng trắng hàng đầu từ trường hợp trước và phân tách tại mọi điểm, tôi có thể xem xét các khoảng trắng trước và sau điểm đó. Ở mỗi trận đấu, khoảng trắng trước tăng 1 và khoảng trắng sau giảm 1; điều này có thể được sử dụng để định vị /\ở những nơi chính xác. Các dòng mới và phần đệm cũng được thêm vào đây; việc này sẽ chăm sóc tất cả các phần đệm ngoại trừ một khoảng trắng ở mỗi dòng và một khoảng trắng trên dòng đầu tiên mà tôi phải thêm thủ công. (Không gian hàng đầu trên các dòng tiếp theo đến từ chuỗi phù hợp).


1

Than , 12 byte

FN«→↗⌈X²⊖ι‖M

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Giải trình:

 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

Độ dài dòng là 1, 1, 2, 4, 8 ... 2 ^ (N-2), do đó, tính toán khó xử.



0

Mẻ, 218 byte

@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: \=/\%

Lưu ý: Dòng 6 kết thúc trong một khoảng trắng. Hoạt động bằng cách di chuyển các nhánh trái và phải một cách thích hợp mỗi lần, ngoại trừ trên các hàng cách 2 n từ cuối, trong trường hợp đó các nhánh được rẽ nhánh thay thế.


0

Haxe, 181 byte

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");

Hoặc, với một số khoảng trắng tùy chọ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");

Tôi đã làm việc một lúc với một giải pháp tạo ra một mảng các ký tự không gian có kích thước phù hợp trước, sau đó lặp đi lặp lại các đường rẽ nhánh thấp hơn và thấp hơn (và dày đặc hơn ở mỗi lần lặp). Nó vẫn còn hơn 230 byte, mặc dù. Cách tiếp cận ở đây là khá nhiều cách tiếp cận Haskell của @ Laikoni. Tôi không thể thoát khỏi việc không có :String, bởi vì Haxe không đủ thông minh để xác định rằng kiểu trả về sẽ luôn là Chuỗi.

Đây chỉ là một chức năng, đây là một chương trình đầy đủ để kiểm tra nó:

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])));
    }
}

Đặt ở trên Main.hx, biên dịch haxe -main Main.hx -neko frac.nvà kiểm tra với neko frac.n 4(thay thế 4bằng thứ tự mong muốn).


0

PHP, 188 byte

Phiên bản trực tuyến

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);

Mở rộng

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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.