最短の固有部分文字列


14

(STDINでは、コマンドライン引数として、または関数引数として)2つの異なる空ではない文字列を指定し、2番目の部分文字列ではない最初の文字列の最短部分文字列を見つけて返します。そのような部分文字列が存在しない場合は、空の文字列を返すか、元の文字列の部分文字列ではない文字列を返すか、例外をスローできます。関数から戻る場合、この場合はnull(または未定義、Noneなど)を返すこともできます。複数のこのような部分文字列が最短で結び付けられている場合、それらのいずれかを返すことができます。

文字列は、印刷可能な任意のASCII文字で構成できます。

STDINで指定された入力は、各行に1つの文字列で指定されます。リクエストに応じて、入力の最後に単一の空行を追加できます。

これはコードゴルフであるため、最短の有効なプログラムが勝ちます。

いくつかのテストケース

入力:

STRING ONE
STRING TWO

出力:

E

入力:

A&&C
A&$C

有効な出力:

&&
&C

入力:

(2つのランダムに生成された80文字の文字列)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

すべての有効な出力:

AD
BJ
BR
CZ
DD
EE
ER
EY
EY
FF
FJ
FW
FZ
HE
IJ
IN
IW
JC
JR
JY
KL
KP
KR
KV
LU
MH
MI
NB
NQ
OY
PK
PY
QE
QF
QI
RA
RB
RF
RO
RV
RY
RZ
SW
UE
UH
UN
UR
VD
VQ
VU
WB
WE
WI
WU
XN
XP
YI
YK
YK
YM
YS
YW
YX
ZB
ZJ
ZN
ZV

1
最短か最長か?
漏れの修道女

@FryAmTheEggmanはその後、私はまだ私の解決策を投稿する必要があります...
漏れ修道女

引用符付きまたは引用符なしの「各行に1つの文字列」
リーキー修道女

1
文字列の配列を取得できますか?
デニス

「B」は「aBc」の部分文字列ですか?
downrep_nation

回答:


4

Brachylog、23バイト

:1foh.,{,.[A:B]hs?'~sB}

古いJavaトランスパイラーで動作します。リスト内の2つの文字列を入力として期待し、出力を部分文字列と統合します。部分文字列が見つからない場合、falseを返します。

残念ながら、新しいPrologトランスパイラーに組み込まれているサブセットはまだコーディングしていません。

説明

:1f               Find all bindings which satisfy predicate 1 with that binding as input and
                  with the Input of the main predicate as output.
   oh.,           Order that list of bindings, and unify the output with the first one.

{
 ,.[A:B]          Unify the output with the list [A,B]
        hs?       Unify the input with a subset of A
           '~sB   Check that no subset of B can be unified with the input
               }

4

パイソン、119 115 91

lambda a,b:[a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a))if a[m:m+n]not in b][0]

テストケース:

| Input 1  | Input 2     | Output        |
|----------+-------------+---------------|
| 'abcd'   | 'abc'       |  'd'          |
| 'abcd'   | 'dabc'      |  'cd'         |
| 'abcd'   | 'dcbabbccd' |  'abc'        |
| 'abcdf'  | 'abcdebcdf' |  'abcdf'      |
| 'abc'    | 'abc'       |  (IndexError) |

短くすることに取り組んでいますが、これは私の脳の本能です。まだゴルファーではありません。

余分なバイトを提供してくれた@ user81655と@NonlinearFruitに感謝します。

編集

ダン このコードを試しました:

def z(a,b):
 for s in [a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a)-n+1)]:
  if s not in b:return s
 return''

数バイト短いと思った。編集前よりも1バイト長かったことがわかりました。


私は多くのPythonを知りませんが、多分あなたは(r=range)(1,len(a)+1)それから使用できますrか?
コナーオブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴそんなことはできない。上記の行でに割り当てるranger、実際にバイトが追加されます。いい考えですが。おそらく、部分文字列を反復処理するより短い方法があります。
テイラーロペス

range(1,len(a))そしてrange(len(a)-1)それいけない動作するはず?また、2つのスペースのインデントにタブ文字を使用すると、1バイト節約できます。
user81655

