中央の繰り返しなしで、繰り返しなしで元の文字列を見つけます


25

文を入力しているときに気が散ってしまい、同じ単語を2回、単語を2回続けて入力してしまうことがあります。

確かめる 他の人がこれに悩まされないするために、あなたの仕事はこの問題を解決するプログラムを書くことです!

仕事

入力文字列を指定します(言語にとって重要な場合は、改行を含まないASCIIのみの入力を想定できます。) str、中間に2回連続して発生する部分文字列が含まれ、このインスタンスを1つ持つ文字列を返します部分文字列が削除されました。

複数の可能性がある場合は、可能な限り最短の回答を返します(つまり、連続する最長の繰り返し部分文字列を選択して削除します)。

複数の同じ長さの連続する繰り返し部分文字列の場合、最初の(つまり、文字列を前後に読んでいるときに最初に現れる)部分文字列を削除します。

入力が正しい(つまり、連続した繰り返し部分文字列が常に含まれている)と想定することもできます。


  1. 入力:hello hello world->出力:hello world
  2. 入力:foofoo->出力:foo。(そのため、はい、文字列は繰り返し部分で2回だけ構成されます)。
  3. 入力:aaaaa->出力:aaa、最も長い繰り返し連続部分文字列がここにあるためaa
  4. 入力:Slartibartfast->これは有効な入力ではありません。連続する繰り返し部分文字列が含まれていないため、このケースを処理する必要はありません。
  5. 入力:the few the bar->これは別の無効な入力です。これは、繰り返し部分が元の部分の直後に続く必要があるためです。この場合、theおよびtheそれらの間の何かで区切られているため、この入力は無効です。
  6. 入力:ababcbc->出力:abcbc。2つの可能な最長の連続した繰り返し部分文字列があるabbc。としてab以前の文字列で発生した、これは正解です。
  7. 入力:Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo。出力:Buffalo buffalo buffalo buffalo Buffalo buffalo。(実行される置換では、大文字と小文字が区別されます)。
  8. 入力:Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.->出力:Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.。最長の連続する繰り返し部分文字列のみが削除されます。

これはであるため、はできるだけ短くする必要があります。そのため、バイト単位の最短回答が優先されます。がんばろう!


@manatwork最初の文Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.を入力するとき、つまり入力として、出力はである必要がありますSometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.。見つかった最長の重複のみが削除されます。
Qqwy

1
2つの代替が可能なテストを追加することをお勧めします。2番目の代替は最初の代替よりも長くなります。ほとんどの答えはそれを通過しないと思う:)
アロス

@arossテストケース8は、まさにそれです:)
Qqwy

私と私のテストコードが間違っていない限り、そこに繰り返される文字列は1つだけです。
アロス

@arossダブルがありますphappens
Qqwy

回答:



8

網膜35 33バイト

バイトカウントはISO 8859-1エンコードを前提としています。

(?=(.+)(\1.*))
$2¶$`
O$#`
$.&
G1`

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

説明

正規表現エンジンは左から右に一致を探すため、位置に関係なく最長一致を見つけるのは簡単ではありません。.NETのバランスグループを使用して実行できますが、結果はかなり不愉快に長くなります。

1`((.)+)\1(?<=(?!.*((?>(?<-2>.)+).+)\3)^.*)
$1

だから私は、他のRetina機能を利用することでそれを回避しようと考えた。

(?=(.+)(\1.*))
$2¶$`

基本的にすべてを適用することから始めます考えられる置換を各行に1つずつます。これを行うには、重複する一致を許可するために、一致の代わりに一致の前の位置を一致させます。これは、実際の正規表現を先読みすることによって行われます。その先読みは、グループ2で削除する重複を除いて残りをキャプチャします。グループ2(重複を削除)、改行、そして入力までの全体を書き戻します。置換されます。

最後に、一致ごとに1行を作成し、対応する重複を削除します。最後に、置換を行わずに完全な入力が再び行われます。

可能なすべての置換ができたので、最短の結果(削除された最長の繰り返しに対応)が必要です。

O$#`
$.&

そこで、最初に行を長さでソートします。

