ทำให้ตัวอักษร


31

พิจารณารายการคำที่เรียงตามตัวอักษรต่อไปนี้:

balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom

คำทั้งหมดเริ่มต้นด้วยbและ 5 balเริ่มต้นครั้งแรกกับ ถ้าเราแค่ดูที่ 2 คำแรก:

balderdash
ballet

เราสามารถเขียนแทน:

balderdash
  +let

โดยที่' 'จะใช้โดยที่คำที่ใช้ร่วมกันอักขระนำหน้ากับคำก่อนหน้า; ยกเว้น'+'อักขระที่ระบุอักขระสุดท้ายที่คำที่สองใช้คำนำหน้าร่วมกับคำก่อนหน้า

นี่คือการจัดเรียงของ'Trie'สร้างภาพ: ผู้ปกครองคือ ' bal' และมี 2 ลูกหลาน: และ'derdash''let'

ด้วยรายการที่ยาวขึ้นเช่น:

balderdash
ballet
brooding

เราสามารถใช้อักขระไพพ์เพิ่มเติม'|'เพื่อให้ชัดเจนยิ่งขึ้นเมื่อคำนำหน้าที่ใช้ร่วมกันสิ้นสุดลงดังต่อไปนี้:

balderdash
| +let
+rooding

และต้นไม้ที่เทียบเท่าจะมีรากของ'b'การมีลูกสองคน: ทรีย่อยที่มีราก'al'และและลูกสองคน'derdash'และ'let'; 'rooding'และ

หากเราใช้กลยุทธ์นี้กับรายการดั้งเดิมของเรา

balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom

เราได้ผลลัพธ์ที่ดูเหมือน:

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

หากคำสองคำติดต่อกันในรายการไม่มีคำนำหน้าที่ใช้ร่วมกันจะไม่มีการแทนที่อักขระพิเศษ เช่นสำหรับรายการ:

broom
brood
crude
crumb

เราต้องการผลลัพธ์:

broom
   +d
crude
  +mb

อินพุต

คำในอินพุตจะประกอบด้วยตัวอักษรและตัวเลขเท่านั้น (ไม่มีช่องว่างหรือเครื่องหมายวรรคตอน) สิ่งนี้อาจอยู่ในรูปแบบของรายการสตริงสตริงเดี่ยวหรือแนวทางอื่นที่สมเหตุสมผลตราบใดที่คุณระบุรูปแบบที่คุณเลือก ไม่มีคำสองคำติดต่อกันจะเหมือนกัน รายการจะถูกจัดเรียงตามตัวอักษร

เอาท์พุต

เอาต์พุตของคุณสามารถมีช่องว่างต่อท้ายต่อบรรทัดหรือทั้งหมด แต่ไม่มีช่องว่างนำหน้า รายการของสตริงหรือที่คล้ายกันก็จะยอมรับได้

นี่คือ ; รหัสที่สั้นที่สุดในแต่ละภาษาจะสงวนสิทธิ์ในการคุยโว มีข้อห้ามตามปกติต่อช่องโหว่

กรณีทดสอบ

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 

สิ่งที่เกี่ยวกับกรณีที่ผมมีคำว่าหลังจากที่ball balloonเราควรคาดหวังผลลัพธ์ใดบ้าง
Don Thousand

@RushabhMehta ฉันคาดเดาว่าคุณจะได้รับ+ภายใต้แรกoแต่ฉันไม่ได้เขียนความท้าทายดังนั้นฉันไม่แน่ใจ
Theo

5
@RushabhMehta คำเรียงตามตัวอักษรดังนั้นสิ่งนี้จะไม่เกิดขึ้น
Neil

@Neil Oh จุดดี
Don Thousand

2
คำในข้อมูลป้อนเข้าจะประกอบด้วยตัวอักษรและตัวเลขเท่านั้น : นั่นรวมถึงตัวเลขจริง ๆ หรือคุณหมายถึงตัวอักษร?
Arnauld

คำตอบ:


11

เรติน่า 0.8.2 , 58 57 ไบต์

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

ลองออนไลน์! ลิงก์มีกรณีทดสอบหนึ่งกรณี แก้ไข: บันทึกไว้ 1 ไบต์ขอบคุณที่ @FryAmTheEggman ชี้ให้เห็นว่าผมมองข้ามสลับจาก\bการทำไปโดย^ m)คำอธิบาย:

m)

เปิดต่อบรรทัด^สำหรับโปรแกรมทั้งหมด

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

สำหรับแต่ละคำพยายามจับคู่ให้มากที่สุดเท่าที่จะทำได้จากจุดเริ่มต้นของคำก่อนหน้า +เปลี่ยนการแข่งขันไปที่ช่องว่างยกเว้นตัวอักษรตัวสุดท้ายซึ่งจะกลายเป็น

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

แทนที่ช่องว่างทั้งหมดทุกครั้งที่อยู่เหนือ+s หรือ|s ด้วย|s


@FryAmTheEggman แน่นอนฉันได้เพิ่มm)เฉพาะเพื่อให้สามารถทำเช่นนั้นดังนั้นฉันรำคาญที่ฉันพลาดตัวอย่าง
Neil

อืมทำไมฉันถึงรำคาญที่จะตอบกลับความคิดเห็นหากผู้คนกำลังจะลบพวกเขา ...
Neil

9

JavaScript (ES6), 128 ไบต์