いいえ、でrange(1,len(a))、4番目のテストキャストは完全な文字列を試行しないため失敗します。文字列の長さ-1だけになります。またrange(len(a)-1)、最初のテストケースでは、の'cd'代わりにが返されません'd'。ただし、何かあるかもしれません。
テイラーロペス

申し訳ありませんが、私はPythonに精通しておらず、範囲は包括的であると想定していました。その場合、してみてくださいrange(1,len(a)+1)range(len(a))
-user81655

3

Python、87 86バイト

lambda s,t,e=enumerate:[s[i:i-~j]for j,_ in e(s)for i,_ in e(s)if(s[i:i-~j]in t)<1][0]

存在する場合、これはすべての最も短い一意の部分文字列の左端を返します。

一意のサブストリングがない場合、IndexErrorが発生します。

Ideoneでテストします。


そこにそれがある。私は誰かが私の非ラムダ実装を殺すのを待っていました。素敵な笑
テイラーロペス

私はあなたがするオプションの第二引数供給することによって、この短いを作ることができると思いenumerateを開始するjにはi+1
user2357112は、Monica

@ user2357112 残念ながらNameErrorがスローされます。コードはj最初に定義してから、iです。
デニス

@デニス:ええ、しかし、それは必要ありません。ループの順序を切り替えることができます。
user2357112は、Monica

1
@ user2357112ループの順序を切り替えると、最初に見つかった一意の部分文字列が最短ではない場合があります。'ab'入力の順序を入れ替えるだけ'abc','aaa'です。
デニス

2

Python、82バイト

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}
f=lambda s,t:min(g(s)-g(t),key=len)

使用法:f('A&&C', 'A&$C')->リターン'&&'

適切なサブストリングがない場合、ValueErrorを送出します。

説明:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}のサブストリングのセットを再帰的に作成u f=lambda s,t:min(g(s)-g(t),key=len)し、セットの差から最も短いサブストリングを取得します


2

JavaScript(ES6)、79バイト

f=
(a,b)=>[...a].some((_,i,c)=>c.some((_,j)=>b.indexOf(s=a.substr(j,i+1))<0))?s:''
<div oninput=o.textContent=f(a.value,b.value)><input id="a"/><input id="b"/><pre id=o>

返すことfalseが許容される場合、の&&s代わりにを使用して2バイトを節約します?s:''



1

JavaScript(Firefox)、80バイト

solution=

a=>b=>[for(_ of(i=0,a))for(_ of(j=!++i,a))if(b.includes(s=a.substr(j++,i)))s][0]

document.write("<pre>"+
[ [ "test", "best" ], [ "wes", "west" ], [ "red", "dress" ] ]
.map(c=>c+": "+solution(c[0])(c[1])).join`\n`)

テストはFirefoxでのみ機能します。undefined部分文字列がない場合に返します。


文字列には、\やその他のRegExpメタ文字などの印刷可能なASCII文字を含めることができますが、Firefoxに限定する場合は、b.includes代わりに使用しないのはなぜですか
ニール

@Neil質問は、文字列が以前に任意の文字になる可能性があるとは言いませんでしたが、私に知らせてくれてありがとう!を使用するように更新されましたincludes
user81655

1
テストスニペットがスローされますSyntaxError: unexpected token 'for'
NoOneIsHere

@NoOneIsHereこれは、Firefoxを使用していない場合に表示されるエラーです
...-user81655

1

網膜、37バイト

M!&`\G(.+?)(?!.*¶.*\1)
O$#`.+
$.&
G1`

に有効なサブストリングが見つからない場合、出力は空ですA

オンラインでお試しください!(複数のテストケースを一度に実行するために少し変更されています。入力形式は実際には改行で区切られていますが、テストスイートは1行に1つのテストケースで記述するのが最も簡単です。テストフレームワークは実際のコードが開始する前にスペースを改行に変換します。)

説明

M!&`\G(.+?)(?!.*¶.*\1)