G1`

そして、最初の行のみを保持します。


うわー、その交換手法は本当に賢いです!
レオ

6

ゼリー22 19 バイト

Dennisのおかげで-2バイト(引数の反転を避け、わずかに冗長な増分を削除します)

ẋ2³wȧ+¥J
ẆÇ€LÐṀḢṬœp

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

完全なプログラム(バグが発見されました ÐṀダイアドに対して正しいアリティで動作ない。これは間もなく修正されます。ただし、ここでコードを短くできるかどうかません)。

どうやって?

入力に繰り返しが存在するように、入力の最も長いスライスの最初を見つけて、それを入力から削除します。

ẋ2³wȧ+¥J - Link 1, removal indices for given slice if valid, else 0: slice, x
ẋ2       - repeat x twice, say y
  ³      - program input: s
   w     - index of first occurrence of y in s (1-based) or 0, say i
       J - range(length(x)): [1,2,3,...,length(x)]
      ¥  - last two links as a dyad
    ȧ    -     and (non-vectorising)
     +   -     addition: [1+i,2+i,3+i,...,length(x)+i] or 0
         - note: no need to decrement these since the last index will be the 1st index
         - of the repetition (thanks to Dennis for spotting that!)

ẆÇ€LÐṀḢṬœp - Main link: string, s
Ẇ          - all sublists of s (order is short to long, left to right, e.g. a,b,c,ab,bc,abc)
 Ç€        - call the last link (1) as a monad for €ach
    ÐṀ     - filter by maximal
   L       -     length
      Ḣ    - head: get the first (and hence left-most) one
       Ṭ   - untruth: make a list with 1s at the indexes given and 0s elsewhere
        œp - partition s at truthy indexes of that, throwing away the borders
           - implicit print

6

JavaScript(ES6)、81 74バイト

f=
s=>s.replace(/(?=(.+)\1)/g,(_,m)=>r=m[r.length]?m:r,r='')&&s.replace(r,'')
<input oninput=o.textContent=f(this.value)><pre id=o>

編集:@Arnauldのm[r.length]トリックを盗んで7バイトを保存しました。


5

PowerShell、87バイト

param($s)([regex](([regex]'(.+)\1'|% *hes $s|sort L*)[-1]|% Gr*|% V*)[1])|% Re* $s '' 1

オンラインでお試しください!(すべてのテストケース)

説明

基本的に内側から始めMatchesて、(.+)\1て、指定された文字列のすべての一致オブジェクトを返すために正規表現でます。正規表現は、その後に続く任意の文字シーケンスと一致します。

次に、結果の一致オブジェクトがパイプされsortて、それらのLengthプロパティによってソートされます(ワイルドカードに短縮されます)。これにより、一致する配列が長さで昇順でソートさ[-1]れるため、最後の要素(最長)を取得するためのインデックスが付けられます。ただし、その一致の値はグループではなく一致であるため、繰り返しが含まれているため、Groupオブジェクト(|% Gr*)を取得し、その値(|% V*)を取得して、最大の繰り返し文字列を取得します。グループ0は常に一致するため、グループオブジェクトは実際には配列ですが、実際のグループ(1)が必要なので、結果の値は実際には値sであるため、2番目の要素を取得するためにインデックス付けされます[1]。この値は正規表現オブジェクト自体にキャストされ、次にReplaceメソッドは元の文字列に対して呼び出され、何も置き換えられず、最初の一致のみが置き換えられます(|% Re* $s '' 1)。


5

Haskell、101バイト

主な機能はf、を取得して返しますString

l=length
a=splitAt
f s|i<-[0..l s-1]=[p++t|n<-i,(p,(r,t))<-fmap(a$l s-n).(`a`s)<$>i,r==take(l r)t]!!0

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

私はこれを始めたとき、私は輸入Data.Listおよび使用maximumtailsinitsisPrefixOfどういうわけか、それはこれに変わりました。しかし、私はまだ11バイトを削ることしかできませんでした...

ノート

  • splitAt/ aは、指定されたインデックスで文字列を分割します。
  • s 入力文字列です。
  • i番号のリストです[0 .. length s - 1]、それ-1を回避することですsplitAt最後の分割が大きすぎるインデックスを与えられている場合。
  • nlength s、繰り返し部分の現在の長さの目標を引いたものであり、そのように選択されているため、2つの数値リストや冗長な減少リスト構文を使用する必要はありません。
  • prtの3Pプレイ分割されているsと、r繰り返しの部分を意図。をfmap使用し(,) String Functorて、中間分割の変数を回避します。
  • !!0 一致リストの最初の要素を選択します。


4

Mathematica、63 60 59バイト

Martin Enderのために4バイト節約されました。

#&@@StringReplaceList[#,a__~~a__->a]~SortBy~{StringLength}&

匿名関数。入力として文字列を受け取り、出力として文字列を返します。


これは、例えば6上で動作するようには思えない- ~SortBy~StringLengthそれらの長さが同じ場合はアルファベット順に並べ替え列...
未木

1
@ LegionMammal978短い修正方法は、リストを保持SortByおよびラップStringLengthして、安定したソートを取得することです。
マーティンエンダー

3

JavaScript(ES6)、70バイト

s=>s.replace(s.match(/(.+)(?=\1)/g).reduce((p,c)=>c[p.length]?c:p),'')

テストケース


失敗しaaaabaaabますが、うまく使用しreduceます。
ニール

2

これはコメントのはずですが、コメントするほどの評判はありません。@Neilに、彼のコードを77バイトに減らすことができることを伝えたいだけです。正規表現でフォワードアサーションを使用する必要はありません。縮小版は次のとおりです。

s=>s.replace(/(.+)\1/g,(_,m)=>(n=m.length)>l&&(l=n,r=m),l=0)&&s.replace(r,'')

2
こんにちは、PPCGへようこそ!これを独自のJavaScript回答として送信できます。必要に応じて、投稿を編集し、どのように表示されるかを示します。
-NoOneIsHere

2
重複する一致の場合に対処するには、前方アサーションを使用する必要があります。aababは、提案が失敗した最短の例です。
ニール

0

C#、169バイト

(s)=>{var x="";for(int i=0;i<s.Length-2;i++){for(int l=1;l<=(s.Length-i)/2;l++){var y=s.Substring(i,l);if(s.Contains(y+y)&l>x.Length)x=y;}}return s.Replace(x+x,x);}

説明

(s) => {                // Anonymous function declaration    
    var x = "";         // String to store the longest repeating substring found
    for (int i = 0; i < s.Length - 2; i++) {               // Loop through the input string
        for (int l = 1; l <= (s.Length - i) / 2; l++) {    // Loop through all possible substring lengths
            var y = s.Substring(i, l);
            if (s.Contains(y + y) & l > x.Length) x = y;   // Check if the substring repeats and is longer than any previously found
        }
    }
    return s.Replace(x + x, x);    // Perform the replacement
}

これはブルートフォースアプローチです。最も長い繰り返し部分文字列が見つかるまで、可能なすべての部分文字列を試します。間違いなく正規表現の方が効率的ですが、C#で正規表現を扱うのはかなり冗長になる傾向があります。


PPCGへようこそ!すべての答えは、完全なプログラムまたは呼び出し可能な関数である必要があり、ハードコードされた変数に入力があるスニペットではありません。また、不要な空白をすべて削除して、実際にカウントしたコードのバージョンを表示してください。完全にゴルフされたものに加えて、インデント付きの読みやすいバージョンをいつでも含めることができます。
マーティンエンダー

0

PHP、84 82バイト

注:IBM-850エンコードを使用します。

for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;

次のように実行します:

echo 'hello hello world' | php -nR 'for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;';echo
> hello world

説明

for(
  $l=strlen($argn);   # Set $l to input length.
  --$l   &&           # Decrement $l each iteration until it becomes 0.
  !$r=preg_filter(    # Stop looping when preg_filter has a result
                      # (meaning a successful replace).
    "#(.{0$l})\g-1#", # Find any character, $l times (so the longest
                      # match is tried first), repeated twice.
    ~█╬,              # Replace with $1: first capture group, removing the
                      # duplicate.
    $argn,
    1                 # Only replace 1 match.
  );
);
echo$r;               # Print the result of the (only) successful
                      # search/replace, if any.

微調整

  • 繰り返される部分文字列の最小長がないため、2バイトを節約しました
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.