タブ補完を実装する


31

タブ補完は、部分的に記述されたコマンドを自動補完する便利な機能です。あなたはそれを実装するつもりです。

使用可能なコマンドがあった場合たとえば、['apply','apple','apple pie','eat']、その後aに完成う applで始まるすべてのコマンドとして、aまたで始まりますappl

入出力

文字列Aと一連の文字列Bを入力する必要があります。

Aで始まるすべてのBの最長共通プレフィックスを出力する必要があります。

  • Aで始まるオプションがない場合は、Aを返します
  • Bは空ではなく、すべての文字列は空ではないと仮定できます。
  • オプションのいずれかがAで始まると仮定したり、共通のプレフィックスがAより長いと仮定したりすることはできません。
  • 大文字と小文字を区別する場合と区別しない場合があります。
  • あなただけの印刷可能なASCIIを処理する必要があります
  • このタスクを明示的に行うビルトインは許可されます

テストケース:

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

最後のテストケースの末尾のスペースに注意してください

これはですので、できるだけ短く答えてください!



後世のために、アルファベット以外の印刷可能なASCII文字を使用した例を追加できますか?
コナーオブライエン

アルファベット以外の文字を使用した他の例では、問題はありません。\​またはを含む入力で壊れていることに気付いたので、答えを削除しました'
デニス

'例で表現する方法がわからない。"文字列に使用する場合、文字列は他の例とは異なります。
ネイサンメリル

それがまさに私の答えが抱えていた問題です。:P
デニス

回答:


10

JavaScript(ES6)、75バイト

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

説明:一致するすべてのプレフィックスをフィルター処理してから、改行で結合し、すべての行の最も長い共通プレフィックスを見つける正規表現と照合します。プレフィックスがない場合、正規表現は空の文字列を返します。この場合、元の文字列を返します。


あなたは置き換えることができますe.startsWith(s)e.match("^"+s)カリー化オフバイトが別救うために
ショーン・H

@ShaunH match任意の印刷可能なASCII では使用できません。
ニール

ああ、正しい正規表現と制御文字。あなたはまだカレー(s,a)=>することができます s=>a=>
ショーンH

7

ゼリー14 12 バイト

ḣJ$€ċÐff\ṪṪȯ

オンラインでお試しください!または、すべてのテストケースを確認します

使い方

ḣ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バイト

-1バイトの@isaacgに感謝

.xe@F/#z._MQz

STDINで文字列のリストを取得し、次に文字列を取得して結果を出力するプログラム。

すべてのテストケースを検証する

使い方

.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バイト

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

入力を文字列$aおよび文字列の配列として受け取ります$b-like演算子を使用して、$b(大文字と小文字を区別しない)で始まる要素からそれらの要素を引き出し$a、明示的に配列としてキャストし@(...)(結果がスカラーとして一致する可能性があるため、後でインデックス付けが失敗するため)、その配列をに格納し$cます。

それがif句を形成します。に何もない場合$c(つまり、で始まるものがない$aため、配列は空です)、で出力$aしますelse。さもないと ...

の最初の要素を-array $cとしてキャストし、char各要素をループし、前の要素と文字列を連結し、$i括弧をカプセル化することで文字列をパイプラインに配置します。これらを介して濾過されている|?{...}Where-Objectことを確認するために、句).countのが$cある-eqにUAL .countで物事の$cあるもの-like(すなわち、部分文字列は$ Cのすべてを一致する)ストリング。部分文字列を最短から最長の順に構築しているため[-1]、結果の文字列の最後が必要です。

テストケース

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バイト

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

完全なプログラム。入力が別々の行になければならないことを除いて、例で与えられた通りに、標準入力から文字列とリストを取ります。

すべてのテストケースを検証する


なぜl.pop()代わりにl[-1]
チョイス

@Cyoce lは通常、setその時点でであり、インデックス付けを許可しません(順序付けされていません)。(幸いなことに、セットとリストの両方がサポートしていpop()ます。)
DLosc

3

Perl、54バイト

-Xp(+ と組み合わせることができる)+2 -eおよび-i(組み合わせることができない)+3を含む

STDINの辞書と-iオプションの後の単語を指定します。例:

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

コードだけ:

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

3

Perl、61バイト

