文字列が双子のシャッフルであるかどうかを確認する


10

説明

2枚のカードの山をシャッフルして1枚の山を作るのと同じように、2つの文字列を混ぜて新しい文字列を形成します。

例えば、文字列HELLOとをWORLD形成するようにシャッフルすることができHWEOLRLLOD、またはHEWORLLLDO恐らく単に、又はHELLOWORLD

それはない文字の元の順序が保存されていない場合はシャッフル。たとえば、シャッフルされた後、DインWORLDが表示されることはありませんR。これはEHLLOWRDLO、たとえば、元の文字がすべて含まれていても、HELLOとのシャッフルではないことを意味しますWORLD

ストリングは、2つの同一ストリングをシャッフルして形成できる場合、双子のシャッフルです。たとえばABACBDECDE、双子のシャッフルは、シャッフルABCDEやで形成できるためABCDEです。DBEACBCADE2つの同一の文字列をシャッフルして形成できないため、双子のシャッフルではありません。

プログラムの詳細

入力文字列を指定して、0双子のシャッフルでない場合は出力し、双子のシャッフルである場合は双子文字列の1つを出力します。

入力文字列は4文字から20文字までの長さで、すべて大文字のアルファベット文字で構成されていると想定できます。妥当な時間、たとえば10分未満で実行できるはずです。

これはコードゴルフなので、最短のソリューションが優先されます。

I / Oの例

> ABACBDECDE
ABCDE

> DBEACBCADE
0

> FFFFFF
FFF

> FFGGG
0

> ABBA
0

> AABB
AB

> AABAAB
AAB

(ゴルフではない)実装例があります


文字列の例FGGはアサーションthat the input string has a length inclusively between four and twenty charactersに違反しており、「ユーザー入力を決して信頼しない!」、「仕様を決して信頼しない!」
ユーザー不明

@userunknown恥ずかしいです!FFGGG一貫性を持たせるために編集しました。
Peter Olson

1
ちょうど好奇心から、指数関数的な最悪の場合の時間の複雑さを備えたソリューションを思い付くことができますか、それとも存在しないことを証明できますか?
Ilmari Karonen、2011

回答:


4

Haskell、114

main=getLine>>=putStrLn.f.p;f x=head$[a|(a,b)<-x,a==b]++["0"]
p[]=[([],[])];p(x:y)=do(a,b)<-p y;[(x:a,b),(a,x:b)]

非ゴルフ:

main :: IO ()
main = getLine >>= putStrLn . findMatch . partitions

-- | Find the first partition where the two subsequences are
-- equal. If none are, return "0".
findMatch :: [(String, String)] -> String
findMatch ps = head $ [a | (a,b) <- ps, a == b] ++ ["0"]

-- | Return all possible partitions of the input into two
-- subsequences. Preserves the order of each subsequence.
--
-- Example:
-- partitions "AB" == [("AB",""),("B","A"),("A","B"),("","AB")]
partitions :: [a] -> [([a], [a])]
partitions []     = [([], [])]
partitions (x:xs) = do (a, b) <- partitions xs
                       [(x:a, b), (a, x:b)]

説明:

ほとんどの作業はpartitions関数内で行われています。(a, b)リストの末尾のすべてのパーティションを再帰的に生成し、リストモナドを使用しxてそれぞれに先頭要素を付加し、すべての結果を収集することで機能します。

findMatchこのリストをフィルタリングすることで機能し、サブシーケンスが等しいパーティションのみが残るようにします。次に、最初のパーティションの最初のサブシーケンスを返します。何も残っていない場合、リストは空なので"0"、最後に追加されたものが代わりに返されます。

main 入力を読み取り、これら2つの関数を介してフィードし、出力するだけです。


Haskellが読めない私たちに説明をお願いします。
Mr.Wizard

1
@ Mr.Wizard:編集を参照してください。
hammar 2011

短くはありませんが、かなり似たものを思いついたと思いますが、私はそれを完全な失敗に終わった愚かな種類のものを投げました。Mathematicaでこのアルゴリズムを実装してもよろしいですか?
Mr.Wizard、2011

4

R、113文字

l=length(x<-charToRaw(scan(,'')));max(apply(combn(l,l/2),2,function(i)if(all(x[i]==x[-i]))rawToChar(x[i])else 0))

Ungolfed(代わりに文字列を受け取る関数):

untwin <- function(x) {
  x <- charToRaw(x)
  indMtx <- combn(length(x),length(x)/2)
  res <- apply(indMtx, 2, function(i) {
    if (all(x[i]==x[-i]))
      rawToChar(x[i])
    else
      0
  })
  max(res)
}

untwin("ABACBDECDE") # "ABCDE"
untwin("DBEACBCADE") # 0

ソリューションはcombn、行列の列としてインデックスのすべての組み合わせを生成する関数に依存しています。apply次に、関数を2行列の各列(次元)に適用し、文字列またはゼロのベクトルを返します。max次に、最大の文字列(0に勝る)を見つけます。

Rの優れた機能は、インデックスのベクトルが指定されたベクトルのサブセットを選択し、インデックスを無効にすることでそのサブセットの集合を選択する機能です。x[i] == x[-i]


いくつかの漸進的な改善と文字数の削減を行いました。
Tommy

3

Mathematica、87

これはハンマーの投稿に直接基づいていますが、うまくいけば投稿に値するほど十分に明確です。

<<Combinatorica`

f=Catch[Cases[Characters@#~KSetPartitions~2,{x_,x_}:>Throw[""<>x]];0]&

テスト:

f /@ {"ABACBDECDE", "DBEACBCADE", "FFFFFF", "FGG", "ABBA", "AABB", "AABAAB"}
{「ABCDE」、0、「FFF」、0、0、「AB」、「AAB」}

1

D

string c(string in,string a=[],string b=[]){
    if(in.length==0)return a==b?a;"0";
    auto r=c(in[1..$],a~in[0],b);
    return r=="0"?c(in[1..$],a,b~in[0]):r;
}
void main(){writeln(c(readline));}

深さ優先再帰検索の使用

int i = min(a.length,b.length);if(a[0..i]!=b[0..i])return "0";ガード句を使って速くすることができます


IDEONEで、プログラムを起動しようとして失敗しましたvoid main(){writeln(c("ABCADABCAD"));}-異なるバージョンのD、私のせい、他に何かありますか?「ABCABCA」とは?
ユーザー不明

std.stdioをインポートする必要があります。IOのため
ラチェットフリーク

1

ルビー、89文字

s=->a,x,y{a=="\n"?x==y ?x:?0:[s[b=a[1..-1],x+c=a[0],y],s[b,x,y+c]].max}
$><<s[gets,'','']

このコードは、単純な再帰検索アルゴリズムを実装しています。入力はSTDINで指定する必要があります。


1

Perl、68文字

/^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0

$_変数内にあると想定される入力文字列、出力は式の値です。入力の末尾の改行は無視されます。これは、次のようにコマンドラインから実行できます。

perl -lne 'print /^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0'

このコードは、Perlのregexpエンジン(特にその埋め込みコード実行機能)を利用してバックトラックを行います。基本的には、正規表現に対する入力文字列と一致する^((.+))+$に奇数と偶数サブマッチを追跡し、$xそして$,、二つが等しくない場合は末尾に一致を拒絶します。


これは正しい結果AABAABですか?
Peter Olson

はい、そうです。(実際にAABAABは、外側のグループが2回一致する必要があるだけなので、このソリューションの簡単なケースです。AABB正しく処理するのにかなり時間がかかりました。)
Ilmari Karonen

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