Implementare il completamento della scheda


31

Il completamento della scheda è una funzione utile che completa automaticamente i comandi scritti parzialmente. Lo implementerai.

Ad esempio, se i comandi disponibili fossero ['apply','apple','apple pie','eat'], allora asi completerebbe appl, poiché anche tutti i comandi che iniziano con ainiziano con appl.

Input Output

Devi inserire una stringa, A e un set di stringhe, B.

È necessario emettere il prefisso comune più lungo di tutta la B che inizia con A.

  • Se nessuna delle opzioni inizia con A, restituisce A
  • Puoi presumere che B sia non vuoto e che tutte le stringhe siano non vuote
  • Non puoi supporre che nessuna delle opzioni inizi con A, né che il prefisso comune sarà più lungo di A
  • Puoi distinguere tra maiuscole e minuscole o maiuscole e minuscole.
  • Devi solo gestire ASCII stampabile
  • Sono consentiti incorporati che svolgono esplicitamente questa attività

Casi test:

'a'       ['apply','apple','apple pie','eat'] => 'appl'
'a'       ['apple pie']                       => 'apple pie'
'apple'   ['eat','dine']                      => 'apple'
'program' ['programa','programb']             => 'program'
'*%a('    ['*%a()-T>','*%a()-T<','@Da^n&']    => '*%a()-T'
'a'       ['abs','absolute','answer']         => 'a'
'a'       ['a','abs']                         => 'a'
'one to'  ['one to one','one to many']        => 'one to '

Nota lo spazio finale sull'ultimo caso di test

Questo è un , quindi rendi le tue risposte il più brevi possibile!



Potresti aggiungere un esempio con caratteri ASCII stampabili non alfabetici per i posteri?
Conor O'Brien,

Altri esempi con caratteri non alfabetici non potevano far male. Ho appena cancellato la mia risposta perché mi sono reso conto che si è rotto con input contenenti \​o '.
Dennis,

Non sono sicuro di come rappresentare 'in un esempio. Se uso "per le stringhe, le stringhe sono diverse rispetto ad altri esempi.
Nathan Merrill,

Questo è esattamente il problema della mia risposta. : P
Dennis,

Risposte:


10

JavaScript (ES6), 75 byte

(s,a)=>/^(.*).*(\n\1.*)*$/.exec(a.filter(e=>e.startsWith(s)).join`
`)[1]||s

Spiegazione: filtra tutti i prefissi corrispondenti, quindi si unisce con le nuove righe e le corrispondenze rispetto a una regex che trova il prefisso comune più lungo di tutte le righe. Se non ci sono prefissi, regex restituisce una stringa vuota, nel qual caso restituiamo semplicemente la stringa originale.


Puoi sostituirlo e.startsWith(s)con e.match("^"+s)per un byte spento. Currying ne salverà un altro
Shaun H,

@ShaunH Non posso usarlo matchcon ASCII stampabili arbitrari.
Neil,

Oh giusto regex e personaggi di controllo. si può ancora curry (s,a)=>as=>a=>
Shaun H

7

Gelatina , 14 12 byte

ḣJ$€ċÐff\ṪṪȯ

Provalo online! o verifica tutti i casi di test .

Come funziona

ḣJ$€ċÐff\ṪṪȯ  Main link. Left argument: B. Right argument: A

  $€          Convert the two links to the left into a monadic chain and apply it
              to each string s in B.
 J              Generate the indices of s, i.e., [1, ..., len(s)].
ḣ               Head; for each index i, take the first i characters of s.
              This generates the prefixes of all strings in B.
     Ðf       Filter; keep prefixes for which the link to the left returns 1.
   ċ            Count the number of times A appears in the prefixes of that string.
       f\     Do a cumulative (i.e., keeping all intermediate values) reduce by
              filter, keeping only common prefixes. f/ is a more obvious choice,
              but it errors on an empty array, i.e., when A isn't a prefix of any
              string in B.
         Ṫ    Tail; take the last prefix array (if any) or return 0.
          Ṫ   Tail; take the last common prefix (if any) or return 0.
           ȯ  Logical OR (flat); replace 0 with A, leave strings untouched.

6

Pyth, 14 13 byte

Grazie a @isaacg per -1 byte

.xe@F/#z._MQz

Un programma che accetta l'elenco di stringhe e quindi la stringa su STDIN e stampa il risultato.

Verifica tutti i casi di test

Come funziona

