爆炸子串


32

介绍

让我们观察一下字符串abc。可以从中创建的子字符串为:

a, ab, abc, b, bc, c

现在,我们需要将它们对齐在初始字符串下,如下所示:

abc
a
 b
  c
ab
 bc
abc

字符串的顺序无关紧要,因此这也是完全有效的:

abc
a
ab
abc
 b
 bc
  c

因此,子字符串位于初始字符串中子字符串位置的下方。因此,对于abcdef和子字符串cde,它看起来像这样:

abcdef
  cde

任务

如上所示,任务是对齐所有长度大于0的子字符串。您可以假设字符串本身仅包含字母字符,并且至少包含1个字符。对于填充,您可以使用空格或其他一些非字母可打印的ASCII字符(32 - 127)。也许不必提,但是字符串本身将仅包含唯一字符,因此不喜欢aba,因为它a发生了两次。

测试用例

输入: abcde

可能的输出:

a
ab
abc
abcd
abcde
 b
 bc
 bcd
 bcde
  c
  cd
  cde
   d
   de
    e

输入: abcdefghij

可能的输出:

a
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
 b
 bc
 bcd
 bcde
 bcdef
 bcdefg
 bcdefgh
 bcdefghi
 bcdefghij
  c
  cd
  cde
  cdef
  cdefg
  cdefgh
  cdefghi
  cdefghij
   d
   de
   def
   defg
   defgh
   defghi
   defghij
    e
    ef
    efg
    efgh
    efghi
    efghij
     f
     fg
     fgh
     fghi
     fghij
      g
      gh
      ghi
      ghij
       h
       hi
       hij
        i
        ij
         j

这是,因此以最少的字节提交为准!


1
空子字符串在哪里?
Leaky Nun

@KennyLau哦,是的,这提醒我编辑一些更多信息来应对挑战。
阿德南

尾随的换行符可以接受吗?
user81655 '16

@ user81655是的,可以接受。
阿德南

字符串数组是否可以接受,还是必须用换行符分隔?
Zgarb

Answers:



21

Perl,32 28 24字节

包括+1的 -n

码:

/.+(??{say$"x"@-".$&})/

在STDIN上运行字符串:

perl -nE '/.+(??{say$"x"@-".$&})/' <<< abcd

高尔夫语言是如此之近,却又相距甚远。

说明

/.+/匹配子字符串。不幸的是,它一旦匹配就停止了。因此,我使用运行时正则表达式构造(??{})来扩展正则表达式,以使其失败,并且回溯将尝试以下子字符串,最后尝试全部尝试,然后厌恶地放弃。

(??{})我在内部打印当前子字符串,前缀为与子字符串偏移量一样多的空格,使用$"x"@-"

因此,输出可整齐地记录正则表达式回溯的工作方式:

abcd
abc
ab
a
 bcd
 bc
 b
  cd
  c
   d

1
肉汁不错,就像雪兰莪一样深奥。+1。
AdmBorkBork '16

4
@TimmyD:出于某些奇怪的原因,有人说打高尔夫球给Perl起了个坏名字……
Ton Hospel

受此启发的Perl 6版本在功能上非常相似perl6 -ne 'm/^(.*)(.+)<{+put " "x$0.to,$1}>/'
Brad Gilbert b2gills

在输入上不起作用ab1(我认为是因为say...计算为1)。(在5.18.2中测试。)编辑:哦!抱歉,问题显示为“您可以假定字符串本身仅包含字母字符”。
msh210 '16

14

MATL20 18字节

受到@aditsu的答案生成的子字符串模式的启发

tt!+gR*c`t3Lt3$)tn

在线尝试!

子字符串的模式由与输入大小相同的上三角矩阵生成,并且所有子矩阵都是通过依次删除最后一行和最后一列而获得的。

说明

t         % implicit input. Duplicate
t!+g      % square matrix with size as input
R         % keep upper triangular part
*c        % multiply element-wise with broadcast. Convert to char
`         % do...while
  t       %   duplicate
  3Lt3$)  %   remove last row and column
  tn      %   number of remaining elements. Used as loop condition
          % implicitly end loop and display

旧方法(笛卡尔势)

我会保留这种方法,以防其他答案得到启发

tn0:2Z^!S!2\Xu4LY)*c

