Liệt kê tất cả các cây nhị phân với n nút


10

Cho một số nguyên n, liệt kê tất cả các cây nhị phân đầy đủ có thể có n nút nội bộ. (Cây nhị phân đầy đủ có chính xác 2 con trên mỗi nút bên trong). Cấu trúc cây nên được xuất ra dưới dạng một giao dịch đặt hàng trước của cây với 1 đại diện cho một nút bên trong và 0 đại diện cho một nút bên ngoài (Null).

Dưới đây là ví dụ cho một vài n đầu tiên:

0:
0

1:
100

2:
11000
10100

3:
1110000
1101000
1100100
1011000
1010100

Đây là một golf mã với giải thưởng sẽ dành cho ít nhân vật nhất. Các cây nên được xuất một trên mỗi dòng đến thiết bị xuất chuẩn. Chương trình nên đọc n từ dòng lệnh hoặc stdin.


Tôi đã suy nghĩ về vấn đề đó khi tôi đang cố gắng tạo ra một hệ thống chữ viết giống như mê cung
Ming-Tang

Thời hạn chuẩn trước khi tuyên bố giải pháp là gì?
Kyle Mông

Sẽ có bất kỳ quan tâm trong việc thực hiện một biến thể nhỏ của vấn đề này, trong đó đầu ra được yêu cầu phải được đặt hàng và phát trực tuyến?
Kyle Mông

@Kyle Mông Chỉ là ý kiến ​​của tôi, nhưng tôi không nghĩ mình sẽ quan tâm. Đối với tôi, một phần thú vị với những vấn đề này là thử các phương pháp thay thế và yêu cầu một trật tự nhất định có thể sẽ hạn chế số lượng thuật toán khả thi.
Migimaru

Câu trả lời:


3

Perl - 125 79 ký tự

Đếm bao gồm 4 ký tự cho -lncác tùy chọn "". Mất n từ stdin.

Cách tiếp cận mang tính xây dựng mới:

@a=0;map{%a=();map{$a{"$`100$'"}=1while/0/g;}@a;@a=keys%a}1..$_;print for@a

Tạo thành giải pháp cho n bằng cách thay thế một nút bên trong mới ("100") cho mỗi lá ("0"), lần lượt, trong mỗi cây từ giải pháp cho n-1.

. > 100 phương pháp xây dựng trong chỉnh sửa trung gian của ai đó.)

Cách tiếp cận đệ quy trước:

sub t{my$n=shift;if($n){--$n;for$R(0..$n){for$r(t($R)){for$l(t($n-$R)){push@_,"1$l$r"}}}}else{push@_,"0"}@_}print for t$_

Đệ quy đệ quy:

sub tree {
  my ($n) = @_;
  my @result = ();
  if ( $n ) {
    for $right_count ( 0 .. $n-1 ) {
      for $right ( tree( $right_count ) ) {
        for $left ( tree( ($n-1) - $right_count ) ) {
          push @result, "1$left$right";
        }
      }
    }
  }
  else {
    push @result, "0";
  }
  return @result;
}
foreach $tree ( tree($_) ) {
  print $tree;
}

2

PHP (142) (138) (134) (113)

Chạy từ dòng lệnh, tức là "php golf.php 1" xuất ra "100".

EDIT: Cắt 4 ký tự bằng một phương thức thay thế, xây dựng các chuỗi từ 0 thay vì đệ quy xuống từ $ n. Sử dụng PHP 5.3 cho toán tử ternary rút ngắn; mặt khác, cần thêm 2 ký tự.

EDIT 2: Đã lưu thêm 4 ký tự với một số thay đổi đối với các vòng lặp.

EDIT 3: Tôi đã thử một cách tiếp cận khác và cuối cùng tôi đã có được nó dưới phương pháp cũ.

Tất cả các cây có thể được coi là biểu diễn nhị phân của các số nguyên trong khoảng từ 4 ^ n (hoặc 0, khi n = 0) và 2 * 4 ^ n. Hàm này lặp qua phạm vi đó và lấy chuỗi nhị phân của mỗi số, sau đó giảm liên tục bằng cách thay "100" bằng "0". Nếu chuỗi cuối cùng là "0", thì đó là một cây hợp lệ, vì vậy hãy xuất nó.