คาดหวังและส่งคืนรายการของตัวละคร

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

ลองออนไลน์!

อย่างไร?

+สามารถแทรกช่องว่างและ's ได้โดยการเดินผ่านคำแรกถึงคำสุดท้ายตามลำดับ แต่|สามารถแทรกposteriori ได้หลังจากที่+มีการระบุ สิ่งนี้สามารถทำได้โดยการทำพาสสองที่แตกต่างกัน แต่เราจะบันทึกตัวชี้ไปยังแต่ละรายการที่ถูกแก้ไขa[~y]เพื่อที่จะสามารถปรับปรุงได้อีกครั้งในmap()ลูปเดียวกัน

ในทางทฤษฎีการแก้ปัญหาที่ง่ายกว่าคือการเดินผ่านคำต่าง ๆ ในลำดับย้อนกลับและย้อนกลับผลลัพธ์เช่นเดียวกับตอนท้ายของกระบวนการ แต่นี่เป็นค่าใช้จ่ายเล็กน้อยใน JS และฉันไม่พบวิธีรับรุ่นที่สั้นกว่าด้วยวิธีนี้

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

คุณจะดูวิธีแก้ปัญหาของฉันฉันมาด้วยตัวเอง แต่มันเตือนความจำของคุณ ดังนั้นถ้ามันใกล้เกินไปคุณสามารถส่งมันเป็นของคุณ (หรือไม่) และไม่ลบมัน :)
DanielIndie

@DanielIndie ไม่ต้องกังวล มันแตกต่างกันพอสมควร
Arnauld


1

Python 263 260 ไบต์

- 3 ไบต์ขอบคุณ Jonathan Frech

รหัส:

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)

ลองออนไลน์!

คำอธิบาย:

วิธีการแก้ปัญหานี้สร้าง trie จากคำที่ป้อนเข้ามาและแยกวิเคราะห์มันซ้ำ ๆ ในเอาต์พุตที่ต้องการ ฟังก์ชั่นใช้ trie t และสตริง s และเพิ่ม x เป็น t ความพยายามที่จะดำเนินการตามพจนานุกรมที่ซ้อนกัน แต่ละพจนานุกรมหมายถึงโหนดในคู่ชีวิต ตัวอย่างเช่นพจนานุกรมที่เป็นตัวแทนของคู่ชีวิตที่สร้างขึ้นโดยกรณีทดสอบครั้งแรกมีลักษณะดังนี้:

{'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': {}}}}}}

ฟังก์ชั่น p เกิดขึ้นอีกครั้งผ่านโครงสร้างนี้และสร้างการแสดงสตริงของคู่ชีวิตที่คาดหวังจากความท้าทาย ฟังก์ชั่น f รับกลุ่มสตริงเป็นอาร์กิวเมนต์เพิ่มทั้งหมดลงในคู่ชีวิตด้วย a แล้วส่งคืนผลลัพธ์ของการเรียก p บนคู่ชีวิต


1
เป็นไปได้252 ไบต์
Jonathan Frech

1

C (gcc) , 165 155 ไบต์

ใช้เวลาสามข้อโต้แย้ง:

  • char** a : อาร์เรย์ของคำที่สิ้นสุดด้วย null
  • char* m : อาร์เรย์ของความยาวของแต่ละคำ
  • int n : จำนวนคำในอาร์เรย์
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;}

ลองออนไลน์!



@Arnauld แน่นอน! แม้ว่าจะไม่ใช่++i<n&j<m[i]&a[i--]พฤติกรรมที่ไม่ได้กำหนด ฉันสามารถใช้ gcc ประเมินจากซ้ายไปขวาได้ไหม
Curtis Bechtel

มีแนวโน้มที่จะเป็นพฤติกรรมที่ไม่ได้กำหนด แต่เรากำหนดภาษาด้วยการใช้งานของพวกเขาดังนั้นตราบใดที่มันทำงานได้อย่างต่อเนื่องกับ gcc รุ่นนี้ฉันคิดว่าไม่เป็นไร
Arnauld

1

Perl 6 , 149 144 142 ไบต์

{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("
")}

ลองออนไลน์!

ฉันแน่ใจว่านี่สามารถเล่นกอล์ฟได้มากขึ้นโดยเฉพาะอย่างยิ่งเมื่อฉันไม่ใช่ผู้เชี่ยวชาญในการจดบันทึก นี้ใช้มากกระบวนการเดียวกันกับคำตอบ Retina นีล



0

Ruby , 118 ไบต์

->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/]&&=?+}}

ลองออนไลน์!

ยอมรับอาร์เรย์ของสตริงเอาต์พุตโดยการแก้ไขอาร์เรย์อินพุตดั้งเดิมแบบ in-place

คำอธิบาย

การแปลงสตริงพื้นฐานไม่ซับซ้อนเกินไป แต่เพื่อที่จะแทรกท่อแนวตั้งอย่างถูกต้องเราจำเป็นต้องวนซ้ำในลำดับย้อนกลับและเนื่องจากreverseวิธีการดังกล่าวค่อนข้างละเอียดเราจะทำมันด้วยวิธีที่ซับซ้อนกว่า ที่นี่เราใช้mapเพียงเพื่อเรียกใช้การวนซ้ำปล่อยให้คำแรกเพียงคำเดียวจากนั้นวนซ้ำโดยใช้ดัชนีลบ:

->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 +
 }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.