알파 베 만들기


31

알파벳순으로 정렬 된 다음 단어 목록을 고려하십시오.

balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom

모든 단어는로 시작 b하고 처음 5는로 시작합니다 bal. 처음 두 단어 만 보면 :

balderdash
ballet

우리는 대신 쓸 수 있습니다 :

balderdash
  +let

여기서 ' '단어는 이전 단어와 접두사 문자를 공유하는 데 사용됩니다. '+'두 번째 단어가 이전 단어와 접두사를 공유하는 마지막 문자를 나타내는 문자는 제외합니다 .

이것은의 일종이다 '트라이' 부모 '입니다 : 시각화 bal', 2 자손을 가지고 'derdash''let'.

다음과 같은 더 긴 목록으로 :

balderdash
ballet
brooding

또한 파이프 문자 '|'를 사용하여 다음과 같이 공유 접두사가 끝나는 위치를 더 명확하게 만들 수 있습니다.

balderdash
| +let
+rooding

그리고 해당 트리의 루트 것 'b'두 아이 갖는 서브 트리 가진 루트 'al'와와 두 자녀 'derdash''let'; 그리고 'rooding'.

이 전략을 원래 목록에 적용하면

balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom

우리는 다음과 같은 출력을 얻습니다.

balderdash    
| +let     
|  +oonfish
|   | +ist 
|   +t     
+rooding   
   +m 

목록에서 두 개의 연속 단어에 공유 접두사가 없으면 특수 문자로 대체되지 않습니다. 예를 들어 목록의 경우 :

broom
brood
crude
crumb

우리는 출력을 원합니다 :

broom
   +d
crude
  +mb

입력

입력 된 단어는 영숫자 (공백 또는 구두점 없음)로만 구성됩니다. 선택한 형식을 지정하는 한 문자열 목록, 단일 문자열 또는 기타 합리적인 방법의 형태 일 수 있습니다. 두 개의 연속 단어는 동일하지 않습니다. 알파벳순으로 목록이 정렬됩니다.

산출

출력은 줄당 또는 총계의 공백을 포함 할 수 있지만 선행 공백은 포함 할 수 없습니다. 문자열 또는 이와 유사한 목록도 허용됩니다.

이것은 . 각 언어에서 가장 짧은 코드는 자랑 할 권리가 있습니다. 허점에 대한 일반적인 금지 사항이 적용됩니다.

테스트 사례

Input:
apogee
apology
app
apple
applique
apply
apt

Output:
apogee     
 |+logy    
 +p        
 |+le      
 | +ique   
 | +y      
 +t        

Input:
balderdash
ballet
balloonfish
balloonist
ballot
brooding
broom
donald
donatella
donna
dont
dumb

Output:
balderdash 
| +let     
|  +oonfish
|   | +ist 
|   +t     
+rooding   
   +m      
donald     
| |+tella  
| +na      
| +t       
+umb 

내가 ball이후 에 단어를 가지고있는 경우는 어떻습니까 balloon. 우리는 어떤 결과를 기대해야합니까?
Don Thousand

@RushabhMehta 나는 당신이 +첫 번째 아래에 있을 것이라고 추측 o하고 있지만, 나는 도전을 쓰지 않았으므로 확실하지 않습니다.
Theo

5
@RushabhMehta 알파벳 순서로 단어가 정렬되므로 이러한 일이 발생하지 않습니다.
Neil

@Neil Oh 좋은 지적
Don Thousand

2
입력의 단어는 영숫자만으로 구성됩니다 . 실제로 숫자를 포함합니까, 아니면 알파벳을 의미합니까?
Arnauld

답변:


11

레티 나 0.8.2 , 58 57 바이트

^((.*).)(?<=\b\1.*¶\1)
$.2$* +
m)+`^(.*) (.*¶\1[+|])
$1|$2

온라인으로 사용해보십시오! 링크에는 하나의 테스트 사례가 포함됩니다. 편집 : @FryAmTheEggman 덕분에 1 바이트를 절약 \b하여 ^에서 가능한 스위치를 간과했다고 지적했습니다 m). 설명:

m)

^전체 프로그램에 대해 라인별로 설정 하십시오.

^((.*).)(?<=^\1.*¶\1)
$.2$* +

각 단어마다 이전 단어의 시작 부분부터 가능한 한 많이 일치 시키십시오. 마지막 문자를 제외하고 공백으로 일치를 변경하십시오 +.

+`^(.*) (.*¶\1[+|])
$1|$2