在在线编译器中,这将耗尽最长的测试用例。

在线尝试!

说明

这会生成所有值模式012以升序排列,然后转换20。这给出了所有可能的模式0,并11值是连续的。这些用于标记从原始字符串中提取哪些字符。

例如,对于字符串'abc',模式生成如下。首先获得[0 1 2]提高到输入字符数的笛卡尔幂:

0 0 0
0 0 1
0 0 2
0 1 0
0 1 1
···
2 2 1
2 2 2

排序每行给出

0 0 0
0 0 1
0 0 2
0 0 1
0 1 1
···
1 2 2
2 2 2

转换20(即mod(...,2))并删除重复的行,可以得到最终的模式

0 0 0
0 0 1
0 1 1
0 1 0
1 1 1
1 1 0
1 0 0

其中,每一行都是与(连续)子字符串相对应的掩码。第一行需要删除,因为它对应于空的子字符串。

t      % Implicitly get input. Duplicate
n      % Number of elements
0:2    % Vector [0 1 2]
Z^     % Cartesian power. Each result is a row
!S!    % Sort each row
2\     % Modulo 2: transform 2 into 0
Xu     % Unique rows
4LY)   % Remove first (corresponds to the empty substring)
*      % Element-wise multiplication by original string
c      % Convert to char. Implicitly display

3
您是一台大型矩阵处理机吗?

@cat Matlab使用了很多年,我猜:-)
Luis

14

视网膜48 32 31字节

感谢Kenny Lau节省了3个字节,为更多的内容铺平了道路。

字节数假定为ISO 8859-1编码。

M&!r`.+
%+`( *)\S(.+)$
$&¶$1 $2

在线尝试!

生成的子字符串的顺序:

abcde
 bcde
  cde
   de
    e
abcd
 bcd
  cd
   d
abc
 bc
  c
ab
 b
a

说明

M&!r`.+

这使我们获得了输入的所有前缀。这是通过匹配(M.+从结尾()开始的任何子字符串()r,考虑重叠的匹配(&)并返回所有与换行符(!)相连的匹配来完成的。

现在,我们需要做的就是找出这些前缀的连续前缀(通过用空格替换)。我们通过循环逐步进行此操作:

%+`( *)\S(.+)$
$&¶$1 $2

%意味着将整个过程分别处理到每一行(暂时将其视为一个单独的字符串,然后将其全部与换行符一起重新连接在一起)。将+告诉视网膜运行此替代在一个循环中,直到输出停止变化(在这种情况下,意味着该正则表达式不再匹配)。然后,正则表达式尝试将输入的最后一行与至少两个非空格字符进行匹配,并追加一个新行,在该行中将其中的第一行替换为一个空格。


我们可以有!暗示M和1char版本.+.*
CalculatorFeline

另外,字符串前缀的前缀=字符串的前缀。也许您是指后缀的前缀?(已编辑,以更正。)
CalculatorFeline

@CatsAreFluffy没有正确的解释。当我们从前缀中删除前缀时,我们得到子字符串。至于其他建议,我认为我不会让选择暗示阶段。目前,很多字符仅用于一种舞台类型,将来可能会改变。至于.+.*我必须标记正则表达式,虽然我计划在某个时候这样做,但我认为它不会很快发生(如果这样做,我可能会专注于那些实际上增加了表现力)。
Martin Ender


11

Oracle SQL 11.2,146字节

WITH v AS(SELECT LEVEL i FROM DUAL CONNECT BY LEVEL<=LENGTH(:1))SELECT LPAD(SUBSTR(:1,s.i,l.i),s.i+l.i-1)FROM v s,v l WHERE s.i+l.i<=LENGTH(:1)+1;

