วิธีการใช้รหัส - นักกอล์ฟในการค้นหาไลบรารี


15

ท้าทาย:

ฉันมีเพลงหลายพันเพลงในคอลเลกชันเพลงของฉันและโชคดีสำหรับฉันผู้เล่นที่ชื่นชอบมีฟังก์ชั่นการค้นหา ฉันยังมีความทรงจำที่ยอดเยี่ยม - ฉันจำชื่อเพลงทุกเพลงในคอลเลคชั่นของฉันได้ อย่างไรก็ตามฉันขี้เกียจมากและไม่ชอบที่จะพิมพ์ - การกดแป้นพิเศษแต่ละครั้งเป็นงานที่น่าเบื่อ!

  • สตริงที่สั้นที่สุดที่ฉันต้องค้นหาคือแยกหนึ่งเพลงคืออะไร ช่วยฉันจำรายการคีย์ที่ฉันสามารถใช้เพื่อลดการพิมพ์เมื่อค้นหา!

นี่คือดังนั้นรหัสที่สั้นที่สุดจึงชนะ


กฎ:

กำหนดรายการอินพุตของชื่อเพลงสร้างรายการคีย์ค้นหาภายใต้ข้อ จำกัด ต่อไปนี้:

  1. ชื่อเพลงแต่ละชื่อควรมีคีย์ค้นหา
  2. จำนวนอักขระทั้งหมดในรายการผลลัพธ์ต้องน้อยที่สุดเท่าที่จะทำได้
  3. เครื่องเล่นเพลงที่ฉันชอบคือfoobar2000 :
    • ฟังก์ชันการค้นหาไม่คำนึงถึงขนาดตัวพิมพ์ ( appleเหมือนกับaPpLE)
    • แต่ละคีย์การค้นหาจะต้องประกอบด้วย "คำ" อย่างน้อยหนึ่งคำตามลำดับใด ๆ คั่นด้วยช่องว่าง:
      • แต่ละคำจะต้องเป็นสตริงย่อยของชื่อเพลงที่เกี่ยวข้อง
      • หากมีการระบุซับสตริงเดียวกันหลายครั้งจะต้องเกิดขึ้นหลายครั้งในชื่อเพลงที่เกี่ยวข้อง
      • หากสตริงย่อยมีช่องว่างสตริงย่อยนั้นจะต้องล้อมรอบด้วยเครื่องหมายคำพูด

คำแนะนำ:

  • บ่อยครั้งสำหรับชื่อเพลงบางเพลงมีกฎการประชุมหลายคีย์การประชุม 2 ในกรณีเช่นนี้คีย์ใดคีย์หนึ่งจะทำ แต่คุณจะได้รับคะแนนบราวนี่เพื่อแสดงรายการทั้งหมด
  • คุณอาจคิดว่ารายการอินพุตจะเป็นอักขระ ASCII เท่านั้น แต่คะแนนบราวนี่จะได้รับรางวัลสำหรับความเข้ากันได้ UTF-8
  • กฎ 3 ยากต่อการติดตามหรือไม่ นี่คือวิธีการทำงาน:


ตัวอย่าง:

หากคอลเล็กชันเพลงของฉันมีเพียงสองอัลบั้มเท่านั้นOff the Wall and Thrilerของ Michael Jackson :

คุณสามารถใช้รายการด้านบนเพื่อทดสอบโปรแกรมของคุณ นี่คือรุ่น raw ของรายการที่สอง:

["Don't Stop 'Til You Get Enough","Rock with You","Working Day and Night","Get on the Floor","Off the Wall","Girlfriend","She's out of My Life","I Can't Help It","It's the Falling in Love","Burn This Disco Out","Wanna Be Startin' Somethin'","Baby Be Mine","The Girl Is Mine","Thriller","Beat It","Billie Jean","Human Nature","P.Y.T. (Pretty Young Thing)"]

1
คุณมีตัวอย่างที่ต้องการหลายสายสำหรับคีย์หรือไม่?
Jonathan Allan

1
แล้วไง["Wanta Be A Wanna B","Wanta Bea A Wanna B","Wanna Be A Wanna Bea"]ล่ะ
Jonathan Allan

... แต่สิ่งที่ควรจะเป็นถ้าไม่มีการเว้นวรรคในสารตั้งต้น - โปรดสังเกตว่าคำทั้งหมดนั้นชนกัน
Jonathan Allan

ทำไมเวอร์ชั่นดิบในสปอยเลอร์?
Leun Nun

คำตอบ:


4

Python 2, 556 ไบต์

ลองออนไลน์

-10 ไบต์ขอบคุณ @Riker, @ovs

เอาตอนเย็นฉันสองคู่เพื่อทำให้ทุกอย่างทำงานได้
เอาต์พุตชื่อเพลงอาร์เรย์ของคีย์การค้นหาและความยาวของคีย์การค้นหารวมกัน (รวมถึงช่องว่างและเครื่องหมายคำพูด)

