最長の非繰り返し部分文字列


33

入力として文字列を指定すると、2回以上文字を持たない最長の連続部分文字列を見つけます。そのような部分文字列が複数ある場合は、どちらかを出力できます。必要に応じて、入力が印刷可能なASCII範囲にあると想定できます。

得点

回答は、最初に独自の最長の非繰り返し部分文字列の長さによってランク付けされ、次にその合計長さによってランク付けされます。両方の基準でスコアが低いほど優れています。言語によっては、これはおそらくソース制限のある挑戦のように感じるでしょう。

自明

1、x(言語)または2のスコアを達成する一部の言語では、x(Brain-flakおよびその他のチューリングターピット)は非常に簡単ですが、最長の非繰り返し部分文字列を最小化することが課題となる他の言語もあります。Haskellで2点を獲得するのはとても楽しかったので、このタスクが楽しい言語を探すことをお勧めします。

テストケース

"Good morning, Green orb!" -> "ing, Gre"
"fffffffffff" -> "f"
"oiiiiioiiii" -> "io", "oi"
"1234567890"  -> "1234567890"
"11122324455" -> "324"

得点提出

次のスニペットを使用してプログラムを採点できます。


提案されたテストケース:11122324455Jonathan Allanは、私の最初のリビジョンでは正しく処理されなかったことに気付きました。
デニス

@Dennisテストケースが追加されました。私はそれがどのように起こったかについて興味があります。
小麦ウィザード

2
すべての部分文字列(既に長さでソート済み)を生成し、部分文字列を重複排除し、部分文字列のままにしたものを保持しました。残念ながら、それは順序を変えます。11122324に発生しますが、重複除外され12ます。
デニス

空白の答えはどこにあるのだろうかと思っています。
魔法のタコ

回答:


13

C、スコア 2、747   720  662バイト

L  [  1  <<  7  ]  ,  *  q  ,  *  r  ,  l  ,  d  ,  i  ,  c  ,  j  ,  s  ,  t  ,  k  =  1  <<  7  ;  h  (  )  {  q  =  s  +  i  +  j  ++  ;  *  q  %  k  &&  !  L  [  *  q  %  k  ]  ++  &&  h  (  ++  c  )  ;  }  g  (  )  {  q  =  s  +  i  ;  *  q  %  k  ?  z  (  k  )  ,  h  (  j  =  c  =  0  )  ,  c  >  d  &&  (  d  =  c  )  &&  (  l  =  i  )  ,  g  (  ++  i  )  :  0  ;  }  f  (  S  ,  T  )  {  s  =  S  ;  l  =  i  =  d  =  0  ;  g  (  t  =  T  )  ;  p  (  i  =  0  )  ;  }  p  (  )  {  q  =  s  +  l  +  i  ;  r  =  t  +  i  ;  i  ++  <  d  ?  p  (  *  r  =  *  q  )  :  (  *  r  =  0  )  ;  }  z  (  i  )  {  L  [  --  i  ]  =  0  ;  i  &&  z  (  i  )  ;  }

少なくとも32ビットMinGWで動作します(最適化は無効になっています)。単一のキーワードを使用しません。

gccとclangを使用したTIOでも動作するようです。(ありがとう@Dennis!)

で呼び出す:

