탭 완성 구현


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

알파벳이 아닌 문자를 사용한 더 많은 예제는 아프지 않았습니다. 나는 그것이 입력이 포함 깨고 것을 깨달았 때문에 난 그냥 내 대답을 삭제 \​하거나 '.
Dennis

'예제에서 표현하는 방법을 잘 모르겠습니다 . "문자열에 사용 하면 문자열이 다른 예제와 다릅니다.
Nathan Merrill

그건 바로 내 대답했던 문제. : P
Dennis

답변:


10

자바 스크립트 (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와 함께 사용할 수 없습니다 .
Neil

오, 정규 표현식과 제어 문자. 당신은 여전히 카레 수 (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받는 연간 .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

파이썬 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그 시점에 있기 때문에 인덱싱을 허용하지 않습니다 (정렬되지 않음). (다행히 두 세트 및 목록 지원 pop().)
DLosc

3

펄, 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

펄, 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

파이썬 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

하스켈, 67 바이트

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

보조 함수 ?는 두 문자열이 동일하고 문자열이 비어 있지 않은 한 첫 번째 문자를 재귀 적으로 가져 와서 두 문자열의 가장 긴 공통 접두사를 찾습니다.

주요 기능은 %먼저 하나의 주어로 시작하는 목록 만 문자열 유지 s에 가장 긴 일반적인 접두사에 의해 확인, s존재를 s. 유효한 경쟁이없는 것을 처리하기 위해 s를 통해 빈 결과에 추가 합니다 max. 그런 다음 이진 함수를 접음으로써 가장 긴 접두사를 찾습니다 ?.


2

파이썬 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과 하나의 반복을 저장합니다 auto. 예외 오용은로 q시작하는 요소가없는 경우를 처리하는 데 필요한 임시 변수 및 조건을 피할 수있게합니다 p.


1

파이썬 2, 107102 바이트

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

와우, 그것은 많은 바이트 를 절약 합니다. 직접 게시하고 싶지 않습니까?
Dennis

베타 Decay의 아이디어와 귀하의 답변이 결합되어 있기 때문에 직접 게시하는 것이 좋지 않습니다.
xnor

솔루션의 경우 for c in ...직접 반복 하고 인쇄 후 오류가 발생 하면 약간 짧아 보입니다 if len(set(c))>1:print r or s;_.
xnor

x 가 싱글 톤 배열 이면 실패 할 것이라고 생각합니다 .
Dennis

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_quoteeh를 사용 하여 변수를 할당하여 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 바이트

디도의 많은 도움으로 감사합니다

<?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의 정규식 솔루션이 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));하고 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

스칼라, 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.