Wdróż uzupełnianie kart

31

Uzupełnianie tabulatorów to przydatna funkcja, która automatycznie uzupełnia częściowo napisane polecenia. Zamierzasz to wdrożyć.

Na przykład, jeśli dostępne byłyby polecenia ['apply','apple','apple pie','eat'], auzupełniałoby to appl, ponieważ wszystkie polecenia zaczynające się od arównież zaczynają się od appl.

Wejście wyjście

Musisz wpisać ciąg, A i zestaw ciągów, B.

Musisz podać najdłuższy wspólny przedrostek ze wszystkich B, który zaczyna się na A.

  • Jeśli żadna z opcji nie zaczyna się od A, zwróć A
  • Możesz założyć, że B jest niepusty i że wszystkie ciągi są niepuste
  • Nie można zakładać, że żadna z opcji zaczyna się od A, ani że wspólny prefiks będzie dłuższy niż A.
  • Możesz rozróżniać małe i wielkie litery.
  • Musisz tylko obsługiwać ASCII do wydruku
  • Wbudowane, które jawnie wykonują to zadanie, są dozwolone

Przypadki testowe:

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

Zwróć uwagę na końcowe miejsce w ostatnim przypadku testowym

To jest gra w , więc udziel odpowiedzi tak krótko, jak to możliwe!

Nathan Merrill
źródło
Powiązane
nimi
Czy możesz dodać przykład z nie alfabetycznymi, drukowalnymi znakami ASCII dla potomności?
Conor O'Brien
Więcej przykładów ze znakami niealfabetycznymi nie mogło zaszkodzić. Właśnie usunąłem swoją odpowiedź, ponieważ zdałem sobie sprawę, że zepsuła się ona z danymi wejściowymi zawierającymi \​lub '.
Dennis,
Nie wiesz, jak reprezentować 'w przykładzie. Jeśli używam "ciągów, to ciągi różnią się od innych przykładów.
Nathan Merrill,
To jest dokładnie problem mojej odpowiedzi. : P
Dennis,

Odpowiedzi:

10

JavaScript (ES6), 75 bajtów

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

Objaśnienie: Filtruje we wszystkich pasujących prefiksach, a następnie łączy się z nowymi liniami i dopasowuje do wyrażenia regularnego, który znajduje najdłuższy wspólny prefiks ze wszystkich linii. Jeśli nie ma prefiksów, wyrażenie regularne zwraca pusty ciąg, w którym to przypadku po prostu zwracamy oryginalny ciąg.

Neil
źródło
Można wymienić e.startsWith(s)z e.match("^"+s)na bajt off currying zapisze kolejną
Shaun H
@ShaunH Nie mogę używać matchz dowolnymi drukowanymi kodami ASCII.
Neil
No dobrze, wyrażenia regularne i kontrolne. można jeszcze curry (s,a)=>dos=>a=>
Shaun H
7

Galaretka , 14 12 bajtów

ḣJ$€ċÐff\ṪṪȯ

Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .

Jak to działa

ḣ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.
Dennis
źródło
6

Pyth, 14 13 bajtów

Dzięki @isaacg za -1 bajt

.xe@F/#z._MQz

Program, który pobiera listę ciągów, a następnie ciąg znaków na STDIN i drukuje wynik.

Sprawdź wszystkie przypadki testowe

Jak to działa

.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
TheBikingViking
źródło
1
f}zT=>/#z
isaacg
5

PowerShell v3 +, 112 bajtów

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

Pobiera dane wejściowe jako ciąg $ai tablicę ciągów $b. Używa -likeoperatora do wyciągnięcia z tego tych elementów $b(bez rozróżniania wielkości liter) $a, jawnie rzutuje je jako tablicę @(...)(ponieważ wynikiem może być jedno dopasowanie jako skalar, w którym to przypadku indeksowanie później się nie powiedzie) i zapisuje tę tablicę w $c.

