Tạo một alphabeTrie


31

Xem xét danh sách các từ được sắp xếp theo thứ tự abc sau đây:

balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom

Tất cả các từ bắt đầu bằng b, và 5 từ đầu tiên bắt đầu bằng bal. Nếu chúng ta chỉ nhìn vào 2 từ đầu tiên:

balderdash
ballet

chúng ta có thể viết thay thế:

balderdash
  +let

trong đó từ ' 'được sử dụng trong đó một từ chia sẻ một ký tự tiền tố với từ trước đó; ngoại trừ '+'ký tự chỉ ra ký tự LAST trong đó từ thứ hai chia sẻ tiền tố với từ trước đó.

Đây là một loại hình ảnh 'trie' : cha mẹ là ' bal' và có 2 con cháu: 'derdash''let'.

Với danh sách dài hơn, chẳng hạn như:

balderdash
ballet
brooding

chúng ta cũng có thể sử dụng ký tự ống '|'để làm cho nó rõ ràng hơn ở nơi tiền tố được chia sẻ kết thúc, như sau:

balderdash
| +let
+rooding

và cây tương đương sẽ có một gốc là 'b'có hai con: cây con có gốc 'al'và hai con của nó 'derdash''let'; và 'rooding'.

Nếu chúng tôi áp dụng chiến lược này vào danh sách ban đầu của chúng tôi,

balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom

chúng tôi nhận được đầu ra trông như:

balderdash    
| +let     
|  +oonfish
|   | +ist 
|   +t     
+rooding   
   +m 

Nếu hai từ liên tiếp trong danh sách không có tiền tố dùng chung, không có ký tự đặc biệt nào được thay thế; ví dụ cho danh sách:

broom
brood
crude
crumb

chúng tôi muốn đầu ra:

broom
   +d
crude
  +mb

Đầu vào

Các từ trong đầu vào sẽ chỉ được tạo thành từ chữ và số (không có dấu cách hoặc dấu chấm câu); nó có thể ở dạng một danh sách các chuỗi, một chuỗi hoặc bất kỳ cách tiếp cận hợp lý nào khác, miễn là bạn chỉ định định dạng đã chọn. Không có hai từ liên tiếp sẽ giống nhau. Danh sách sẽ được sắp xếp theo thứ tự abc.

Đầu ra

Đầu ra của bạn có thể chứa khoảng trắng theo sau trên mỗi dòng hoặc tổng cộng, nhưng không có khoảng trắng hàng đầu. Một danh sách các chuỗi hoặc tương tự cũng sẽ được chấp nhận.

Đây là ; mã ngắn nhất trong mỗi ngôn ngữ vẫn giữ quyền khoe khoang. Các lệnh cấm thông thường chống lại sơ hở được áp dụng.

Các trường hợp thử nghiệm

Input:
apogee
apology
app
apple
applique
apply
apt

Output:
apogee     
 |+logy    
 +p        
 |+le      
 | +ique   
 | +y      
 +t        

Input:
balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom
donald
donatella
donna
dont
dumb

Output:
balderdash 
| +let     
|  +oonfish
|   | +ist 
|   +t     
+rooding   
   +m      
donald     
| |+tella  
| +na      
| +t       
+umb 

Thế còn trường hợp tôi có từ ballsau balloon. Sản lượng nào chúng ta nên mong đợi?
Don Ngàn

@RushabhMehta Tôi đoán bạn sẽ chỉ có một người +dưới quyền đầu tiên o, nhưng tôi đã không viết thử thách nên tôi không chắc chắn.
Theo

5
@RushabhMehta Các từ được sắp xếp theo thứ tự abc, vì vậy điều này sẽ không xảy ra.
Neil

@Neil Oh điểm tốt
Don Ngàn

2
Các từ trong đầu vào sẽ chỉ được tạo thành từ chữ và số : có thực sự bao gồm các chữ số, hoặc bạn có nghĩa là chữ cái?
Arnauld

Câu trả lời:


11

Võng mạc 0.8.2 , 58 57 byte