+2を含む -0p

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バイト

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バイト

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

補助関数?は、両方の文字列で同じであり、文字列が空でない限り、最初の文字を再帰的に取得して、2つの文字列の最長共通プレフィックスを検索します。

主な機能は、%最初の1つの所与で始まる、リスト内の文字列のみ保持sして最長の共通のプレフィックスによって確認された、sことをs。有効な競合がないことを処理するsために、を介して空の結果に追加しmaxます。次に、バイナリ関数を畳むことにより、それらの最長共通プレフィックスを見つけます?


2

Python 2、75バイト

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

この回答で元々@BetaDecayによって使用されていたビルトインを提案してくれた@xnorに感謝します

スコアリングの目的ÿで、DELバイトに置き換えることができます。Ideoneでテストします。


1

D、88バイト

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

使用法:

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

コードqは、で始まらないすべての要素を単純に削除しp、残りの要素の最大の共通初期サブシーケンスを計算します。

テンプレート化されたパラメーターはstring、の2回の繰り返しと1 回の繰り返しを保存しますauto。例外の誤用により、でq始まる要素がない場合の処理​​に必要な一時変数と条件変数を回避できますp


1

Python 2、107 102バイト

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

スコアリングの目的ÿで、DELバイトに置き換えることができます。Ideoneでテストします。

5バイトを節約してくれた@xnorに感謝します!


os.path.commonprefix ベータ崩壊が見られるように、あなたはそれがあなたのための作業を行うことができます。
xnor

うわー、それは多くのバイトを節約ます。自分で投稿したくないのですか?
デニス

それはベータ崩壊のアイデアとあなたの答えが組み合わされているだけなので、私はそれを自分で投稿するのは正しいとは思わないでしょう。
xnor

ソリューションでは、のfor c in ...ように印刷した後、直接反復してエラーで終了する方が少し短く見えますif len(set(c))>1:print r or s;_
xnor

xがシングルトン配列の場合、それは失敗すると思います。
デニス

1

PHP、167の 160 157 152バイト

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

preg_grepand preg_quoteで変数を割り当てることで、さらに3バイト節約できますが、ええ。

壊す

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バイト

Titusありがとうございます

<?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バイト

array_uniqueを使用したTitusによる32バイトの節約

<?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によるRegex Solutionは、Titusが私の方法を改善するのを手伝うまでは短いことを知っています。たぶん私が見つけた方法はあなたにとって面白いです


1
1)と置き換え$zてケース$sを修正しapple, [eat,dine]ます。2)$l=廃止された; その変数は使用しません。(-2)3)$i++<$mはより短い++$i<=$m。(-1)4)substr($x,0,$i);はより短いstr_split($x,$i)[0]。(-3)5)$r[]=$vstrlenの中に入れることができます。(-5)
タイタス

1
6)<2はより短い==1。(-1)7)strstr最初のループで使用できます:strstr($v,$s)==$v。(-3)
タイタス

1
言い換えてみましょう:5)カーリーに結合$r[]=$v;$m=max($m,strlen($v));$m=max($m,strlen($r[]=$v));てドロップできます。これは状態に影響しません。
タイタス

1
考え直して$m、まったく必要ありません。必要なのは、置換の最小長> =であるものです。新しい5)を交換{$r[]=$v;$m=max($m,strlen($v));}して$r[]=$v;}<$mして<strlen($r[0]))-13(
タイタス

1
すばらしいです!そして、私はちょうど別のゴルフを見つけました:9)$r[]=$z=$v;最初のループで{$s=substr($z,0,$i);foreach($r as$x)if($x[$i]!=$z[$i])break 2;}2番目(-3)
タイタス

1

網膜、60バイト

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

末尾の改行は重要です。入力を1行の文字列として、次に各単語を別々の行に入力します(ただし、末尾の改行はありません!)。最初の行の文字列で始まるすべての行の最長共通プレフィックスを照合することにより、JavaScriptの回答と同様に機能します。見つからない場合は、すべての単語が削除されます。


0

Scala、119バイト

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

ゴルフをしていない:

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

説明:

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バイト

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

オンラインで試すたり、すべてのテストケースを確認してください

説明:

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

ガイア、12バイト

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

オンラインでお試しください!

入力をB、次に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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.