Bir kütüphane aramanın kod-golfçü yolu


15

Meydan okuma:

Müzik koleksiyonumda binlerce şarkı var ve neyse ki benim için en sevdiğim oyuncunun bir arama fonksiyonu var. Ayrıca harika bir anım var - koleksiyonumdaki her şarkının adını hatırlıyorum. Ancak, çok tembelim ve yazmayı sevmiyorum - her ekstra tuş vuruşu bir angarya!

  • Bir şarkıyı ayırmak için aramam gereken en kısa dize nedir? Arama yaparken yazmayı en aza indirmek için kullanabileceğim tuşların listesini ezberlememe yardım et!

Bu , bu yüzden en kısa kod kazanır.


Kurallar:

Şarkı adlarının bir girdi listesi verildiğinde, aşağıdaki kısıtlamalara tabi arama anahtarlarının bir listesini oluşturun:

  1. Her şarkı başlığının bir arama tuşu olmalıdır.
  2. Çıktı listesindeki toplam karakter sayısı mümkün olduğunca az olmalıdır.
  3. En sevdiğim müzik çalarım foobar2000 :
    • Arama işlevi büyük / küçük harfe duyarlı değildir. ( appleile aynıdır aPpLE).
    • Her arama anahtarı, herhangi bir sırada boşlukla ayrılmış bir veya daha fazla "kelimeden" oluşmalıdır:
      • Her kelime , karşılık gelen şarkı başlığının bir alt dizesi olmalıdır .
      • Aynı alt dize birden çok kez belirtilirse, karşılık gelen şarkı başlığında birçok kez gerçekleşmelidir.
      • Bir alt dizenin kendisi boşluk içeriyorsa, o alt dizenin tırnak işaretleri içine alınması gerekir.

İpuçları:

  • Çoğu zaman, bazı şarkı başlıkları için kural 2'yi karşılayan birden fazla arama tuşu vardır. Böyle bir durumda, herhangi bir anahtar yapar, ancak hepsini listelemek için brownie puanları alırsınız.
  • Giriş listesinin yalnızca ASCII karakterleri olacağını, ancak UTF-8 uyumluluğu için kek puanları verileceğini varsayabilirsiniz.
  • Kural 3'ü takip etmek zor muydu? Şöyle çalışır:


Misal:

Müzik koleksiyonum sadece iki albümden oluşuyorsa, Michael Jackson'ın Duvardan Çıkması ve Gerilim :

Programınızı test etmek için yukarıdaki listeleri kullanabilirsiniz. İkinci listenin ham versiyonu:

["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
Bir anahtar için birden fazla dize gerektiren bir örneğiniz var mı?
Jonathan Allan

1
Nasıl ["Wanta Be A Wanna B","Wanta Bea A Wanna B","Wanna Be A Wanna Bea"]?
Jonathan Allan

... ancak alt dizelerin kendilerinde boşluk bırakılmazsa ne olmalılar da olabilirler - bütün kelimelerin çarpıştığına dikkat edin.
Jonathan Allan

Ham versiyon neden bir spoilerde?
Leaky Nun

Yanıtlar:


4

Python 2, 556 bayt

Çevrimiçi deneyin.

-10 bayt, @Riker, @ovs sayesinde

Her ţeyin çalýţmasý için bana birkaç akţam aldý.
Şarkı adı, arama tuşu dizisi ve birleştirilmiş arama tuşu uzunluğu (boşluklar ve tırnak işaretleri dahil)

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]

Bazı açıklamalar:

T=len

İşlev len()burada çok sık kullanılır, bu nedenle bu yeniden adlandırma bayt tasarrufu sağlar


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)

N uzunluğunun tüm olası alt dizelerini değerlendirir.
eval(...)komut zip(s,s[1:],s[2:],...,s[n:])
oluşturur Mümkünse nher dizinden uzunluk alt dizeleri oluşturur s. Yani s='budd've bu, ud, ddn='2' üretecek


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

Sağlanan tuşların (K) benzersiz şarkı adı olup olmadığını kontrol etmek için filtreleyin.
re.sub, örneklerde ['nn', 'nn'] gibi birden çok özdeş anahtar için gereklidir.


İç işlev def R(r,t), şarkı adını açıklayabilecek tüm olası alt dize kombinasyonlarını oluşturmak için yinelemeli bir işlevdir .
Her kombinasyon, daha az sayıda oluşturulan kombinasyon ile şu anda en kısa olanla (varsa) karşılaştırılır - daha büyükse, tüm türevleri olarak kabul edilmez.
Fonksiyon durumu izlemek için 2 değişken kullanır: nmevcut en kısa tuş kombinasyonunun uzunluğu ve ykombinasyonun kendisi için


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

Bu tuş kombinasyonunun uzunluğunu hesaplar. ' '.jointuşlar arasına boşluk ekler ve boşluklu tuşlar 2*sum(...)için gereken tırnak sayısını hesaplar.


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

Geçerli dize için olası tüm tuş kombinasyonlarını (olası her uzunlukta) elde etmek için ilk lambda işlevini kullanır.


Oluşturulan tüm anahtarlara bakmak ve bunları bir sonraki özyinelemeli basamağa geçirmek için döngüler için iki. Anahtar yer ( j) bunun sonunda doğru dilim dizeye gereklidir: r[j+T(u[i][j]):].
Dilim, geçerli anahtarın bittiği yerde başlayan dize sağlar, böylece çakışma olmaz.
Yer bilinmiyorsa, eşit anahtarlar her şeyi karıştırır.


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

Sadece çok daha uzun y, ama boşluklu anahtarlar tırnak içine alınmalıdır


Bu harika. Kural 3'ü doğru alan ilk sizsiniz!
ayane

1
Bu arada, 0,aralığınızdan birini kaldırarak iki bayt tıraş edebilmeniz gerekir : u=[L(r,i)for i in range(0,T(r))]=> u=[L(r,i)for i in range(T(r))].
notjagan

1
Birkaç bayt daha kaydedebilirsiniz: çıktınızda, girdi dizelerini ve çıktı dizelerinin boyutunu göstermeniz gerekmez.
ayane

@ 彩 音 M Teşekkürler! Bu birkaç baytı aralık ve çıktıdan kesmiştim.
Dead Possum

1
S=map(str.lower,input())-5 bayt için
ovs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.