^((.*).)(?<=\b\1.*¶\1)
$.2$* +
m)+`^(.*) (.*¶\1[+|])
$1|$2

Hãy thử trực tuyến! Liên kết bao gồm một trường hợp thử nghiệm. Chỉnh sửa: Đã lưu 1 byte nhờ @FryAmTheEggman chỉ ra rằng tôi đã bỏ qua một chuyển đổi từ\b để ^thực hiện bởi m). Giải trình:

m)

Bật mỗi dòng ^ cho toàn bộ chương trình.

^((.*).)(?<=^\1.*¶\1)
$.2$* +

Đối với mỗi từ, hãy cố gắng kết hợp càng nhiều càng tốt từ đầu của từ trước đó. Thay đổi trận đấu thành khoảng trắng, ngoại trừ ký tự cuối cùng, trở thành một+ .

+`^(.*) (.*¶\1[+|])
$1|$2

Liên tục thay thế tất cả các khoảng trắng ngay trên +s hoặc |s bằng |s.


@FryAmTheEggman Thật vậy, tôi đã thêm m)cụ thể để có thể làm điều đó, vì vậy tôi rất bực mình vì đã bỏ lỡ một ví dụ.
Neil

Ugh, tại sao tôi thậm chí còn bận tâm trả lời các bình luận nếu mọi người sẽ xóa chúng ...
Neil

9

JavaScript (ES6), 128 byte

Mong đợi và trả về một danh sách các danh sách các nhân vật.

a=>a.map((w,y)=>a[~y]=w.map(m=(c,x)=>(p=a[y-1]||0,m|=c!=p[x])?c:p[x+1]==w[x+1]?' ':(g=y=>a[y][x]<1?g(y+1,a[y][x]='|'):'+')(-y)))

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

Làm sao?

Dấu cách và +dấu có thể được chèn bằng cách đi qua từ đầu tiên đến từ cuối cùng theo thứ tự, nhưng |chỉ có thể được chèn một posteriori sau khi +đã xác định được. Điều này có thể đạt được bằng cách thực hiện hai lần chuyển khác nhau, nhưng thay vào đó chúng tôi lưu một con trỏ vào mỗi mục được sửa đổi a[~y]để sau đó có thể được cập nhật lại trong cùng mộtmap() vòng lặp.

Về lý thuyết, một cách giải quyết đơn giản hơn sẽ là duyệt qua các từ theo thứ tự ngược lại và đảo ngược đầu ra cũng như ở cuối quá trình. Nhưng điều này hơi tốn kém trong JS và tôi đã không tìm ra cách để có được một phiên bản ngắn hơn với phương thức này.

a =>                           // a[] = input array
  a.map((w, y) =>              // for each word w at position y in a[]:
    a[~y] =                    //   save a pointer to the current entry in a[~y]
    w.map(m =                  //   initialize m to a non-numeric value
      (c, x) => (              //   for each character c at position x in w:
        p = a[y - 1] || 0,     //     p = previous word or a dummy object
        m |= c != p[x]         //     set m = 1 as soon as w differs from p at this position
      ) ?                      //     if w is no longer equal to p:
        c                      //       append c
      :                        //     else:
        p[x + 1] == w[x + 1] ? //       if the next characters are still matching:
          ' '                  //         append a space
        : (                    //       else:
            g = y =>           //         g() = recursive function to insert pipes
            a[y][x] < 1 ?      //           if a[y][x] is a space:
              g(               //             do a recursive call to g()
                y + 1,         //               with y + 1
                a[y][x] = '|'  //               and overwrite a[y][x] with a pipe
              )                //             end of recursive call
            :                  //           else:
              '+'              //             make the whole recursion chain return a '+'
                               //             which will be appended in the current entry
          )(-y)                //         initial call to g() with -y (this is ~y + 1)
    )                          //   end of map() over the characters
  )                            // end of map() over the words

bạn sẽ xem xét giải pháp của tôi, tôi đã tự mình nghĩ ra nhưng nó nhắc nhở về giải pháp của bạn. vì vậy nếu nó quá gần, bạn có thể gửi nó dưới dạng của bạn (hoặc không) và xóa nó đi :)
DanielIndie

@DanielIndie Không phải lo lắng. Nó đủ khác biệt.
Arnauld


1

Con trăn 263 260 byte

- 3 byte nhờ Jonathan Frech

Mã số:

p=lambda t,f,g:"\n".join([(f[:-1]+"+"if(a!=min(t))*g else"")+a+p(t[a],(f+" "if len(t[a])>1or a==max(t)else f[:-1]+"| "),1)for a in t])if t else""
def a(t,x):
 if x:c=x[0];t[c]=c in t and t[c]or{};a(t[c],x[1:])
def f(*s):t={};[a(t,i)for i in s];return p(t,"",0)

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

Giải trình:

Giải pháp này xây dựng một bộ ba từ đầu vào và phân tích đệ quy nó thành đầu ra cần thiết. Hàm lấy một trie t và một chuỗi s và thêm x vào t. Tries được thực hiện như từ điển lồng nhau. Mỗi từ điển đại diện cho một nút trong trie. Ví dụ: từ điển đại diện cho bộ ba được tạo bởi trường hợp thử nghiệm đầu tiên trông như thế này:

{'b': {'a': {'l': {'d': {'e': {'r': {'d': {'a': {'s': {'h': {}}}}}}}, 'l': {'e': {'t': {}}, 'o': {'o': {'n': {'f': {'i': {'s': {'h': {}}}}, 'i': {'s': {'t': {}}}}}, 't': {}}}}}, 'r': {'o': {'o': {'d': {'i': {'n': {'g': {}}}}, 'm': {}}}}}}

Hàm p đệ quy thông qua cấu trúc này và tạo ra biểu diễn chuỗi của bộ ba dự kiến ​​của thử thách. Hàm f lấy một chuỗi các chuỗi làm đối số, thêm tất cả chúng vào một trie với a, sau đó trả về kết quả của việc gọi p trên trie.


1
Có thể có 252 byte .
Jonathan Frech

1

C (gcc) , 165 155 byte

Có ba đối số:

  • char** a : một mảng các từ kết thúc null
  • char* m : một mảng độ dài của mỗi từ
  • int n : số lượng từ trong mảng
f(a,m,n,i,j)char**a,*m;{for(i=n;--i;)for(j=0;j<m[i]&j<m[i-1]&a[i][j]==a[i-1][j];j++)a[i][j]=a[i][j+1]^a[i-1][j+1]?43:++i<n&j<m[i]&a[i--][j]%81==43?124:32;}

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



@Arnauld Tất nhiên rồi! Mặc dù ++i<n&j<m[i]&a[i--]hành vi không xác định? Tôi có thể dựa vào gcc đánh giá nó từ trái sang phải không?
Curtis Bechtel

Nó rất có thể là hành vi không xác định. Nhưng chúng tôi xác định ngôn ngữ bằng cách triển khai chúng, miễn là nó hoạt động ổn định với phiên bản gcc này, tôi nghĩ điều đó tốt.
Arnauld

1

Perl 6 , 149 144 142 byte

{1 while s/(\n.*)\s(.*)$0(\+|\|)/$0|$1$0$2/;$_}o{$=({.[1].subst(/^(.+)<?{.[0].index($0)eq 0}>/,{' 'x$0.ords-1~'+'})}for '',|$_ Z$_).join("
")}

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

Tôi chắc chắn rằng điều này có thể được chơi golf nhiều hơn, đặc biệt là vì tôi không phải là một chuyên gia về regexes. Điều này sử dụng nhiều quá trình tương tự như câu trả lời Retina của Neil .



0

Ruby , 118 byte

->a{i=1;a.map{s="";a[i+=j=-1].chars{|c|a[i][j+=1]=i<0&&a[i-1][/^#{s+=c}/]?a[i+1][j]=~/[|+]/??|:?\s:c}[/[| ]\b/]&&=?+}}

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

Chấp nhận một chuỗi các chuỗi, đầu ra bằng cách sửa đổi mảng đầu vào ban đầu tại chỗ.

Giải trình

Việc chuyển đổi chuỗi cơ bản không quá phức tạp, nhưng để chèn các ống thẳng đứng đúng cách, chúng ta cần lặp lại theo thứ tự ngược lại, và vì reversephương thức này khá dài dòng, chúng ta sẽ thực hiện theo cách khó hơn. Ở đây, chúng tôi mapchỉ sử dụng để chạy vòng lặp, để lại từ đầu tiên và sau đó lặp lại từ cuối bằng các chỉ số phủ định:

->a{
 i=1;                   #Initialize word indexer
 a.map{                 #Loop
  s="";                 #Initialize lookup string
  a[i+=j=-1]            #Initialize char indexer and decrement i
  .chars{|c|            #Loop through each char c of current word
   a[i][j+=1]=          #Mofify current word at position j 
    i<0&&               #If it's not the first word and
    a[i-1][/^#{s+=c}/]? #Word above matches current one from start to j
     a[i+1][j]=~/[|+]/? #Then if char below is | or +
      ?|:?\s:c          #Then set current char to | Else to Space Else leave as is
  }[/[| ]\b/]&&=?+      #Finally, replace Space or | at word boundary with +
 }
}
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.