.xe@F/#z._MQz  Program. Inputs: Q, z
        ._MQ   Map prefixes over Q
     /#z       Filter that by count(z)>0, removing the prefixes corresponding to elements
               in Q that do not start with z
   @F          Fold intersection over that. This yields all the common prefixes
  e            Yield the last element of that, giving the longest common prefix, since the
               prefixes are already sorted by length
.x             But if that throws an exception since no elements of Q start with z:
            z  Yield z instead
               Implicitly print

1
f}zT=>/#z
isaacg,

5

PowerShell v3 +, 112 byte

param($a,$b)if($c=@($b-like"$a*")){([char[]]$c[0]|%{($i+="$_")}|?{($c-like"$_*").count-eq$c.count})[-1]}else{$a}

Accetta l'input come una stringa $ae una matrice di stringhe $b. Utilizza l' -likeoperatore per estrarre quegli elementi da $bquello (senza distinzione tra maiuscole e minuscole) con cui inizia $aesplicitamente il cast come array @(...)(poiché il risultato potrebbe essere una corrispondenza come scalare, nel qual caso l'indicizzazione in seguito fallisce), e archiviare tale array in $c.

Questo costituisce la ifclausola. Se non c'è nulla in $c(cioè, nulla inizia con $a, quindi l'array è vuoto), quindi l'output $acon else. Altrimenti ...

Lanciamo il primo elemento di $ccome char-array e passiamo attraverso ciascun elemento, concatenando le stringhe con il precedente $ie posizionando le stringhe sulla pipeline tramite incapsulamento di parentesi. Questi vengono filtrati attraverso |?{...}(la Where-Objectclausola) per verificare che il .countof $csia -eqidentico al .countof delle cose $cche sono -likela sottostringa (ovvero, la sottostringa corrisponde a tutto in $ c). Poiché stiamo costruendo le nostre sottostringhe nell'ordine dal più breve al più lungo, abbiamo bisogno dell'ultima [-1]stringa risultante.

Casi test

PS C:\Tools\Scripts\golfing> $tests=@('a',@('apply','apple','apple pie','eat')),@('a',@('apple pie')),@('apple',@('eat','dine')),@('program',@('programa','programb')),@('one to',@('one to one','one to many')),@('*%a(',@('*%a()-T>', '*%a()-T<', '@Da^n&'))