for($i=$p=pow(4,$argv[1])-1;$i<=2*$p;){$s=$d=decbin($i++);while($o!=$s=str_replace(100,0,$o=$s));echo$s?:"$d\n";}

2

Ruby, 99 94 92 89 87 ký tự

(n=4**gets.to_i).times{|i|s=(n+i-1).to_s 2;t=s*1;0while s.sub!'100',?0;puts t if s==?0}

Đầu vào được đọc từ stdin.

> echo 2 | ruby binary_trees.rb
10100
11000

Chỉnh sửa 1: Thay đổi IO (xem bình luận của Lowjacker)

b=->n{n==0?[?0]:(k=[];n.times{|z|b[z].product(b[n-1-z]){|l|k<<=?1+l*''}};k)}
puts b[gets.to_i]

Chỉnh sửa 2: Thay đổi thuật toán.

b=->n{n==0?[?0]:(k=[];b[n-1].map{|s|s.gsub(/0/){k<<=$`+'100'+$'}};k.uniq)}
puts b[gets.to_i]

Chỉnh sửa 3: Phiên bản hiện có cách tiếp cận thứ ba (sử dụng ý tưởng của Migimaru).

Chỉnh sửa 4: Lại hai nhân vật. Cảm ơn bạn đến Migimaru.


Nó sẽ ngắn hơn một ký tự để chấp nhận đầu vào từ stdin.
Lowjacker

Ngoài ra, bạn không cần *?\n, bởi vì putsin từng phần tử của mảng trong dòng riêng của nó.
Lowjacker

@Lowjacker Cảm ơn bạn.
Howard

Tôi mới bắt đầu cố gắng học Ruby, nhưng tôi nghĩ bạn có thể lưu một nhân vật bằng cách sử dụng 0 thay vì {} trong khi. Ít nhất là nó hoạt động trong NetBeans.
Migimaru

Ngoài ra, phụ! là đủ ở đây thay vì gsub!, vì vậy đó là một nhân vật khác bạn có thể lưu.
Migimaru

1

Ruby 1.9 (80) (79)

Sử dụng phương pháp không đệ quy, mang tính xây dựng được DCharness sử dụng.

EDIT: Đã lưu 1 ký tự.

s=*?0;gets.to_i.times{s.map!{|x|x.gsub(?0).map{$`+'100'+$'}}.flatten!}
puts s&s

0

Haskell 122 ký tự

main=do n<-readLn;mapM putStrLn$g n n
g 0 0=[['0']]
g u r|r<u||u<0=[]
g u r=do s<-[1,0];map((toEnum$s+48):)$g(u-s)(r-1+s)

Vì IO là một phần không quan trọng của mã trong haskell, nên có thể ai đó có thể sử dụng một giải pháp tương tự trong ngôn ngữ khác. Về cơ bản ngẫu nhiên đi trong một hình vuông từ dưới cùng bên trái sang trên bên phải dừng lại nếu đường chéo được chéo. Tương đương như sau:

module BinTreeEnum where

import Data.List
import Data.Monoid

data TStruct = NonEmpty | Empty deriving (Enum, Show)
type TreeDef = [TStruct]

printTStruct :: TStruct -> Char
printTStruct NonEmpty = '1'
printTStruct Empty = '0'

printTreeDef :: TreeDef -> String
printTreeDef = map printTStruct

enumBinTrees :: Int -> [TreeDef]
enumBinTrees n = enumBinTrees' n n where
  enumBinTrees' ups rights | rights < ups = mempty
  enumBinTrees' 0   rights = return (replicate (rights+1) Empty)
  enumBinTrees' ups rights = do
    step <- enumFrom (toEnum 0)
    let suffixes =
          case step of
            NonEmpty -> enumBinTrees' (ups - 1) rights
            Empty -> enumBinTrees' ups (rights - 1)
    suffix <- suffixes
    return (step:suffix)

mainExample = do
  print $ map printTreeDef $ enumBinTrees 4

Lưu ý rằng tôi không có ý định chấp nhận đây là câu trả lời, chỉ nghĩ rằng tôi sẽ ném nó ra khỏi đó.
Kyle Mông

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.