Il modo del golfista del codice di cercare una biblioteca


15

Sfida:

Ho migliaia di canzoni nella mia collezione musicale e fortunatamente per me il mio lettore preferito ha una funzione di ricerca. Ho anche un grande ricordo: ricordo il titolo di ogni canzone della mia collezione. Tuttavia, sono molto pigro e non mi piace digitare: ogni sequenza di tasti in più è un lavoro ingrato!

  • Qual è la stringa più corta che devo cercare per isolare una canzone? Aiutami a memorizzare un elenco di tasti che posso usare per ridurre al minimo la digitazione durante la ricerca!

Questo è , quindi vince il codice più corto.


Regole:

Dato un elenco di input di titoli di brani, genera un elenco di tasti di ricerca soggetti ai seguenti vincoli:

  1. Ogni titolo del brano deve avere una chiave di ricerca.
  2. Il numero totale di caratteri nell'elenco di output deve essere il meno possibile.
  3. Il mio lettore musicale preferito è foobar2000 :
    • La funzione di ricerca non fa distinzione tra maiuscole e minuscole. ( appleè uguale a aPpLE).
    • Ogni chiave di ricerca deve essere composta da una o più "parole", in qualsiasi ordine, separate da spazi:
      • Ogni parola deve essere una sottostringa del titolo del brano corrispondente.
      • Se la stessa sottostringa viene specificata più volte, è necessario che ciò avvenga più volte nel titolo del brano corrispondente.
      • Se una sottostringa stessa contiene uno spazio, tale sottostringa deve essere racchiusa tra virgolette.

suggerimenti:

  • Spesso, per alcuni titoli di brani, ci sono più chiavi di ricerca che soddisfano la regola 2. In tal caso, ogni tasto lo farà, ma otterrai punti brownie per elencarli tutti.
  • Si può presumere che l'elenco di input includerà solo caratteri ASCII, ma i punti brownie verranno assegnati per la compatibilità UTF-8.
  • La Regola 3 è stata difficile da seguire? Ecco come funziona:


Esempio:

Se la mia collezione musicale consisteva solo di due album, Off the Wall e Thriler di Michael Jackson :

È possibile utilizzare gli elenchi sopra per testare il programma. Ecco la versione non elaborata del secondo elenco:

["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
Hai un esempio che richiede più stringhe per una chiave?
Jonathan Allan,

1
Che ne dici ["Wanta Be A Wanna B","Wanta Bea A Wanna B","Wanna Be A Wanna Bea"]?
Jonathan Allan,

... ma cosa dovrebbero / potrebbero essere se non sono ammessi spazi nelle sottostringhe stesse - nota che tutte le parole intere si scontrano.
Jonathan Allan,

Perché la versione raw è in uno spoiler?
Leaky Nun,

Risposte:


4

Python 2, 556 byte

Provalo online.

-10 byte, grazie a @Riker, @ovs

Mi ci sono volute un paio di sere per far funzionare tutto.
Emette il nome del brano, la matrice di chiavi di ricerca e la lunghezza delle chiavi di ricerca combinate (inclusi spazi e virgolette)

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]

Qualche spiegazione:

T=len

Funzione len()usata molto spesso qui, quindi questa ridenominazione salva byte


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)

Valuta tutte le possibili sottostringhe della lunghezza della stringa n.
eval(...)comando crea zip(s,s[1:],s[2:],...,s[n:])
Crea sottostringhe di lunghezza nda ogni indice di sse possibile. Quindi per s='budd'e n='2'produrrà 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

Filtro per verificare se i tasti forniti (K) sono per un nome di brano univoco.
re.sub è richiesto per più chiavi identiche, come ['nn', 'nn'] negli esempi.


La funzione interna def R(r,t)è ricorsiva per creare tutte le possibili combinazioni di sottostringa, che possono descrivere il nome della canzone.
Ogni combinazione viene confrontata con la più breve attualmente (se presente) con un numero inferiore di combinazioni create - se è più grande, non verrà accettata come tutte le sue derivate.
La funzione utilizza 2 variabili per tracciare lo stato: nper la lunghezza della combinazione di tasti più breve corrente e yper la combinazione stessa


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

Questo calcola la lunghezza della combinazione di tasti. ' '.joinaggiunge spazi tra le chiavi e 2*sum(...)calcola il numero di virgolette necessarie per le chiavi con spazi.


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

Utilizza la prima funzione lambda per ottenere tutte le possibili combinazioni di tasti (di ogni lunghezza possibile) per la stringa corrente.


Due cicli per esaminare tutti i tasti generati e passarli individualmente al passaggio successivo ricorsivo. Posto chiave ( j) è necessaria per correttamente stringa fetta alla fine di esso: r[j+T(u[i][j]):].
Slice fornisce una stringa, che è iniziata dove finisce la chiave corrente, quindi non ci saranno sovrapposizioni.
Se il posto è sconosciuto, chiavi uguali rovinerebbero tutto.


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

Molto più lungo del semplice y, ma le chiavi con spazi dovrebbero essere racchiuse tra virgolette


Questo ... è fantastico. Sei il primo a ottenere la regola 3 giusta!
Ayane,

1
A proposito, dovresti essere in grado di radere due byte rimuovendo 0,in uno dei tuoi intervalli: u=[L(r,i)for i in range(0,T(r))]=> u=[L(r,i)for i in range(T(r))].
Notjagan,

1
Potresti salvare qualche altro byte: nel tuo output, non devi mostrare le stringhe di input e le dimensioni delle stringhe di output.
Ayane,

@ 彩 音 M Grazie! Ho tagliato questi pochi byte dall'intervallo e dall'output.
Dead Possum

1
S=map(str.lower,input())per -5 byte
ovs
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.