int main()
{
    char str[1024];

    f("Good morning, Green orb!", str);
    puts(str);

    f("fffffffffff", str);
    puts(str);

    f("oiiiiioiiii", str);
    puts(str);

    f("1234567890", str);
    puts(str);

    f("L  [  1  <<  7  ]  ,  *  q  ,  *  r  ,  l  ,  d  ,  i  ,  c  ,  j  ,  s  ,  t  ,  k  =  1  <<  7  ;  h  (  )  {  q  =  s  +  i  +  j  ++  ;  *  q  %  k  &&  !  L  [  *  q  %  k  ]  ++  &&  h  (  ++  c  )  ;  }  g  (  )  {  q  =  s  +  i  ;  *  q  %  k  ?  z  (  k  )  ,  h  (  j  =  c  =  0  )  ,  c  >  d  &&  (  d  =  c  )  &&  (  l  =  i  )  ,  g  (  ++  i  )  :  0  ;  }  f  (  S  ,  T  )  {  s  =  S  ;  l  =  i  =  d  =  0  ;  g  (  t  =  T  )  ;  p  (  i  =  0  )  ;  }  p  (  )  {  q  =  s  +  l  +  i  ;  r  =  t  +  i  ;  i  ++  <  d  ?  p  (  *  r  =  *  q  )  :  (  *  r  =  0  )  ;  }  z  (  i  )  {  L  [  --  i  ]  =  0  ;  i  &&  z  (  i  )  ;  }");
    puts(str);
}

出力:

少し読みやすい形式のコード:

L[1<<7],
*q, *r, l, d, i, c, j, s, t, k=1<<7;

h()
{
    q = s+i+j++;
    *q%k && !L[*q%k]++ && h(++c);
}

g()
{
    q = s+i;
    *q%k ? z(k), h(j=c=0), c>d && (d=c) && (l=i), g(++i) : 0;
}

f(S, T)
{
    s = S;
    l = i = d = 0;
    g(t=T);
    p(i=0);
}

p()
{
    q = s+l+i;
    r = t+i;
    i++<d ? p(*r=*q) : (*r=0);
}

z(i)
{
    L[--i] = 0;
    i && z(i);
}

そして、これを使用して適切な間隔を生成し、スコア2で書式設定を行うことができます。オンラインで試してください!


C、スコア3、309バイト

i
,
j
,
l
,
c
,
d
;
f
(
\
c\
\
h\
\
a\
\
r
*
s
)
{
\
f\
\
o\
\
r
\
(
i
=
l
=
d
=
0
;
s
[
i
]
;
c
>
d
&&
(
d
=
c
)
&&
(
l
=
i
)
,
++
i
)
\
f\
\
o\
\
r
(
\
c\
\
h\
\
a\
\
r

L
[
\
1\
\
2\
\
8
\
]
=
{
j
=
c
=
0
}
;
s
[
i
+
j
]
&&
!
L
[
s
[
i
+
j
++
]
]
++
;
++
c
)
;
\
w\
\
r\
\
i\
\
t\
\
e
(
1
,
s
+
l
,
d
)
;
}

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


10

Haskell、スコア2、492 ... 307 224 212 209 207バイト

((yy:yyy))??ss|ss==yy  =  ""  |  yy==yy=yy:yyy??ss
ss??sss=ss
ss""=""

ss((ff:fff))  =  ff  :  ss  fff??ff
ff""=""

ff((xxx:xx))  =  ss((xxx:xx))##ff  xx
xx##xxx  |  ((((xx>>xx))<))  $  xxx>>xx=xxx|xx==xx=xx

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

おかげバイトの文字通り何百Golfed WWØrjanヨハンセン

説明

この関数(??)は、文字cと文字列sを受け取り、をs含まない最長のプレフィックスを返しますc。ゴルフをしていない、スコアに最適化されていない:

c ?? (y:s)  
    | c==y = ""
    | True = y : c ?? s
c ?? s = s

この関数ss(??)、指定された文字列の一意の文字の最長プレフィックスを見つけるために使用します。

ss (x:r) = x : (x ?? ss r)
ss "" = ""

