实施制表符完成


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字符的示例?
Conor O'Brien

使用非字母字符的更多示例不会受到伤害。我刚刚删除了答案,因为我意识到答案被包含\​或的输入弄乱了'
丹尼斯

不确定如何'在示例中表示。如果我使用"这些字符串,则这些字符串与其他示例不同。
内森·美林

正是我的答案所遇到的问题。:P
丹尼斯

Answers:


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字节

感谢@isaacg为-1个字节

.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,所以数组是空的),然后输出$aelse。除此以外 ...

我们将第一个元素转换$cchar-array,并循环遍历每个元素,与前一个元素进行字符串连接,$i然后通过封装括号将字符串放置在管道中。这些都是通过过滤|?{...}(该Where-Object条款),以验证该.count$c-eqUAL到.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()

完整程序;完全按照示例中的说明从stdin中获取字符串和列表,只是输入必须位于单独的行上。

验证所有测试用例


为什么要l.pop()代替l[-1]
Cyoce

@Cyoce因为l通常set在该点是a ,所以不允许索引(无序)。(幸运的是,集合和列表都支持pop()。)
DLosc

3

Perl,54个字节

包括+2 -Xp(可以与结合-e)和+3 -i(不能与)结合

在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]

辅助函数?通过递归地采用第一个字符来查找两个字符串的最长公共前缀,只要两个字符串相同且字符串为非空即可。

主要功能%首先仅保持在给定一个启动列表中的字符串s,由最长的公共前缀与检查ss。要处理没有有效的比赛,它会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

感谢@xnor建议内置,最初由@BetaDecay在此答案中使用

出于计分目的,ÿ可以用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和之一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上进行测试

感谢@xnor节省了5个字节!


随着os.path.commonprefix Beta Decay的发现,您可以让它为您完成工作。
xnor

哇,节省了很多字节。您确定不想自己张贴吗?
丹尼斯

我自己发布该消息并不正确,因为它完全是Beta Decay的想法和您的回答。
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_grep和分配变量来节省3个字节preg_quote,但是eh。

分解

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字节

Titus用array_unique保存了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解决方案要短一些,直到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)
Titus

1
让我重组你的问题:5)你可以结合$r[]=$v;$m=max($m,strlen($v));$m=max($m,strlen($r[]=$v));并删除curlys。这不符合条件。
泰特斯(Titus)

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;}中,第二个循环(-3)
Titus

1

视网膜,60字节

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

尾随的新线很重要。将输入作为一行上的字符串,然后将每个单词放在单独的一行上(但不包含结尾的换行符!)。通过匹配以第一行的字符串开头的所有行的最长公共前缀,以与我的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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.