import re
S=map(str.lower,input())
T=len
for s in S:
 y=s;n=T(s)
 def R(r,t):
    global n,y
    l=T(' '.join(t))+2*sum(map(lambda x:' 'in x,t))
    if l>n:return
    if(lambda K:T([s for s in S if T(s)-T(reduce(lambda x,y:re.sub(re.escape(y),'',x,1),K,s))==T(''.join(K))])==1)(t)and l<n:y=t;n=l
    u=[(lambda s,n:n and[''.join(y) for y in eval('zip(s%s)'%(''.join(',s[%s:]'%-~x for x in range(n))))]or list(s))(r,i)for i in range(T(r))]
    for i in range(T(r)):
     for j in range(T(r)-i):R(r[j+T(u[i][j]):],t+[u[i][j]])
 R(s,[])
 print[' 'in x and'"%s"'%x or x for x in y]

คำอธิบายบางอย่าง:

T=len

ฟังก์ชั่นlen()ใช้บ่อยมากที่นี่ดังนั้นการเปลี่ยนชื่อนี้จะช่วยประหยัดไบต์


L=lambda s,n:n and[''.join(y) for y in eval('zip(s%s)'%(''.join(',s[%s:]'%-~x for x in range(n))))]or list(s)

หาค่าสตริงย่อยที่เป็นไปได้ทั้งหมดของ string s lenght n
eval(...)สร้างคำสั่งzip(s,s[1:],s[2:],...,s[n:])
มันสร้างสตริงย่อยของความยาวnจากทุกดัชนีsถ้าเป็นไปได้ ดังนั้นs='budd'แล้วn='2'มันจะผลิตbu, ud, dd


F=lambda K:len([s for s in S if len(s)-len(reduce(lambda x,y:re.sub(re.escape(y),'',x,1),K,s))==len(''.join(K))])==1

ตัวกรองเพื่อตรวจสอบว่ามีรหัส (K) สำหรับชื่อเพลงที่ไม่ซ้ำหรือไม่
re.sub มีการร้องขอสำหรับคีย์ที่เหมือนกันหลายรายการเช่น ['nn', 'nn'] ในตัวอย่าง


ฟังก์ชั่นด้านในdef R(r,t)เป็นแบบเรียกซ้ำเพื่อสร้างชุดค่าผสมย่อยที่เป็นไปได้ทั้งหมดซึ่งอาจอธิบายชื่อเพลง
ชุดค่าผสมทุกชุดจะถูกเปรียบเทียบกับชุดค่าผสมที่สั้นที่สุด (หากมี) เพื่อลดจำนวนชุดค่าผสมที่สร้างขึ้น - หากมีชุดค่าผสมที่ใหญ่กว่าชุดค่าผสมจะไม่ได้รับการยอมรับว่าเป็นชุดของสัญญาซื้อขายล่วงหน้าทั้งหมด
ฟังก์ชันใช้ตัวแปร 2 ตัวเพื่อติดตามสถานะ: nสำหรับความยาวของคีย์ผสมที่สั้นที่สุดในปัจจุบันและyสำหรับการรวมกันของมันเอง


l=T(' '.join(t))+2*sum(map(lambda x:' 'in x,t))

สิ่งนี้จะคำนวณความยาวของคีย์ผสม ' '.joinเพิ่มช่องว่างระหว่างคีย์และ2*sum(...)คำนวณจำนวนเครื่องหมายคำพูดที่จำเป็นสำหรับคีย์ที่มีช่องว่าง


u=[L(r,i)for i in range(0,T(r))]

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


สองรอบสำหรับการค้นหาคีย์ที่สร้างขึ้นทั้งหมดและส่งผ่านแต่ละปุ่มไปยังขั้นตอนแบบเรียกซ้ำ สถานที่สำคัญ (Key j) r[j+T(u[i][j]):]เป็นสิ่งจำเป็นเพื่อสตริงชิ้นอย่างถูกต้องที่ปลายของมัน:
Slice จัดเตรียมสตริงซึ่งเริ่มต้นที่คีย์ปัจจุบันสิ้นสุดดังนั้นจะไม่มีการทับซ้อนใด ๆ
หากสถานที่ไม่เป็นที่รู้จักกุญแจเท่ากับจะทำให้ทุกอย่างสับสน


[' 'in x and'"%s"'%x or x for x in y]

นานกว่าเพียงyแต่คีย์ที่มีช่องว่างควรล้อมรอบด้วยคำพูด


นี่มันอัศจรรย์มาก. คุณเป็นคนแรกที่ได้รับกฎ 3 ถูกต้อง!
Ayane

1
โดยวิธีการที่คุณควรจะสามารถที่จะโกนไบต์ที่สองโดยการลบ0,ในหนึ่งในช่วงของคุณ: =>u=[L(r,i)for i in range(0,T(r))] u=[L(r,i)for i in range(T(r))]
notjagan

1
คุณสามารถบันทึกอีกสองสามไบต์: ในเอาต์พุตของคุณคุณไม่จำเป็นต้องแสดงสตริงอินพุตและขนาดของสตริงเอาต์พุต
ayane

@ 彩音 M ขอบคุณ! ฉันตัดแต่งสองสามไบต์นี้จากช่วงและเอาท์พุท
Dead Possum

1
S=map(str.lower,input())สำหรับ -5 ไบต์
ovs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.