未打高尔夫球

WITH v AS(SELECT LEVEL i FROM DUAL CONNECT BY LEVEL<=LENGTH(:1))
SELECT LPAD(SUBSTR(:1,s.i,l.i),s.i+l.i-1)
FROM   v s, v l
WHERE  s.i+l.i<=LENGTH(:1)+1

9

果酱20

q{__,{\_N+oSt}/;W<}h

在线尝试

说明:

q           read the input (initial string)
{…}h        do … while
  _         copy the current string
  _,        copy and get the length
  {…}/      for each value (say i) from 0 to length-1
    \       bring the string to the top
    _N+o    make a copy, append a newline and print
    St      set the i'th element to S=" "
  ;         pop the last result (array full of spaces)
  W<        remove the last character of the current string
             if the string is empty, the do-while loop terminates

8

Python,57个字节

f=lambda s,p='':set(s)and{p+s}|f(s[1:],' '+p)|f(s[:-1],p)

输出一个setlike {' b', 'a', 'ab'}。想法是递归向下切掉第一个或最后一个字符的两个分支。提供冗余输出,但set自动删除重复项。为了对齐,每次切断第一个字符时,都会在前缀上添加一个空格p,并将其连接在前面。


7

PowerShell v2 +,69个字节

param($a)0..($b=$a.length-1)|%{($i=$_)..$b|%{" "*$i+-join$a[$i..$_]}}

接受输入$a,遍历整个长度($b在过程中进行设置以供以后使用)。在每个外部循环中,我们$b再次循环,以$i备后用。在每个内部循环中,我们输出$i与输入字符串的一部分相连的空格数。由于我们只是遍历字符串,因此它实际上将处理任何任意字符串(重复的字母,空格等)。

PS C:\Tools\Scripts\golfing> .\exploded-substrings.ps1 "Golfing"
G
Go
Gol
Golf
Golfi
Golfin
Golfing
 o
 ol
 olf
 olfi
 olfin
 olfing
  l
  lf
  lfi
  lfin
  lfing
   f
   fi
   fin
   fing
    i
    in
    ing
     n
     ng
      g

7

C#,136个 132 131字节


打高尔夫球

String m(String s){String o="",e=o;for(int i=0,a,l=s.Length;i<l;i++,e+=" ")for(a=1;a+i<=l;a++)o+=e+s.Substring(i,a)+"\n";return o;}

不打高尔夫球

String m( String s ) {
    String o = "", e = o;

    for (int i = 0, a, l = s.Length; i < l; i++, e += " ")
        for (a = 1; a + i <= l; a++)
            o += e + s.Substring( i, a ) + "\n";

    return o;
}

完整代码

    using System;
using System.Collections.Generic;

namespace Namespace {
    class Program {
        static void Main( string[] args ) {
            List<String> ls = new List<String>() {
                    "abcde",
                    "abcdefghijklmnop",
                    "0123456789",
                };

            foreach (String s in ls) {
                Console.WriteLine( s );
                Console.WriteLine( m( s ) );
                Console.WriteLine( "" );
            }

            Console.ReadLine();
        }

        static String m( String s ) {
            String o = "", e = o;

            for (int i = 0, a, l = s.Length; i < l; i++, e += " ")
                for (a = 1; a + i <= l; a++)
                    o += e + s.Substring( i, a ) + "\n";

            return o;
        }
    }
}

发布

  • V1.2 - -1 byte-改变了String o="",e="";,以String o="",e=o;节省1个字节。这个想法来自 Gallant很抱歉,我忘了在上一次更新中应用此部分)。
  • V1.1 - -4 bytes- DROP掉从支架for环和移动的eVAR 空间增量到外的迭代器区for循环。这个想法来自加兰特
  • 1.0 - 136 bytes-初始溶液。

