Sekme tamamlamayı uygulayın


31

Sekme tamamlama , kısmen yazılmış komutları otomatik olarak tamamlayan kullanışlı bir özelliktir. Bunu uygulayacaksın.

Örneğin, eğer mevcut komutlar olsaydı ['apply','apple','apple pie','eat'], o azaman applbaşlayacak olan tüm komutlar ile ade başlayacağı gibi, tamamlanmış olacaktı appl.

Giriş çıkış

Bir dize, A ve bir dizi dize girmeniz gerekir.

A ile başlayan B'nin en uzun önekini çıkarmanız gerekir.

  • Seçeneklerden hiçbiri A ile başlamazsa, A ile geri dönün.
  • B'nin boş olmadığını ve tüm dizelerin boş olmadığını varsayabilirsiniz.
  • Seçeneklerden herhangi birinin A ile başladığını ya da ortak ön ekin A'dan daha uzun olacağını varsayamazsınız.
  • Büyük / küçük harfe duyarlı veya büyük / küçük harf duyarlı olmayabilir.
  • Yalnızca yazdırılabilir ASCII'yi kullanmanız gerekir.
  • Açıkça bu görevi yapan yerleşiklere izin verilir

Test durumları:

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

Son sınama durumundaki izleyen boşluğa dikkat edin

Bu bir , bu yüzden cevaplarınızı mümkün olduğunca kısa yapın!



Posterity için alfabetik olmayan, yazdırılabilir ASCII karakterleri içeren bir örnek ekleyebilir misiniz?
Conor O'Brien,

Alfabetik olmayan karakterlere sahip diğer örnekler zarar görmedi. Cevabımı sildim, çünkü \​ya da içeren girdilerden kırıldığını fark ettim '.
Dennis,

'Bir örnekte nasıl temsil edileceğinden emin değilim . "Dizeler için kullanırsam , dizeler diğer örneklerden farklıdır.
Nathan Merrill

Bu tam olarak cevabımdaki problemdi. : P
Dennis,

Yanıtlar:


10

JavaScript (ES6), 75 bayt

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

Açıklama: Eşleşen tüm önekleri filtreler, ardından yeni satırlara katılır ve tüm satırların en uzun genel önekini bulan bir regex ile eşleşir. Önek yoksa, regex boş bir dize döndürür, bu durumda orijinal dizeyi döndürürüz.


Sen yerini alabilir e.startsWith(s)ile e.match("^"+s)Currying kapalı bir bayt başka kurtaracak için
Shaun H

@ShaunH matchKeyfi yazdırılabilir ASCII ile kullanamıyorum .
Neil

Ah sağ regex ve kontrol karakterleri. Hala köri (s,a)=>olabilirs=>a=>
Shaun H

7

Jöle , 14 12 bayt

ḣJ$€ċÐff\ṪṪȯ

Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın .

Nasıl çalışır

ḣ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 bayt

-1 bayt için @isaacg öğesine teşekkürler

.xe@F/#z._MQz

Dizelerin listesini ve ardından dizeyi STDIN'de alan ve sonucu basan bir program.

Tüm test durumlarını doğrulayın

Nasıl çalışır

.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 23:16

5

PowerShell v3 +, 112 bayt

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

Bir dize $ave bir dize dizisi olarak girdiyi alır $b. -likeBu öğeleri $bbundan (büyük / küçük harfe duyarsız) çıkarmak için operatörün kullandığı $a, bunları açıkça bir dizi @(...)olarak yayınladığınızdan (sonuç bir skalar gibi bir eşleşme olabilir, bu durumda dizin oluşturma daha sonra başarısız olur) ve bu diziyi saklar $c.

Bu ifmaddeyi oluşturur. İçinde bir şey yoksa $c(yani, hiçbir şey başlamadan $adizi boştur, böylece), sonra çıkış $aile else. Aksi takdirde ...

İlk elemanını bir dizi $colarak charatar ve her elemanın içinden geçiririz , bir öncekiyle sicim oluşturur ve $itelleri kapsülleyici parensler vasıtasıyla boru hattına yerleştiririz. Bunlar süzülür |?{...}( Where-Objectdoğrulamak için maddesinde) .countarasında $colduğu -eqiçin ual .countşeylerin $colduğunu şunlardır -likealt dize (yani alt dize $ c şeyi eşleşir). [-1]Alt dizgilerimizi en kısa sürede en uzun sürede oluşturduğumuz için , sonuçtaki dizgilerin sonuncusuna ihtiyacımız var .

Test Kılıfları

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 bayt

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

Tam program; Girdilerin ayrı satırlarda olması dışında, tam olarak örneklerde verilen dizge ve listeyi stdin'den alır.

Tüm test durumlarını doğrulayın


Neden l.pop()yerine l[-1]?
Cyoce

@Cyoce Çünkü lgenellikle setbu noktada, indekslemeye izin vermeyen (sırasız). (Neyse ki, hem ayarlar hem de listeler desteği pop().)
DLosc

3

Perl, 54 bayt

İçin +2 -Xp(ile birleştirilebilir -e) ve + için -i(birleştirilemez) içerir

-iÖrneğin , STDIN ve opsiyondan sonraki kelimelerin sözlüğünü verin , örneğin:

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

Sadece kod:

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