To tworzy ifklauzulę. Jeśli nic nie ma $c(tzn. Nic nie zaczyna się $a, więc tablica jest pusta), następnie wypisuje $aza pomocą else. Inaczej ...

Rzucamy pierwszy element $cjako- chartablicę i pętlę przez każdy element, łącząc łańcuch z poprzednim $ii umieszczając łańcuchy na rurociągu za pomocą enkapsulujących parens. Ci są filtrowane przez |?{...}(w Where-Objectpunkcie), aby sprawdzić, czy .countz $cjest -eqseksualnego do .countrzeczy, w $cktóre są -likepodciąg (tj podciąg dopasowuje wszystko w $ c). Ponieważ budujemy nasze podciągi w kolejności od najkrótszej do najdłuższej, potrzebujemy ostatniego [-1]z powstałych ciągów.

Przypadki testowe

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
AdmBorkBork
źródło
4

Python 2, 122 bajty

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

Pełny program; pobiera ciąg i listę ze standardowego wejścia dokładnie tak, jak podano w przykładach, z tym wyjątkiem, że dane wejściowe muszą znajdować się w osobnych wierszach.

Sprawdź wszystkie przypadki testowe

DLosc
źródło
Dlaczego l.pop()zamiast l[-1]?
Cyoce,
@Cyoce Ponieważ ljest to zwykle setw tym momencie, co nie pozwala na indeksowanie (jest nieuporządkowane). (Na szczęście obsługiwane są zarówno zestawy, jak i listy pop().)
DLosc 24.09.16
3

Perl, 54 bajty

Obejmuje +2 za -Xp(można łączyć z -e) i +3 za -i(nie można łączyć)

Podaj słownik na STDIN i słowo po -iopcji, np .:

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

Tylko kod:

/^\Q$^I\E.*?(?{$F[$a{$&}++]=$&})^/}{$_=pop@F||$^I
Ton Hospel
źródło
3

Perl, 61 bajtów

Obejmuje +2 za -0p

Uruchom z pierwszym słowem, a następnie słowami ze słownika na STDIN:

tabcompletion.pl
a
apply
apple
apple pie
eat
^D

tabcompletion.pl:

#!/usr/bin/perl -0p
/^(.+)
((?!\1).*
)*(\1.*).*
((?!\1).*
|\3.*
)*$|
/;$_=$3||$`
Ton Hospel
źródło
2

Python 2, 112 bajtów

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]
Lynn
źródło
2

Haskell, 67 bajtów

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

Funkcja pomocnicza ?znajduje najdłuższy wspólny przedrostek dwóch łańcuchów, rekurencyjnie biorąc pierwszy znak, o ile jest taki sam dla obu łańcuchów, a łańcuchy nie są puste.

Główna funkcja %najpierw zachowuje na liście tylko łańcuchy zaczynające się od podanej s, sprawdzane przez najdłuższy wspólny przedrostek z sistnieniem s. Aby poradzić sobie z brakiem ważnych konkursów, dodaje sdo pustego wyniku za pośrednictwem max. Następnie znajduje najdłuższy wspólny przedrostek, składając funkcję binarną ?.

xnor
źródło
2

Python 2, 75 bajtów

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

Dzięki @xnor za sugestię wbudowanego, pierwotnie używanego przez @BetaDecay w tej odpowiedzi .

Do celów punktacji ÿmożna zastąpić bajtem DEL. Przetestuj na Ideone .

Dennis
źródło
1

D, 88 bajtów

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

Stosowanie:

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

Kod po prostu usuwa wszystkie elementy, od qktórych się nie zaczyna p, a następnie oblicza największą wspólną podsekwencję początkową pozostałych elementów.

Parametry szablonów oszczędzają nam dwa powtórzenia stringi jedno z nich auto. Niewłaściwe użycie wyjątku pozwala nam uniknąć zmiennej tymczasowej i warunkowej, które w innym przypadku byłyby konieczne, aby obsłużyć przypadek, w którym brak elementów na qpoczątku p.

Promień
źródło
1

Python 2, 107 102 bajtów

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

Do celów punktacji ÿmożna zastąpić bajtem DEL. Przetestuj na Ideone .

Dzięki @xnor za uratowanie 5 bajtów!

Dennis
źródło
Dzięki os.path.commonprefix znalezieniu wersji Beta Decay możesz ją wykonać za Ciebie.
xnor
Wow, to oszczędza dużo bajtów. Czy na pewno nie chcesz tego opublikować?
Dennis
Sam nie opublikowałbym tego, ponieważ jest to wyłącznie pomysł Beta Decay w połączeniu z twoją odpowiedzią.
xnor
W przypadku twojego rozwiązania iteracja wydaje się nieco krótsza for c in ...i kończy się błędem po wydrukowaniu if len(set(c))>1:print r or s;_.
xnor
Myślę, że to by się nie powiodło, gdyby x był tablicą singletonów.
Dennis,
1

PHP, 167 160 157 152 bajtów

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

Mógłbym zapisać jeszcze 3 bajty, przypisując zmienne przy pomocy preg_grepi preg_quote, ale eh.

awaria

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;
Tytus
źródło
1

PHP, 156 bajtów

z wielką pomocą od Tytusa Dziękujemy

<?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 bajtów

32 bajty zapisywane przez Tytusa z 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;

Wiem, że rozwiązanie Regex firmy Titus było krótsze, dopóki Tytus nie pomógł mi ulepszyć mojej drogi. Może to, co znalazłem, jest dla ciebie interesujące

Jörg Hülsermann
źródło
1
1) Wymień $zsię $snaprawić apple, [eat,dine]sprawę. 2) $l=jest przestarzały; Nie używasz tej zmiennej. (-2) 3) $i++<$mjest krótszy niż ++$i<=$m. (-1) 4) substr($x,0,$i);jest krótszy niż str_split($x,$i)[0]. (-3) 5) Możesz włożyć $r[]=$vstrlen. (-5)
Tytus
1
6) <2jest krótszy niż ==1. (1) 7), można użyć strstrw pierwszej pętli: strstr($v,$s)==$v. (-3)
Tytus
1
Pozwól mi przeformułować go: 5) Można łączyć $r[]=$v;$m=max($m,strlen($v));się $m=max($m,strlen($r[]=$v));i upuść curlys. To nie wpływa na warunek.
Tytus
1
Po namyśle, $mwcale nie potrzebujesz . Wszystko czego potrzebujesz to> minimalna długość zamienników. Nowy 5) Wymień {$r[]=$v;$m=max($m,strlen($v));}się $r[]=$v;}i <$mz <strlen($r[0])(-13)
Titus
1
Świetny! I właśnie znalazłem innego golfa: 9) $r[]=$z=$v;w pierwszej pętli, a {$s=substr($z,0,$i);foreach($r as$x)if($x[$i]!=$z[$i])break 2;}dla drugiej (-3)
Titus
1

Siatkówka, 60 bajtów

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

Końcowa nowa linia jest znacząca. Pobiera dane wejściowe jako ciąg znaków w wierszu, a następnie każde słowo w osobnym wierszu (ale bez końcowego nowego wiersza!). Działa w sposób podobny do mojej odpowiedzi JavaScript, dopasowując najdłuższy wspólny przedrostek wszystkich linii rozpoczynających się od ciągu w pierwszym wierszu. Jeśli go nie znajdzie, to po prostu usuwa wszystkie słowa.

Neil
źródło
0

Scala, 119 bajtów

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

Nie golfowany:

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

Wyjaśnienie:

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
corvus_192
źródło
0

05AB1E , 14 bajtów

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

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

ʒ   }           # 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"
Kevin Cruijssen
źródło
0

Gaia , 12 bajtów

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

Wypróbuj online!

Pobiera dane jako B, a następnie 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
Giuseppe
źródło