(##)2つの文字列を取り、長い方を返す関数です。長さの比較は、文字列を繰り返すことによって動作するxことが多いほどx(長くなるx>>y)としてy長い(あるy>>x)と辞書大きい得られた文字列のチェック。

x ## y
  | (x>>x) < (y>>x) = y
  | True = x

最後にff、入力文字列の上に再帰的で最長プレフィックスを生成しss、再帰的に最長の文字列と戻り2つとの長い尾のサブ非繰り返し判定する(##)

ff "" = ""
ff (x:r) = ss(x:r) ## ff r

4
224、主に中間リストを融合します。
Ørjanヨハンセン

2
この回答を、以前チャットで投稿した回答と組み合わせて216を得ました。
小麦ウィザード

3
209物事を並べ替えることによって。
Ørjanヨハンセン

3
恵みの発表で、私は別の見ていたし、実現@トリックが実際にオーバーだけで作る2バイトコスト?2つの文字を:207
Ørjanヨハンセンを

5

Lua、スコア3、274バイト

g='g'..'s'..'u'..'b'  _G  [  'l'..'o'..'a'..'d'  ](  g[g  ](  "s  =...f  o  r d = # s - 1 , 0 , - 1 d  o f  or r = 1 , # s - d d  o t = s :s  ub  (r  ,r  +d  )i  f n  ot t:  fi  nd  '(  .)  .*  %1  't  he  n p  ri  nt  (t  )r  et  ur  n en  d e  n  d e  nd  ","  ",""))(...)

注:Lua 5.2またはLua 5.3が必要です

使用法:

$ lua lnrs.lua "Good morning, Green orb!"
ing, Gre
$ lua lnrs.lua "fffffffffff"
f
$ lua lnrs.lua "oiiiiioiiii"
oi
$ lua lnrs.lua "1234567890"
1234567890
$ lua lnrs.lua "11122324455"
324

主なアイデア:すべてをスペースでインターリーブし、挿入します " "(2つのスペース)を長い識別子を分割します

未ゴルフコード:

g = "gsub"
_G["load"](
   g[g](      -- g[g] == string.gsub - a function for substitution of substrings
      "The source of actual program, but two-space sequences were inserted in some places", 
      "  ",   -- we are replacing all two-space substrings
      ""      -- with an empty string
   )
)(...)

実際のプログラム(スペースのすべてのペアを削除した後):

s = ...
for d = #s - 1, 0, -1 do
   for r = 1, #s - d do
      t = s:sub(r, r+d)
      if not t:find"(.).*%1" then
         print(t)
         return
      end
   end
end

ところで、スコアを計算するためのJSスニペットは私のコードで失敗します。


4

Retina 0.8.2、37バイト、スコア9

.
$&$'¶
(.)(?<=\1.+).*

O#$^`
$.&
1G`

オンラインでお試しください!この回答をRetina 1に直接翻訳すると、のN代わりにを使用してバイトを節約できますO#。ただし、Retina 1の回答を28バイトまでナイーブにゴルフした場合、そのスコアは実際には10に上がります!説明:

.
$&$'¶

入力のすべての接尾辞を生成します。

(.)(?<=\1.+).*

各接尾辞について、最初に複製された文字までの接頭辞を取ります。

O#$^`
$.&

残りの文字列を長さの逆順に並べ替えます(つまり、最も長いものが最初になります)。

1G`

最長を取る。


4

ゼリー、スコア2、14バイト

Ẇµµff  Q  €  Ṫ

スコア-1、+ 7バイト、およびバグに気付いた@JonathanAllanに感謝します。

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

使い方

Ẇµµff  Q  €  Ṫ  Main link. Argument: s (string)

Ẇ               Window; yield all substrings of s, sorted by length.
 µ              Begin a new chain. Argument: A (array of substrings)
  µ             Begin a new chain. Argument: A (array of substrings)
   f            Filter A by presence in itself. Does nothing.
       Q  €     Unique each; deduplicate all strings in A.
    f           Filter A by presence in the array of deduplicated substrings,
                keeping only substrings composed of unique characters.
             Ṫ  Tail; take the last (longest) kept substring.

4

クリーン、スコア7 5、276バイト

@[ss:s]=rr(pp[][ss:s])((@s))
@s=s
ee x[rr:xx]|e x rr=True=ee x xx
ee x xx=f
f=e'e'' '
e::!  Char  !  Char  ->Bool
e  _ _=  code  {

eqC
}
pp p[r:rr]|ee r p=p=pp(a r p)rr
pp a _=a
a  x[ll:l]=[ll:a x  l]
a l ll=[l]
l[]rr=e'l''l'
l ff[]=f

l[r:rr][ss:ll]=l rr ll
rr x y|l x y=y=x

オンラインでお試しください!Clean内から直接ABCマシンコードを呼び出すことができることを示してくれた@Οurousに感謝します。これによりimport、最小スコアを7に設定する前のボトルネックを取り除くことができますが、キーワードが必要ですcodeこのアプローチでは最小スコアを5に設定するです。

上記のコードのスコアが最適化されていないバージョンは、ここで見つけることができます:オンラインで試してみてください!


スコア7、158 154 130バイトの以前のバージョン

import  StdEnv  
@[xx:rr]=c(%[][xx:rr])(@rr)
@e=e
c s b|  length  s<  length  b=b=s
%s[xx:r]|  isMember xx s=s= %(s++[xx])r
%r _=r

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

importスコアが輸入しないと7の下に行くことができないものである任意のライブラリ関数せずに文字列や文字の等価性を実装する必要があるだろうおそらくない上に新しいバージョンに見られるように、可能。


1
実際、インラインABCを使用して平等を実装できます。これにより、スコアが低下します。興味のある方は、本日後半に修正案をお送りします。
Οurous

例:char equality:tio.run
##

@Ourous A code block with raw ABC instructions, which can be used for primitive functions like integer addition, for linking with C, bypassing the type system... welcome down the rabbit hole!cloogleから)確かに魅力的に聞こえます。明日、その提案に感謝します!
ライコニ

1
Οurousおかげで再び、あなたのchar平等のテストでスコアを5になりました@
Laikoni

ちなみに、-IL何もインポートされていないため、どちらのフラグも必要ありません。
Οurous

3

Python 3、スコア4、155バイト

exec(('l=la''mbd''a f'',e=en''ume''rat''e:m''ax''([f[ j  :k]  for  j,i in e ( f)f''or  k,i in e ( f )if  len  ( { *''f[j'':k]''})==k-''j],''key''=le''n)'))

これは関数を定義しますl

長さ3の文字列はスコアを上げず、32バイトを節約することを指摘してくれた@xnorに感謝します。

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


文字列は3つのチャンクにすることができますか?
xnor

@xnor実際に関数の名前を変更します。ありがとう!
デニス

3

Brachylog、スコア2、19バイト

s  ᶠ  l  ᵒ  ≠  ˢ  t

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

退屈な古い「すべてを空にする」答え。少なくとも、メタ述語は述語から間隔を空けて動作することができることを学びました(そして(パラメトリック)下付き文字と上付き文字はできません)。

s ᶠ -指定された文字列のすべての部分文字列を検索します

l ᵒ -長さで並べ替えます(デフォルトで昇順)

≠ ˢ -すべての明確な要素を持つものを選択します

t -その末尾(最後の要素)を取得する-最大の長さを持つもの


2

Pyth、11バイト、スコア4

デニスのおかげで-4点

e lD {I# .:

elD{I#.:Q      Full program, inputs "string" from stdin and outputs to stdout
e              The last element of the list generated by taking
      .:Q      All substrings of the input
     #         Filtered for
   {I          Being invariant over deduplicate i.e. being "non-repeating"
 lD            and sorted by length

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


2

、スコア2、10バイト

►IIËII≠IIQ

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

説明

プログラムはこれと同等です:

►Ë≠Q  Implicit input.
   Q  List of substrings.
►     Find one that maximizes:
 Ë    all ordered pairs
  ≠   are inequal.

ビルトインは、その引数のすべての順序付けられたペアでË評価し、すべての結果が真実であればx戻りlength(x)+1、そうでなければを返します0。これを最大化すると、文字が繰り返されない最長の文字列が見つかります。

提出では、I各関数の間にアイデンティティ関数を2回挿入するだけです。はと同じであるためË、などI≠と同じであるため、これはセマンティクスを変更しません。唯一の危険性は、高階関数がIsの1つを引数として使用することを決定できることですが、幸いなことにプログラムで型エラーが発生するため、発生しません。


2

Clojure、スコア4

#(  let  [N  (fn  [[_ & r]] r) R  (fn  R [f v c]  (if  c (R f (f v (  nth  c 0))  ( N  c)) v)) C  (fn  C  (  [i]  (C (  seq  i) 0)) ( [i  n]  (if i (C ( N  i )  (  inc n)) n)))  J  (fn  [c  i]  (assoc c (C  c) i)) I  (fn  F [f i n R]  (if ( =  (C  R) n) R (F f (f  i) n ( J  R (f  i)))))] ( apply  str  (R ( fn  [a  b] ( if  (< (C  a)  (C  b)) b a )) "" (  for  [k  (I N % (C  % ) [])]  (R  ( fn [ t  c ] ( if ( or ( = t (  str t) ) ((  set t)c))(apply  str t) ( J  t c)))[]k)))))

ああ、これは痛かった!Nimplements nextRis reduceCis countJis conj(ベクターに対してのみ機能します)およびIis iterateです。apply strそうでないと、「aaaa」入力が文字列ではなくベクトルを返すため[\a]です。幸いなことに、を使用するようにapplyなりassoc、ベクターの最後の要素を超えて1つのインデックスを関連付けることができるとは知りませんでした:o




1

Python 3、スコア4、317バイト

exec(('%s'  *58  %(  's=','in','pu','t(',');','pr','in','t(','so','rt','ed','((s','[i',':j',']f','or',' j',' i','n ','ra','ng','e(','1,','le','n(','s)','+1',')f','or',' i',' i','n ','ra','ng','e(','j)','if',' l','en','(s','et','(s','[i',':j',']))','==l','en','(s','[i',':j',']))',',k','ey','=l','en',')[','-1','])')))

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

実行されていないコード:

s=input();print(sorted((s[i:j]for j in range(1,len(s)+1)for i in range(j)if len(set(s[i:j]))==len(s[i:j])),key=len)[-1])

lambda acontains mbda にはスコア5があり、関数にはreturn明らかにexec編集できない(したがって、少なくとも5のスコアを取るeturn)必要があるため、完全なプログラムが必要でした。おそらく、実行されていないコードサイズをかなり少なくすることは可能かもしれませんが、すぐに明確な改善を見ることはできません。


1

アリス、40バイト

/ii..nn$$@@BBww..DD~~FF..!!nn$$KK??oo@@

(末尾の改行)

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

命令ポインタは順序モードで斜めに移動するため、1文字おきに実行されます。

i.n$@Bw.D~F.!n$K?o@

i     take input
.n$@  terminate if empty
B     push all nonempty substrings, with the longest on the top of the stack
w     push return address (start main loop)
.     make copy of current substring
D     deduplicate characters
~     swap: this places the original above the deduplicated copy
F     Push the original string if it is a substring of the deduplicated copy
      (which can only happen if they're equal); otherwise push empty string
.!    place a copy on the tape
n$K   if the empty string was pushed, return to start of loop
o     output
@     terminate

1

Perl 6、スコア:15 10 8、長さ:46 55 62バイト

{~m:ov/(.+)<!{$0.comb.repeated}>/.max(&chars)}

試して

{~m:ov/(..*)<!{(($0)).comb.repeated}>{{}}/.max(&chars)}

試して

{m:ov:i/(..*)<!{(($0)).comb.repeated}>{{}}/.max((&chars)).Str}

試して

拡張:

{    # bare block lambda with implicit parameter 「$_」

    m                          # match (implicitly against 「$_」)
    :overlap                   # in every single way possible
    :ignorecase                # add a 「:」 to break up substring
    /

      (..*)                    # match at least one character

      <!{
        (($0)).comb.repeated  # backtrack if there were repeats
      }>

      {{}}                    # anon hash in code block (no-op)
    /

    .max((&chars))            # get the longest

    .Str                      # coerce to a Str (from a Match object)
}

88バイトで5点。ゴルフのバイトにはいくつかの場所があるかもしれません
ジョーキング

1

Java 8、スコア9(384 B) 7(401 B)

S -> { int s = 0 , e = 0 , l = 0 , x = 0 , y = 0 , b [ ] = new int [ 256 ] ; for ( ; x <S.  length  & y <S.  length  & l <S.  length  - x ; x ++ ) { b [S[x]] = 1 ; for ( y ++ ; y <S.  length  && b [S[y]] < 1 ; b [S[y ++]] = 1 ) ; if ( l < y - x ) { s = x ; e = y ; l = y - x ; } for ( ; y <S.  length  && x < y & S[x] != S[y  ];)b [S[x ++]] = 0 ; }  String g=""; for( ; s<e ; g+= S[s++]);  return  g;}
  • 初期バージョン。ここから下に行きます。スコアは9のため"ubstring "substring交換する最初の部分になります。
  • " length"これにより、スコアは7 になりました。おそらく、これをさらに減らすことはできないでしょう。.の4つの用途を削除することはできないと思いますlength。可能であれば、" eturn"(6)最終的な改善としてスコアを1下げる可能性がありますが、これはそれであると思います(バイトカウントのわずかな削減を除く。)

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



0

Mathematica、スコア11 9

Length@Last@Select[Subsequences[Characters@#],#==DeleteDuplicates  @#&]&

関数の名前を不明瞭にすることにより、最長の非反復文字列から数バイトを削ります:

Length@Last@Select[Subsequences[Characters  @#],#==(  ToExpression@ 
StringJoin@@FromCharacterCode@{{68},{101},{108},{101},{116},{101},{68},{117},
{112},{108},{105},{99},{97},{116},{101},{115}}))@#&]&

0

Kotlin、スコア:11 10 9バイト、長さ:227 246 245バイト

indices
  .flatMap { p -> indices . map { p to p + it } }
  .  filter { (r,i) -> i < length  }
  .map { ( s , a )->substring  (  s,  a  ) }
  .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
  .maxBy { it.length }

最長はubstring9文字です

次のように呼び出されます。

val c = "Good morning, Green orb!"

fun String.c(): String? = indices
    .flatMap { p -> indices . map { p to p + it } }
    .  filter { (r,i) -> i < length  }
    .map { ( s , a )->substring  (  s,  a  ) }
    .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
    .maxBy { it.length }

fun main(args: Array<String>) {
    val text = """indices
    .flatMap { p -> indices . map { p to p + it } }
    .  filter { (r,i) -> i < length  }
    .map { ( s , a )->substring  (  s,  a  ) }
    .  filter { it  .  groupBy  { it } .  none { ( k , v )->v . size>1 } }
    .maxBy { it.length }"""
    val message = text.c()!!
    println(message)
    println(text.length)
    println(message.length)
    println(c.c())
}

roupingByとの間にスペースを追加して10に減らすことはできません{か?
ケビンクルーイッセン

1
素敵な発見、私は他の11を変更し、10になった
jrtapsell

これ 10文字ですが、最も長い部分文字列はroupingBy(9文字)ではなくeachCount(末尾スペースを含む)です。
エリックアウトゴルファー

roupingBy 末尾のスペースがあります(
マークダウンで



0

05AB1E、22バイト| スコア:2

Œ  ʒ  D  Ù  Q  }  é  ¤

-1スコア+ HeebyJeebyのおかげで7バイト

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


05AB1E、15バイト| スコア:3

Œ ʒ D Ù Q } é ¤

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


05AB1E、8バイト| スコア:8

ŒʒDÙQ}é¤

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


05AB1Eは実際にはかなり安価なことを行うことができます... 05AB1Eに空白を追加しても何も起こりません。

これに対するルールがある場合は、´他の7文字を使用することもできます。


1
@HeebyJeebyMan私はバカだから、それで問題が発生しましたか?
魔法のタコ

@HeebyJeebyMan冗談です、ハハ、アイデアをありがとう。
魔法のタコ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.