1
您可以将花括号放在内部循环上并分配e=o以保存3个字节。
Gallant

也可以String o="",...var o...其他3 交换
。– TyCobb

@tycobb它会导致无用的转换String o = "", e = "";var因为我必须将它们分成两个,从而导致var o = ""; var e = "";长度与我的长度相同。可以做到,但是VS在使用隐式类型的变量-aka var的时候不允许多变量声明。但是,谢谢您的帮助。 编辑:有VS喊我不能做,我假设这是不正确的,可能是错误的。
auhmaan

5

Python 2.7版,70 82个字节

我不知道如何在1行上得到它。致电e("abcde",0)

def e(s,p):
 f=len(s)
 for x in range(f):print(' '*p+s[:x+1])
 if f>1:e(s[1:],p+1)

4

Python 3,80 78字节

循环搜索要加前缀的空格数,然后搜索要结束的字符数。

lambda x:[print(' '*i+x[i:j+1])for i in range(len(x))for j in range(i,len(x))]

编辑:删除for循环之前的空格。


4

MATL,15个 14字节

由于@LuisMendo的提示,在此保存了一个字节!

tfWt2/!-RXzB*c

这么多方法...必须找到一个新方法。开心点!:)

在线尝试!

爆炸了

t       % duplicate input
f       % get indices of nonzero elements in vector (i.e. 1:n)
W       % 2 raised to array, element-wise: 2^(1:n)
t       % duplicate array
2/      % divide by 2: 2^(0:n-1)
!       % transpose array 
-       % element-wise subtraction (w/singleton expansion)
R       % upper triangular part
Xz      % nonzero elements
B       % convert from decimal to binary. Produces a logical array
*       % array product (element-wise, singleton expansion)
c       % convert to character array; 0's automatically converted to spaces

3

JavaScript(ES6),89个字节

document.write("<pre>"+(

s=>(a=[...s]).map((_,i)=>a.map((_,j)=>++j>i?r+=" ".repeat(i)+s.slice(i,j)+`
`:0),r="")&&r

)("abcde"))

直截了当的方法。输出包含尾随换行符。


=>Javascript是什么意思?它是二进制运算符

@EwanDelanoy它声明一个ES6箭头函数
user81655 '16

3

JavaScript(ES6),72

s=>{for(i=j=0;s[j]||s[j=++i];)console.log(' '.repeat(i)+s.slice(i,++j))}      

3

Pyth,12 11字节

jm+*;xQdd.:

可悲的是,这个问题使我们可以假设字符是唯一的,因此我只是查找子字符串的第一个位置,并用空格填充。


在最低级别的地图内时,您可以使用;代替\
FryAmTheEggman '16

3

Mathematica 89字节

