分解された部分文字列


32

前書き

stringを観察しましょうabc。これから作成できる部分文字列は次のとおりです。

a, ab, abc, b, bc, c

次のように、最初の文字列の下にそれらを配置する必要があります。

abc
a
 b
  c
ab
 bc
abc

文字列の順序は重要ではないため、これも完全に有効です。

abc
a
ab
abc
 b
 bc
  c

したがって、サブストリングは、初期ストリングのサブストリングの位置の下に配置されます。したがってabcdef、substringのcde場合、次のようになります。

abcdef
  cde

タスク

タスクは、上記のようにすべての部分文字列を0より大きい長さに揃えることです。文字列自体にはアルファベット文字のみが含まれ、少なくとも1文字は含まれると想定できます。パディングには、スペースまたはその他のアルファベット以外の印刷可能なASCII文字(32 - 127)を使用できます。言及するかもしれない必要はありませんが、文字列自体はそうではないように、ユニークな文字が含まれていますabaから、a2回出現します。

テストケース

入力: 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
空の部分文字列はどこにありますか?
リーキー修道女

@KennyLauそうそう、それはチャレンジにいくつかの情報を編集することを思い出させます。
アドナン

末尾の改行は受け入れられますか?
-user81655

@ user81655はい、それは許容範囲です。
アドナン

文字列の配列は受け入れ可能ですか、それとも改行で区切る必要がありますか?
-Zgarb

回答:



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

4
@TimmyD:いくつかの奇妙な理由でゴルフはPerlのに悪い名前を与えると言う人々は...ある
トンHospel

これに触発されたPerl 6バージョンは機能的に非常に似ていますperl6 -ne 'm/^(.*)(.+)<{+put " "x$0.to,$1}>/'
ブラッドギルバートb2gills

入力では機能しませんab1say...評価はであるため1)。(5.18.2でテスト済み。)編集:ああ!申し訳ありませんが、「文字列自体にはアルファベット文字のみが含まれると想定できます」という質問があります。
msh210

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

オンラインコンパイラでは、最長のテストケースでメモリが不足します。

オンラインでお試しください!

説明

これは、すべての値のパターンを生成し01そして2昇順に、次いで変換20。これは、すべての可能なパターンを与える01場所1値の連続する値が連続します。これらは、元の文字列から取得された文字をマークするために使用されます。

例として、文字列の場合'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

重複する行2への変換0(つまり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
あなたの心は1つの大きなマトリックス操作マシンですか?

@cat Matlabの使用が長すぎます:
ルイスメンドー

14

網膜48 32 31バイト

3バイトを節約し、さらに多くの道を開いてくれたKenny Lauに感謝します。

バイトカウントは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

これ%は、この行全体が各行に対して個別に実行されることを意味します(とりあえず別の文字列とみなし、最後に改行で結合します)。+出力が変化しなくなるまでループでこの置換を実行するために、網膜に指示します(これはこの場合の手段で正規表現がもはや一致していること)。次に、正規表現は、入力の最後の行と少なくとも2つのスペース以外の文字を一致させ、最初の行をスペースに置き換える新しい行を追加します。


私たちが持つことができる!意味Mと1charのバージョンを.+して.*
CalculatorFeline

また、文字列のプレフィックスのプレフィックス=文字列のプレフィックス。たぶんあなたは接尾辞の接頭辞を意味しましたか?(修正するために編集。)
CalculatorFeline

@CatsAreFluffyいいえ、説明は正しくありませんでした。プレフィックスからプレフィックスを削除すると、サブストリングが取得されます。他の提案については、オプションをステージを意味するつもりはありません。現在、多くのキャラクターは1つのステージタイプにのみ使用されていますが、将来的には変更される可能性があります。.+.*私は正規表現をトークン化する必要があります、そして私はいつかそれを行うことを計画している間、私はそれがすぐにいつでも起こるとは思わないと思います実際に表現力を追加します)。
マーティンエンダー


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

CJam、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'}ます。アイデアは、最初または最後の文字を切り捨てる2つの分岐を再帰的に再帰することです。は冗長出力を提供しますが、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- Dropedからブラケットforループと移動eするvar 空間インクリメント外側のイテレータゾーンにforループ。アイデアはギャラントからのものでしたでした。
  • v1.0の - 136 bytes-初期ソリューション。