PS C:\Tools\Scripts\golfing> $tests|%{""+$_[0]+" ("+($_[1]-join',')+") -> "+(.\implement-tab-completion.ps1 $_[0] $_[1])}
a (apply,apple,apple pie,eat) -> appl
a (apple pie) -> apple pie
apple (eat,dine) -> apple
program (programa,programb) -> program
one to (one to one,one to many) -> one to 
*%a( (*%a()-T>,*%a()-T<,@Da^n&) -> *%a()-T

4

Python 2, 122 byte

s=input();l=[x for x in input()if x[:len(s)]==s]or[s];i=len(l[0])
while len(l)>1:i-=1;l=set(x[:i]for x in l)
print l.pop()

Programma completo; prende la stringa e la lista dallo stdin esattamente come indicato negli esempi, tranne che gli input devono essere su linee separate.

Verifica tutti i casi di test


Perché l.pop()invece di l[-1]?
Cyoce,

@Cyoce Perché di lsolito è un seta quel punto, che non consente l'indicizzazione (non ordinata). (Fortunatamente, entrambi i set e gli elenchi supportano pop().)
DLosc

3

Perl, 54 byte

Include +2 per -Xp(abbinabile a -e) e +3 per -i(non abbinabile)

Fornisci il dizionario su STDIN e la parola dopo l' -iopzione, ad esempio:

perl -ia -Xpe '/^\Q$^I\E.*?(?{$F[$a{$&}++]=$&})^/}{$_=pop@F||$^I'
apply
apple
apple pie
eat
^D

Solo il codice:

/^\Q$^I\E.*?(?{$F[$a{$&}++]=$&})^/}{$_=pop@F||$^I

3

Perl, 61 byte

Include +2 per -0p

Esegui con la prima parola seguita dalle parole del dizionario su STDIN:

tabcompletion.pl
a
apply
apple
apple pie
eat
^D

tabcompletion.pl:

#!/usr/bin/perl -0p
/^(.+)
((?!\1).*
)*(\1.*).*
((?!\1).*
|\3.*
)*$|
/;$_=$3||$`

2

Python 2, 112 byte

lambda n,h:[a.pop()for a in[{s[:-i]for s in h if s.find(n)==0}for i in range(-len(`h`),0)]+[{n}]if len(a)==1][0]

2

Haskell, 67 byte

(a:b)?(c:d)|a==c=a:(b?d)
_?_=""
s%l=foldr1(?)$max[s][x|x<-l,x?s==s]

La funzione ausiliaria ?trova il prefisso comune più lungo di due stringhe assumendo ricorsivamente il primo carattere purché sia ​​lo stesso per entrambe le stringhe e le stringhe non sono vuote.

La funzione principale %mantiene innanzitutto solo le stringhe nell'elenco che iniziano con quella data s, verificate dal prefisso comune più lungo con sessere s. Per gestire la mancanza di competizioni valide, si aggiunge sun risultato vuoto tramite max. Quindi, trova il prefisso comune più lungo di quelli piegando la funzione binaria ?.


2

Python 2, 75 byte

import os
lambda s,x:os.path.commonprefix([t for t in x if s<=t<s+'ÿ'])or s

Grazie a @xnor per aver suggerito il built-in, originariamente utilizzato da @BetaDecay in questa risposta .

Ai fini del punteggio, ÿpuò essere sostituito con un byte DEL. Provalo su Ideone .


1

D, 88 byte

S f(S)(S p,S[]q){try p=q.filter!(a=>a.startsWith(p)).fold!commonPrefix;catch{}return p;}

Uso:

assert(f("a", ["apply","apple","apple pie","eat"]) ==  "appl");

Il codice rimuove semplicemente tutti gli elementi qche non iniziano con p, quindi calcola la sottosequenza iniziale comune più grande degli elementi rimanenti.

I parametri modellati ci salvano due ripetizioni di stringe una di auto. L'uso improprio dell'eccezione ci consente di evitare la variabile temporanea e condizionale che sarebbe altrimenti necessaria per gestire il caso in cui non vi sono elementi di qpartenza p.


1

Python 2, 107 102 byte

s,x=input();r='';q=1
for c in zip(*[t for t in x if s<=t<s+'ÿ']):q/=len(set(c));r+=c[0]*q
print r or s

Ai fini del punteggio, ÿpuò essere sostituito con un byte DEL. Provalo suProvaloIdeone .

Grazie a @xnor per aver salvato 5 byte!


Con os.path.commonprefix il decadimento Beta trovato , puoi farlo fare il lavoro per te.
xnor,

Wow, questo fa risparmiare un sacco di byte. Sei sicuro di non voler pubblicarlo tu stesso?
Dennis,

Non mi sembra giusto pubblicarlo da solo poiché è solo l'idea di Beta Decay unita alla tua risposta.
xnor

Per la tua soluzione, sembra un po 'più breve per iterare for c in ...direttamente e terminare con errori dopo aver stampato come if len(set(c))>1:print r or s;_.
xnor,

Penso che fallirebbe se x fosse un array singleton.
Dennis,

1

PHP, 167 160 157 152 byte

<?for($r=preg_grep("$^".preg_quote($s=$_GET[s])."$",$a=$_GET[a]);$r[0]>$s&&preg_grep("$^".preg_quote($t=$s.$r[0][strlen($s)])."$",$a)==$r;)$s=$t;echo$s;

Potrei salvare altri 3 byte assegnando variabili con preg_grep e preg_quote, ma eh.

abbattersi

for(
    // find items in $a that start with $s
    $r=preg_grep("$^".preg_quote($s=$_GET[s])."$",$a=$_GET[a]);
    // while the first match is longer than $s
    $r[0]>$s
    // and appending the next character of the first match
    &&preg_grep("$^".preg_quote($t=$s.$r[0][strlen($s)])."$",$a)
    // does not change the matches
    ==$r
;)
    // keep appending
    $s=$t;
return$s;

1

PHP, 156 byte

con tanto aiuto da parte di Tito Grazie

<?foreach($_GET[t]as$v)if(strstr($v,$s=$_GET[s])==$v)$r[]=$z=$v;for(;$i++<strlen($z);){$s=substr($z,0,$i);foreach($r as$x)if($x[$i]!=$z[$i])break 2;}echo$s;

PHP, 199 byte

32 byte vengono salvati da Titus con array_unique

<?foreach($_GET[t]as$v)if(strstr($v,$s=$_GET[s])==$v)$r[]=$v;for(;$i++<strlen($r[0]);$a=[]){foreach($r as$x)$a[]=substr($x,0,$i);if(count($r)==count($a)&count(array_unique($a))<2)$s=$a[0];}echo$s;

So che la soluzione Regex di Titus è stata più breve fino a quando Titus mi ha aiutato a migliorare la mia strada. Forse il modo in cui ho trovato è interessante per te


1
1) Sostituire $zcon $sper riparare la apple, [eat,dine]custodia. 2) $l=è obsoleto; Non usi quella variabile. (-2) 3) $i++<$mè più corto di ++$i<=$m. (-1) 4) substr($x,0,$i);è più corto di str_split($x,$i)[0]. (-3) 5) È possibile inserire l' $r[]=$vinterno. (-5)
Tito

1
6) <2è più corto di ==1. (-1) 7) Si potrebbe usare strstrnel primo ciclo: strstr($v,$s)==$v. (-3)
Tito

1
Mi permetta di riformulare che: 5) È possibile combinare $r[]=$v;$m=max($m,strlen($v));per $m=max($m,strlen($r[]=$v));e rilasciare i Curlys. Questo non tocca la condizione.
Tito,

1
A pensarci bene, non è necessario $maffatto. Tutto ciò che serve è qualcosa che sia> = la lunghezza minima delle sostituzioni. Il nuovo 5) Sostituisci {$r[]=$v;$m=max($m,strlen($v));}con $r[]=$v;}e <$mcon <strlen($r[0])(-13)
Tito

1
Grande! E ho appena trovato un altro golf: 9) $r[]=$z=$v;nel primo anello e {$s=substr($z,0,$i);foreach($r as$x)if($x[$i]!=$z[$i])break 2;}per il secondo (-3)
Titus

1

Retina, 60 byte

^(.*)(\n(?!\1).*)*(\n(\1.*)).*(\n((?!\1)|\4).*)*$
$4
s`\n.*

La nuova riga finale è significativa. Prende l'input come stringa su una riga e quindi ogni parola su una riga separata (ma nessuna nuova riga finale!). Funziona in modo simile alla mia risposta JavaScript abbinando il prefisso comune più lungo di tutte le righe che iniziano con la stringa sulla prima riga. Se non ne trova uno, cancella semplicemente tutte le parole.


0

Scala, 119 byte

def f(s:String,a:Seq[Char]*)=a filter(_ startsWith s)reduceOption(_ zip _ takeWhile(t=>t._1==t._2)map(_._1))getOrElse s

Ungolfed:

def tabComplete(input: String, options: Seq[Char]*) = {
  options.
  filter((x: String) => x.startsWith(input)).
  reduceOption((x: Seq[Char], y: Seq[Char]) =>
    x.zip(y).
    takeWhile((t: (Char, Char)) => t._1 == t._2).
    map((t: (Char, Char)) => t._1)
  ).getOrElse(input)
}

Spiegazione:

def g(s:String,a:Seq[Char]*)= //define a method g with a string and a vararg array of strings as parameter
  a filter(_ startsWith s)    //filter the options to contains only elements starting with the input
  reduceOption(               //if the filtered array is nonempty, reduce it: 
    _ zip _                     //zip two elements together
    takeWhile(t=>t._1==t._2)    //take the tuples while they contain the same char
    map(_._1)                   //take the first element from each tuple
  )getOrElse s                //else return the input


0

05AB1E , 14 byte

ʒIÅ?}€ηøʒË}‚˜θ