+s 또는 |s 바로 위 의 모든 공백을 s로 반복해서 바꿉니다 |.


@FryAmTheEggman 실제로, 나는 그것을 m)할 수 있도록 구체적으로 추가 했으므로 인스턴스를 놓친 것에 대해 짜증이납니다.
Neil

어째서 사람들이 댓글을 삭제하려고한다면 댓글에 답장을하는 것을 왜 귀찮게합니까?
Neil

9

JavaScript (ES6), 128 바이트

문자 목록 목록을 예상하고 반환합니다.

a=>a.map((w,y)=>a[~y]=w.map(m=(c,x)=>(p=a[y-1]||0,m|=c!=p[x])?c:p[x+1]==w[x+1]?' ':(g=y=>a[y][x]<1?g(y+1,a[y][x]='|'):'+')(-y)))

온라인으로 사용해보십시오!

방법?

공간과 +의 순서에서 마지막 단어에 대한 첫 번째 통해 도보로 삽입 할 수 있지만 |'들에만 삽입 할 수있는 사후 A가 한 번 +확인되었습니다. 이것은 두 개의 고유 한 패스를 수행함으로써 달성 될 수 있지만, 대신 a[~y]에 동일한 map()루프 내에서 다시 업데이트 될 수 있도록 수정 된 각 항목에 대한 포인터를 저장합니다 .

이론적으로, 더 간단한 해결 방법은 단어를 역순으로 진행하고 프로세스가 끝날 때 출력을 반전시키는 것입니다. 그러나 이것은 JS에서 약간 비용이 많이 들며이 방법으로 더 짧은 버전을 얻는 방법을 찾지 못했습니다.

a =>                           // a[] = input array
  a.map((w, y) =>              // for each word w at position y in a[]:
    a[~y] =                    //   save a pointer to the current entry in a[~y]
    w.map(m =                  //   initialize m to a non-numeric value
      (c, x) => (              //   for each character c at position x in w:
        p = a[y - 1] || 0,     //     p = previous word or a dummy object
        m |= c != p[x]         //     set m = 1 as soon as w differs from p at this position
      ) ?                      //     if w is no longer equal to p:
        c                      //       append c
      :                        //     else:
        p[x + 1] == w[x + 1] ? //       if the next characters are still matching:
          ' '                  //         append a space
        : (                    //       else:
            g = y =>           //         g() = recursive function to insert pipes
            a[y][x] < 1 ?      //           if a[y][x] is a space:
              g(               //             do a recursive call to g()
                y + 1,         //               with y + 1
                a[y][x] = '|'  //               and overwrite a[y][x] with a pipe
              )                //             end of recursive call
            :                  //           else:
              '+'              //             make the whole recursion chain return a '+'
                               //             which will be appended in the current entry
          )(-y)                //         initial call to g() with -y (this is ~y + 1)
    )                          //   end of map() over the characters
  )                            // end of map() over the words

내 솔루션을 보시겠습니까? 나는 스스로 생각해 냈지만 솔루션을 생각 나게합니다. 너무 가까이 있다면 당신의 것으로 제출하거나 지울 수 있습니다 :)
DanielIndie

@DanielIndie 걱정하지 마십시오. 충분히 다릅니다.
Arnauld


1

파이썬, 263260 바이트

- 3 조나단 FRECH 덕분 바이트

암호:

p=lambda t,f,g:"\n".join([(f[:-1]+"+"if(a!=min(t))*g else"")+a+p(t[a],(f+" "if len(t[a])>1or a==max(t)else f[:-1]+"| "),1)for a in t])if t else""
def a(t,x):
 if x:c=x[0];t[c]=c in t and t[c]or{};a(t[c],x[1:])
def f(*s):t={};[a(t,i)for i in s];return p(t,"",0)

온라인으로 사용해보십시오!

설명:

이 솔루션은 입력 단어를 사용하여 trie를 작성하고 필요한 출력으로 재귀 적으로 구문 분석합니다. a 함수는 trie t와 string s를 취하여 x를 t에 더합니다. 시도는 중첩 된 사전으로 구현됩니다. 각 사전은 트리의 노드를 나타냅니다. 예를 들어 첫 번째 테스트 사례에서 생성 된 트리를 나타내는 사전은 다음과 같습니다.

{'b': {'a': {'l': {'d': {'e': {'r': {'d': {'a': {'s': {'h': {}}}}}}}, 'l': {'e': {'t': {}}, 'o': {'o': {'n': {'f': {'i': {'s': {'h': {}}}}, 'i': {'s': {'t': {}}}}}, 't': {}}}}}, 'r': {'o': {'o': {'d': {'i': {'n': {'g': {}}}}, 'm': {}}}}}}

p 함수는이 구조를 통해 반복되며 챌린지에 의해 예상되는 트라이의 문자열 표현을 생성합니다. f 함수는 많은 문자열을 인수로 취하여 a를 사용하여 trie에 모두 추가 한 다음 tri에서 p를 호출 한 결과를 반환합니다.



1

C (gcc) , 165155 바이트

세 가지 인수를 취합니다.

  • char** a : null로 끝나는 단어의 배열
  • char* m : 각 단어의 길이의 배열
  • int n : 배열의 단어 수
f(a,m,n,i,j)char**a,*m;{for(i=n;--i;)for(j=0;j<m[i]&j<m[i-1]&a[i][j]==a[i-1][j];j++)a[i][j]=a[i][j+1]^a[i-1][j+1]?43:++i<n&j<m[i]&a[i--][j]%81==43?124:32;}

온라인으로 사용해보십시오!



@Arnauld 물론입니다! ++i<n&j<m[i]&a[i--]정의 되지 않은 동작 은 아니지만 ? 왼쪽에서 오른쪽으로 평가할 때 gcc를 사용할 수 있습니까?
커티스 베텔

정의되지 않은 동작 일 가능성이 큽니다. 그러나 우리는 구현에 따라 언어를 정의 하므로이 버전의 gcc와 일관되게 작동하는 한 괜찮습니다.
Arnauld

1

Perl 6 , 149144142 바이트

{1 while s/(\n.*)\s(.*)$0(\+|\|)/$0|$1$0$2/;$_}o{$=({.[1].subst(/^(.+)<?{.[0].index($0)eq 0}>/,{' 'x$0.ords-1~'+'})}for '',|$_ Z$_).join("
")}

온라인으로 사용해보십시오!

나는 이것이 정규식에 대한 전문가가 아니기 때문에 이것이 더 골프화 될 수 있다고 확신합니다. 이것은 Neil 's Retina answer 와 거의 동일한 프로세스를 사용합니다 .



0

루비 , 118 바이트

->a{i=1;a.map{s="";a[i+=j=-1].chars{|c|a[i][j+=1]=i<0&&a[i-1][/^#{s+=c}/]?a[i+1][j]=~/[|+]/??|:?\s:c}[/[| ]\b/]&&=?+}}

온라인으로 사용해보십시오!

원래 입력 배열을 내부에서 수정하여 문자열 배열, 출력을 허용합니다.

설명

기본 문자열 변환은 너무 복잡하지는 않지만 수직 파이프를 올바르게 삽입하려면 역순으로 반복해야하며 reverse방법이 매우 장황하므로 더 까다로운 방식으로 수행합니다. 여기서는 map루프를 실행하고 첫 번째 단어 만 남겨두고 음수 인덱스를 사용하여 끝에서 반복합니다.

->a{
 i=1;                   #Initialize word indexer
 a.map{                 #Loop
  s="";                 #Initialize lookup string
  a[i+=j=-1]            #Initialize char indexer and decrement i
  .chars{|c|            #Loop through each char c of current word
   a[i][j+=1]=          #Mofify current word at position j 
    i<0&&               #If it's not the first word and
    a[i-1][/^#{s+=c}/]? #Word above matches current one from start to j
     a[i+1][j]=~/[|+]/? #Then if char below is | or +
      ?|:?\s:c          #Then set current char to | Else to Space Else leave as is
  }[/[| ]\b/]&&=?+      #Finally, replace Space or | at word boundary with +
 }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.