3

Perl, 61 bayt

İçin +2 içerir -0p

STDIN'deki ilk kelimeleri ve ardından sözlük kelimeleri ile çalıştırın:

tabcompletion.pl
a
apply
apple
apple pie
eat
^D

tabcompletion.pl:

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

2

Python 2, 112 bayt

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 bayt

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

Yardımcı işlev ?, iki dizenin en uzun önekini, her iki dizgede aynı olduğu ve dizgelerin boş olmadığı sürece tekrar tekrar ilk karakteri alarak bulur.

Ana işlevi %ilk verilen ile başlayan listedeki sadece dizeleri tutar sile en uzun ortak önek tarafından kontrol, svarlık s. Geçerli bir yarışma olmamak için, süzerinden boş bir sonuca ulaşır max. Daha sonra, ikili işlevi katlayarak en uzun kullanılan önekleri bulur ?.


2

Python 2,75 bayt

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

Başlangıçta bu cevabı @BetaDecay tarafından kullanılan yerleşik önermek için @xnor için teşekkürler .

Puanlama amacıyla, ÿbir DEL bayt ile değiştirilebilir. İdeone üzerinde test et .


1

D, 88 bayt

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

Kullanımı:

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

Kod basitçe qbaşlangıçta olmayan tüm öğeleri kaldırır p, ardından kalan öğelerin en büyük ilk alt sırasını hesaplar.

Şablonlu parametreler bize iki tekrardan stringve iki taneden daha fazla tekrar kazandırır auto. İstismarın kötüye kullanılması, başka hiçbir öğenin qbaşlayamadığı durumda ele almak için gerekli olan geçici değişkeni ve koşullu koşullardan kaçınmamızı sağlar p.


1

Python 2, 107 102 bayt

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

Puanlama amacıyla, ÿbir DEL bayt ile değiştirilebilir. İdeone üzerinde test et .

5 byte tasarruf için @xnor teşekkürler!


İle os.path.commonprefix Beta bozunumu bulduğumuz gibi , bunu sizin için yaparız olabilir.
xnor

Vay, bu çok fazla bayt kazandırır . Bunu kendin göndermek istemediğine emin misin?
Dennis,

Sadece Beta Decay'in cevabınızla birleştirdiği fikri olduğundan, kendimi göndermekte kendimi haklı hissetmem.
xnor

Çözümünüz için, for c in ...doğrudan yinelemek ve benzeri bir baskıdan sonra hatayı sonlandırmak biraz daha kısa görünüyor if len(set(c))>1:print r or s;_.
xnor

Eğer x bir singleton dizisi ise, bunun başarısız olacağını düşünüyorum .
Dennis,

1

PHP, 167 160 157 152 bayt

<?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;

Değişkenleri preg_grepve ile atayarak 3 bayttan daha fazlasını kaydedebilirim preg_quote.

Yıkmak

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 Bayt

Titus'tan çok yardımı ile teşekkür ederim

<?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 Bayt

32 Bytes array_unique ile Titus kaydeder

<?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;

Titus'un Regex Çözümünün, Titus benim tarzımı geliştirmeme yardım edene kadar daha kısa olduğunu biliyorum. Belki de bulduğum yol senin için ilginç.


1
1) Kasayı düzeltmek için $zile değiştirin . 2) eskidir; Bu değişkeni kullanmıyorsun. (-2) 3) ' den daha kısa . (-1) 4) ' den daha kısa . (-3) 5) Streni içine koyabilirsin . (-5)$sapple, [eat,dine]$l=$i++<$m++$i<=$msubstr($x,0,$i);str_split($x,$i)[0]$r[]=$v
Titus

1
6) <2daha kısa ==1. (1) 7) kullanabilir strstrbirinci döngüde: strstr($v,$s)==$v. (-3)
Titus

1
Let me bu ifadeleri: 5) birleştirebilirsiniz $r[]=$v;$m=max($m,strlen($v));için $m=max($m,strlen($r[]=$v));ve Curlys bırakın. Bu duruma dokunmuyor.
Titus

1
İkinci düşüncede, $mhiç ihtiyacınız yok . Tek ihtiyacınız olan şey, değiştirmelerin minimum uzunluğu> =. Yeni 5) değiştirin {$r[]=$v;$m=max($m,strlen($v));}ile $r[]=$v;}ve <$mile <strlen($r[0])) (-13
Titus

1
Harika! Ve başka bir golf buldum: 9) $r[]=$z=$v;ilk döngüde ve {$s=substr($z,0,$i);foreach($r as$x)if($x[$i]!=$z[$i])break 2;}ikincisi için (-3)
Titus

1

Retina, 60 bayt

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

Sondaki yeni satır önemli. Satırdaki bir dize ve ardından her bir kelimeyi ayrı bir satırda alır (ancak izleyen satır yok!). JavaScript'le aynı şekilde çalışır, ilk satırdaki dizeyle başlayan tüm satırların en uzun önekini eşleştirerek çalışır. Bir tane bulamazsa, o zaman tüm kelimeleri siler.


0

Scala, 119 bayt

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

Açıklama:

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 bayt

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

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

ʒ   }           # 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 bayt

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

Çevrimiçi deneyin!

Girdiyi önce B, sonra A olarak alır.

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