1
内側のループに中括弧をドロップして、e=o3バイトを節約するために割り当てます。
ギャラント

別の3 String o="",...と交換することもできvar o...ます。
TyCobb16年

@tycobb無駄な変換レンダリングになるString o = "", e = "";までvar、私は、その結果、二つにそれらを分離しなければならないので、var o = ""; var e = "";私が持っているものと比較して、同じ長さであるが。それを行いますが、VSは暗黙的に型指定された変数(別名)を使用する場合、複数の変数宣言を許可しません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のヒントのために1バイトを節約しました

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で何を意味しますか?それは二項演算子である
ユアン・Delanoy

@EwanDelanoy ES6 Arrow Functionを宣言します。
user81655

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

3

Mathematica 89バイト

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

説明

i 入力文字列を参照します

Subsequences[y=Characters@i]入力のすべてのサブシーケンス(文字のリストを表す)を返します。(Subsequences was introduced in v. 10.4)

各サブシーケンスに対して、存在しないComplement...入力文字列の文字を返します。これらの各文字は、次のようにして空のスペースに置き換えられますStringReplace[i,#->" "]ます。

Column結果を単一の列に表示します。各出力文字列の文字数は同じであるため、文字が整列されます。


r@"abcdefgh"

output


10.0.4では、10.4を意味しますか?10.3にはありません。
CalculatorFeline

Yes. 10.4 I'll correct it.
DavidC

3

J, 32 29 28 bytes

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

This evaluates to a monadic verb. Try it here. Usage:

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

Explanation

As some other answers, I compute the index of occurrence of the first character of each substring. The substrings are stored in a matrix with trailing spaces, so I rotate them to the right by their index to get the right amount of padding. That one piece of whitespace between "1 and a: is really annoying...

(-@{.@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 is not a substring as defined by the challenge
Ton Hospel

@TonHospel I fixed the program, it now follows the spec.
Zgarb

3

JavaScript (Firefox 30-57), 65 63 bytes

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

Returns an array of strings. As ES6 it's 78 bytes:

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

2

QBasic, 75 bytes

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

The basic double-FOR-loop strategy, modified a bit for QBasic's 1-based indexing. The main trick is LOCATE,j, which moves the cursor over to column j of the current line before printing. Since column 1 is the first column, this is equivalent to printing j-1 leading spaces.


2

Perl 6, 34 bytes

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
  }>
/

The reason for the + before put is so that it returns 1 instead of True, which is guaranteed not to be in the input so it always has to backtrack.

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

( If you want it in the opposite order use (.*?)(.+?) instead of (.*)(.+) )

This was inspired by the Perl 5 answer.


2

J, 35 23 22 bytes

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

It took me a while but I finally optimized it.

Usage

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

Explanation

[:;#\.<@{."_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

You can save 2 bytes by removing the right pair of parentheses. Also, doing [:+./"1' '~:] instead of [:-.[:*/"1' '=] saves another 2 bytes.
Zgarb

2

Java, 138 bytes

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;}

Formatted:

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

Pyke, 15 bytes

QlFUQRd:DlRF2h<

Try it here!

Assumes array of padded strings is acceptable

Pads first and then chops.


1

Haskell, 65 bytes

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

It requires inits and tails from Data.List, though. To output it, add mapM_ putStrLn. to the front.

Relatively straightforward; the reverse is to make sure the original string is first.

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. And please add the import Data.List; to the byte count.
nimi

1

Ruby, 75 67 bytes

Anonymous function. Uses regex substitution to align the substrings. . is the filler character.

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

1

bash + GNU coreutils, 109 Bytes

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

Maybe there is a shorter solution, but this is the best that came into my mind. Uniqueness of chracters does not matter here.


1

PHP, 151 chars

Ungolfed

<?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";
    }
}
?>

Golfed

<?$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";}}

Example

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

1

C++, 145 Bytes

the first start parameter is used as input, console as output

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

Great answer and welcome to PPCG! I don't use C++ much but can't you do std::cout<<r[0]<<y<<'\n' instead of `std::cout.write(r[0],y)<<'\n'? Can you please add a brief explanation? Thanks!
NoOneIsHere

1

Python 2 (Ungolfed) 99 Bytes

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]  

Result:

>>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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.