の可能な開始位置ごとにA、に表示されない最も短い部分文字列に一致しBます。これ&は、一致が1文字よりも長い場合でも、実際にすべての開始位置を試すように、重複する一致のためです。これ\Gにより、位置をスキップしないことが保証されます。特に、この方法では、ラインフィードで停止する必要があります。これにより、から追加の一致が得られないため、現在位置のさらに右から始まるすべての部分文字列が破棄されるため、これらは問題ではありません(実際にパフォーマンスが向上します)。Bそれ自体。これが混乱しない理由は実際には非常に微妙です:の開始位置がある場合A有効なサブストリングを見つけることができないある場合、それは\Gそれ以上の位置のチェックを停止する原因となる失敗でもあるためです。ただし、(現在の開始位置から)すべての部分文字列がB

M!構成により、これらの一致はすべてステージから返され、改行で結合されます。

O$#`.+
$.&

これにより、前の結果の行が長さでソートされます。これは、行をと一致させることによって行われ.+ます。次に$$.&ソート順を決定するために一致が置き換えられるように、「ソートバイ」のフォームをアクティブにします。$.&自体は、その長さとの一致を置き換えます。最後に、この#オプションはRetinaに数値でソートするように指示します(そうでない場合、結果の数値をストリングとして扱い、辞書式にソートします)。

G1`

最後に、grepステージに空の正規表現(常に一致する)とlimitを使用して、最初の行のみを保持し1ます。


1

Perl、 87 85

sub{(grep{$_[1]!~/\Q$_/}map{$}=$_;map{substr($_[0],$_,$})}@}}(@}=0..length$_[0]))[0]}

これは、で$_[0]発生しない$_[1]、またはundefそのようなサブストリングが存在しない場合に、最も短いサブストリングの最初の(位置による)を返す無名関数です。

Perl 5.22.1でテストされた@iAmMortosの回答から取得した文字列を使用してプログラムをテストします。

#!/usr/bin/perl -l
use strict;
use warnings;

my $f = <see above>;
print $f->('abcd', 'abc');
print $f->('abcd', 'dabc');
print $f->('abcd', 'dcbabbccd');
print $f->('abcdf', 'abcdebcdf');
print $f->('abc', 'abc');

1

Haskell、72バイト

import Data.Lists
a#b=argmin length[x|x<-powerslice a,not$isInfixOf x b]

使用例:"abcd" # "dabc"-> "cd"

簡単な実装:のすべての部分文字列を構築aし、に表示されない部分文字列を保持しbます。argminここで、2番目の引数が与えられた関数を最小化するリストの要素を返しますlength


知らなかったargmin!とても便利そうです。
ズガルブ

0

取り消し線9はまだ9

これがどのように機能するかを知りたいです。
mroman

@mroman the。:引数が1つの場合はすべてsubstrsです。それを両方の文字列にマッピングし、setwise diffを折りたたむので、最初のsubstrsが2番目の引数になり、最初の1つを選択します。これは最小のcuz。:がソートされます。
マルティセン

0

C#、152バイト

string f(string a,string b){int x=a.Length;for(int i=1;i<=x;i++)for(int j=0;j<=x-i;j++){var y=a.Substring(j,i);if(!b.Contains(y))return y;}return null;}

0

ルビー、70バイト

最初の文字列から特定の長さのすべての部分文字列を収集し、2番目の文字列にない部分文字列がある場合はそれを返します。

->a,b{r=p;(1..l=a.size).map{|i|(0...l).map{|j|b[s=a[j,i]]?0:r||=s}};r}

0

バーレスク-26バイト

今私が思いつくことができる最短の方法は:

lnp^sujbcjz[{^p~[n!}f[-][~

0

Japt、14バイト

Êõ!ãU c k!èV g

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

有効なサブストリングundefinedない場合に返します。これは、文字列「undefined」を返すこととは異なりますとは異なりますが、違いは-Qフラグのためにのみ表示されます。

説明:

Ê                 :Length of the first input
 õ                :For each number in the range [1...length]:
  !ãU             : Get the substrings of the first input with that length
      c           :Flatten to a single array with shorter substrings first
        k         :Remove ones which return non-zero to:
         !èV      : Number of times that substring appears in second input
             g    :Return the shortest remaining substring

0

Japt -h、11バイト

à f@øX «VøX

それを試してみてください

                :Implicit input of strings U & V
à               :All combinations of U
  f@            :Filter each as X
    øX          :  Does U contain X?
       «        :  Logical AND with the negation of
        VøX     :  Does V contain X?
                :Implicit output of last element
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.