Provalo online o verifica tutti i casi di test .

Spiegazione:

ʒ   }           # Filter the (implicit) input-list
 IÅ?            #  Does it start with the (second) input-string
                #   i.e. ["codex","bla","codegolf"] and "c" → ["codex","codegolf"]
     €η         # Then take the prefixes of every remaining string
                #  → [["c","co","cod","code","codex"],
                #     ["c","co","cod","code","codeg","codego","codegol","codegolf"]]
       ø        # Zip/transpose; swapping rows/columns
                #  → [["c","c"],["co","co"],["cod","cod"],["code","code"],["codex","codeg"]]
        ʒ }     # Filter:
         Ë      #  Only keep sublists which only contain the same substrings
                #   → [["c","c"],["co","co"],["cod","cod"],["code","code"]]
               # Pair it with the (second implicit) input
                #  → ["c",["c","c"],["co","co"],["cod","cod"],["code","code"]]
                # (workaround if nothing in the input-list starts with the input-string)
            ˜   # Flatten this list
                #  → ["c","c","c","co","co","cod","cod","code","code"]
             θ  # And only leave the last item (which is output implicitly as result)
                #  → "code"

0

Gaia , 12 byte

e…¦&⊢…Ė⁇_+ₔ)

Provalo online!

Accetta input come B, quindi A.

e		| eval B as list of strings
 …¦		| take prefixes of each string
   &⊢		| reduce by set intersection
     …		| take list prefixes of each.
      Ė⁇	| Keep only those with A as an element
	_	| flatten
	 +ₔ	| add A to the beginning of the list
	   )	| take the last element
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.