制作字母


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'具有两个子树的根:具有root '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,但是我没有写挑战,所以我不确定。
西奥,

5
@RushabhMehta单词按字母顺序排序,因此不会发生。
尼尔

@Neil好点子
Don Thousand

2
输入中的单词将仅由字母数字组成:这是否真的包括数字,还是您指的是字母?
阿诺尔德

Answers:


11

视网膜0.8.258个 57字节

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

在线尝试!链接包括一个测试用例。编辑:保存1个字节感谢@FryAmTheEggman指出,我忽略了从交换机\b^被成为可能m)。说明:

m)

^为整个程序打开每行。

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

对于每个单词,请尝试从上一个单词的开头尽可能匹配。将匹配项更改为空格(最后一个字符除外,该字符变为)+

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

重复替换紧邻上方的所有空格 + s或|s的为|s。


@FryAmTheEggman确实,我添加了m)专门用于执行此操作的功能,因此我很生气错过了一个实例。
尼尔,

gh,如果人们只是要删除评论,我为什么还要打扰他们……
尼尔,

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

在线尝试!

怎么样?

空间和+的可以步行通过第一个到最后一个字的顺序插入,但|'s只能插入事后一旦+已被确定。这可以通过执行两次不同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

Python,263260字节

- 3字节感谢乔纳森弗雷希

码:

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)

在线尝试!

说明:

该解决方案从输入单词中构造一个特里树,然后将其递归地解析为所需的输出。函数a取一个t和一个字符串s,并将x加到t上。尝试被实现为嵌套字典。每个字典代表该Trie中的一个节点。例如,表示第一个测试用例生成的特里字典的字典如下所示:

{'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函数通过此结构递归,并生成质询所期望的trie的字符串表示形式。f函数使用一串字符串作为参数,将它们全部添加到带有a的trie中,然后返回在trie上调用p的结果。



1

C(gcc)165155字节

接受三个参数:

  • char** a :以零结尾的单词的数组
  • 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从左到右对其进行评估吗?
Curtis Bechtel

这很可能是未定义的行为。但是我们通过语言的实现来定义语言,因此只要它与该版本的gcc一致,我认为就可以了。
Arnauld

1

Perl 6的149个144 142字节

{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("
")}

在线尝试!

我确信这可以打得更多,特别是因为我不是正则表达式专家。这使用了与尼尔的视网膜答案相同的过程。


0

Python 2 191字节

def f(w,r=['']):
 for b,c in zip(w[1:],w)[::-1]:
	s='';d=0
	for x,y,z in zip(r[0]+b,b,c+b):t=s[-1:];s=s[:-1]+[['+'*(s>'')+y,t+' |'[x in'+|']][y==z],t+y][d];d=d|(y!=z)
	r=[s]+r
 return[w[0]]+r

在线尝试!


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 +
 }
}
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.