r@i_:=StringReplace[i,#->" "]&/@(Complement[y,#]&/@Subsequences[y=Characters@i])//Column

说明

i 引用输入字符串

Subsequences[y=Characters@i]返回输入的所有子序列(表示的字符列表)。(Subsequences在第10.4节中引入)

对于每个子序列,Complement...返回输入字符串中存在的那些字符。这些字符中的每个字符都通过替换为空白StringReplace[i,#->" "]

Column在单列中显示结果。每个输出字符串具有相同数量的字符,从而使字母对齐。


r@"abcdefgh"

output


10.0.4代表10.4,对吧?10.3没有。
CalculatorFeline

是。10.4我会改正。
DavidC

3

J,32 29 28字节

(-@{.@i.|.])"1 a:>@-.~&,<\\.

该值为一元动词。在这里尝试。用法:

   f =: (-@{.@i.|.])"1 a:>@-.~&,<\\.
   f 'abe'
a  
ab 
abe
 b 
 be
  e

说明

作为其他答案,我计算每个子字符串的第一个字符的出现索引。子字符串存储在带有尾部空格的矩阵中,因此我将它们按其索引向右旋转以获取正确的填充量。"1和之间的空白a:非常令人讨厌...

(-@{.@i.|.])"1 a:>@-.~&,<\\.  Input is y
                        <\\.  Compute suffixes of prefixes of y, and put them in boxes.
                              This gives a 2D array of substrings in boxes.
                      &,      Flatten the array of boxes,
               a:  -.~        remove all empty strings, and
                 >@           open each box. This places the strings in a 2D matrix of
                              characters, with trailing spaces to make it rectangular.
(          )"1                Do this for each line x in the matrix:
      i.                        The index of every character of x in y.
 -@{.@                          Take the first one and negate it.
        |.]                     Rotate x to the left by that amount.
                                Since we negated the index, this rotates to the right.

a e不是挑战定义的子字符串
Ton Hospel '16

@TonHospel我修复了程序,现在它遵循规范。
Zgarb '16

3

JavaScript(Firefox 30-57),65 63字节

s=>[for(c of(i=0,s))for(d of(t=r=i?t+' ':'',s.slice(i++)))r+=d]

返回字符串数组。作为ES6,它为78个字节:

s=>[...s].map((_,i,a)=>a.slice(i).map(c=>r.push(u+=c),t=u=i?t+' ':''),r=[])&&r

2

QBasic,75个字节

INPUT s$
FOR i=1TO LEN(s$)
FOR j=1TO i
LOCATE,j
?MID$(s$,j,i+1-j)
NEXT
NEXT

基本的双FOR循环策略对QBasic基于1的索引进行了一些修改。主要技巧是LOCATE,j,它可以j在打印之前将光标移到当前行的列。由于列1是第一列,因此等效于打印j-1前导空格。


2

Perl 6,34个字节

perl6 -ne 'm/^(.*)(.+)<{+put " "x$0.to,$1}>/'
m/       # match the input line
  ^      # from the start
  ( .* ) # 0 or more characters ( $0 )
  ( .+ ) # 1 or more characters ( $1 )

  <{ # match against the result of:

    +put # print with a trailing newline:
      " " x $0.to, # add the leading spaces
      $1           # the substring
  }>
/

之所以使用+before,put是因为它返回1而不是True,这保证不在输入中,因此它总是必须回溯。

$ perl6 -ne 'm/^(.*)(.+)<{+put " "x$0.to,$1}>/' <<< abcd
   d
  cd
  c
 bcd
 bc
 b
abcd
abc
ab
a

(如果要以相反的顺序使用,请使用(.*?)(.+?)代替(.*)(.+)

这是受到Perl 5答案的启发


2

J,35 23 22字节

[:;#\.<@{."_1|.\."1^:2

我花了一段时间,但我终于对其进行了优化。

用法

   f =: [:;#\.<@{."_1|.\."1^:2
   f 'abcde'
abcde
abcd 
abc  
ab   
a    
 bcde
 bcd 
 bc  
 b   
  cde
  cd 
  c  
   de
   d 
    e

说明

[:;#\.<@{."_1|.\."1^:2  Input: s
             |.\."1     For each suffix of s, reverse it
                   ^:2  Repeat that twice to create all exploded substrings
   #\.                  Get the length of each suffix. This is
                        used to make the range [len(s), len(s)-1, ..., 1]
        {."_1           For each value in the range, take that many strings from
                        the list of exploded substrings. This avoids blank substrings
      <@                Box each set of strings
[:;                     Unbox and join the strings together and return

您可以通过删除右括号来节省2个字节。另外,执行[:+./"1' '~:]而不是[:-.[:*/"1' '=]保存另外2个字节。
Zgarb

2

Java,138个字节

String e(String s){int l=s.length(),a=0,i,j;for(;++a<l;)for(i=0;i<=l-a;){s+="\n";for(j=0;j++<i;)s+=" ";s+=s.substring(i,i+++a);}return s;}

格式:

String e(String s) {
    int l = s.length(), a = 0, i, j;
    for (; ++a < l;)
        for (i = 0; i <= l - a;) {
            s += "\n";
            for (j = 0; j++ < i;)
                s += " ";
            s += s.substring(i, i++ + a);
        }
    return s;
}


1

Haskell,65个字节

(>>=zipWith((++).(`replicate`' '))[0..].init.tails).reverse.inits

它需要initstails来自Data.List。要输出,请添加mapM_ putStrLn.到最前面。

相对简单;的reverse是要确保原始字符串是第一。

GHCi> mapM_ putStrLn.(>>=zipWith((++).(`replicate`' '))[0..].init.tails).reverse.inits$"abcde"
abcde
 bcde
  cde
   de
    e
abcd
 bcd
  cd
   d
abc
 bc
  c
ab
 b
a
it :: ()
(0.02 secs, 0 bytes)

2
(>>=zipWith(++)(inits$cycle" ").init.tails).inits。并将其添加import Data.List;到字节数中。
nimi 2016年

1

Ruby,75 67字节

匿名函数。使用正则表达式替换来对齐子字符串。 .是填充符。

->s{(l=s.size).times{|i|(l-i).times{|j|puts s.tr(?^+s[j,i+1],?.)}}}

1

bash + GNU coreutils,109字节

l=${#1}
for i in `seq 0 $l`;{
for j in `seq $((l-i))`;{
for k in `seq $i`;{ printf ' ';}
echo ${1:i:j}
}; }

也许有一个较短的解决方案,但这是我想到的最好的方法。个性的独特性在这里并不重要。


1

PHP,151个字符

不打高尔夫球

<?php
$input = $argv[1];
foreach(str_split($input) as $p=>$letter)
{
    $spaces = str_repeat(" ", $p);
    echo $spaces.$letter."\n";
    $p++;
    for($i=$p;$i<strlen($input);$i++)
    {
        echo $spaces.$letter.substr($input, $p, $i)."\n";
    }
}
?>

打高尔夫球

<?$c=$argv[1];foreach(str_split($c)as$d=>$b){$a=str_repeat(" ",$d);echo$a.$b."\n";$d++;for($e=$d;$e<strlen($c);$e++){echo$a.$b.substr($c,$d,$e)."\n";}}

php explodesub.php 'abc'
a
ab
abc
 b
 bc
  c

1

C ++,145字节

第一个开始参数用作输入,控制台用作输出

#include<iostream>
#define f(y,b,d) for(int y=b;r[0][y];y++){d;}
int main(int,char*r[]){f(x,0,f(y,x+1,std::cout.write(r[0],y)<<'\n')r[0][x]=32)}

好的答案,欢迎来到PPCG!我用的不是C ++,但是您不能std::cout<<r[0]<<y<<'\n'代替`std :: cout.write(r [0],y)<<'\ n'吗?能否请您简要说明一下?谢谢!
NoOneIsHere

1

Python 2(非高尔夫)99字节

t=raw_input()
l=len(t)
for j in range(l):
 for i in range(l):
  if i>=j:print j*' '+t[j:i+1]  

结果:

>>python codegolf.py
abc
a
ab
abc
 b
 bc
  c

>>python codegolf.py
abcdef
a
ab
abc
abcd
abcde
abcdef
 b
 bc
 bcd
 bcde
 bcdef
  c
  cd
  cde
  cdef
   d
   de
   def
    e
    ef
     f

>>python codegolf.py
lmnopqrst
l
lm
lmn
lmno
lmnop
lmnopq
lmnopqr
lmnopqrs
lmnopqrst
 m
 mn
 mno
 mnop
 mnopq
 mnopqr
 mnopqrs
 mnopqrst
  n
  no
  nop
  nopq
  nopqr
  nopqrs
  nopqrst
   o
   op
   opq
   opqr
   opqrs
   opqrst
    p
    pq
    pqr
    pqrs
    pqrst
     q
     qr
     qrs
     qrst
      r
      rs
      rst
       s
       st
        t
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.