Ortasında tekrar olmadan tekrar olmadan orijinal dizgiyi bulun


25

Bazen bir cümle yazarken, dikkatim dağılıyor ve sonunda aynı iki kelimeyi iki kez art arda iki kez yazıyordum.

Başkalarının bu konuda rahatsız olmadıklarından emin olmak için , sizin göreviniz bu sorunu çözen bir program yazmak!

Görev

Bir giriş dizesi verildiğinde (diliniz için önemliyse, satır beslemesi içermeyen yalnızca ASCII girişini kabul edebilirsiniz.) str , ortası bir yerde , Ortasındaki herhangi bir yerde, art arda iki kez meydana gelen bir alt dizeyi içeren, dizeyi bunun bir örneğiyle döndürün. substring kaldırıldı.

Birden fazla olasılık olması durumunda, mümkün olan en kısa cevabı döndürün (yani, en uzun ardışık yinelenen alt dizeyi seçin ve bunu kaldırın).

Birden fazla, aynı derecede uzun ardışık tekrarlayan alt diziler söz konusu olduğunda, ilkini (dize önden arkaya okurken ilk karşılaşılan) çıkarın.

Girişin doğru olduğunu varsayalım (yani her zaman ardışık tekrarlayan bir alt dize içerir), bu onu düşürmeye yardımcı olabilir.


Örnekler

  1. Giriş: hello hello world-> Çıkış:hello world .
  2. Giriş: foofoo-> Çıkış:foo . (Yani: Evet, dizi yalnızca iki kez tekrarlayan bölümden oluşabilir).
  3. Girdi: aaaaa-> Çıktı: aaaEn uzun tekrarlayan ardışık alt dize burada olduğundanaa .
  4. Giriş: Slartibartfast -> Bu geçerli bir giriş değildir, çünkü art arda tekrarlayan bir alt dize içermez, bu nedenle bu durumu ele almanıza gerek yoktur.
  5. Giriş: the few the bar-> Bu başka bir geçersiz giriş, çünkü yinelenen bölüm hemen orijinal bölümü takip etmelidir. Bu durumda thevethe bu giriş geçersiz nedenle, arada başka bir şey ile ayrılır.
  6. Girdi: ababcbc-> Çıktı: abcbc. Mümkün olan en uzun iki ardışık yinelenen alt dizge abve bc. Gibiab dizede daha erken karşılaşıldığında, bu bir doğru cevaptır.
  7. Girdi: Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. Çıktı: Buffalo buffalo buffalo buffalo Buffalo buffalo. (Yapılan değiştirme büyük / küçük harf duyarlı olmalıdır).
  8. Girdi: 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.-> Çıktı: Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Yalnızca en uzun ardışık yinelenen alt dize kaldırılır.

Kodunuz mümkün olduğu kadar kısa olmalıdır, çünkü bu olduğundan, bayt cinsinden en kısa cevap kazanır. İyi şanslar!


@manatwork İlk cümleyi alırken, bu 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.girdi gibidir, çıktı olmalıdır Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Yalnızca en uzun bulunan çoğaltma kaldırılır.
Qqwy

1
İkincisinin birincisinden daha uzun olduğu iki olası değişime sahip bir test eklemenizi öneriyorum. Yanıtların çoğunun bunu geçmeyeceğinden şüpheliyim :)
17:17

@aross test durumu 8 tam olarak böyle :)
Qqwy

Ben ve test kodum hatalı değilse, orada sadece bir tekrarlanan dize var.
saat

@ aross içinde bir çift pvarhappens
Qqwy

Yanıtlar:



8

Retina , 35 33 bayt

Bayt sayısı, ISO 8859-1 kodlamasını varsayar.

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

Çevrimiçi deneyin!

açıklama

Regex motorları soldan sağa doğru eşleşmeler aradığından, pozisyondan bağımsız olarak en uzun eşleşmeyi bulmak önemsiz değildir. .NET'in dengeleme grupları ile yapılabilir, ancak sonuç oldukça nahoş bir şekilde:

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

Bu yüzden diğer Retina özelliklerinden yararlanarak bundan kaçınmaya çalışacağımı düşündüm.

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

Her satırda bir tane olmak üzere tüm olası ikameleri esas olarak uygulayarak başlıyoruz . Bunu yapmak için, üst üste gelen eşleşmelere izin vermek için eşleşmenin karşısındaki konumu (eşleşmenin kendisi yerine) eşleştiririz. Bu, gerçek regex'i bir gözetleme kafasına koyarak yapılır. Bu bakış, daha sonra grup 2'de kaldırmak istediğimiz kopya dışında kalanı yakalar. Grup 2'yi (kopyayı silme), bir satır beslemesi ve ardından eşleşmeye kadar olan tüm girdiyi bize geri gönderir. ikame edilebilir.

Sonunda her eşleşme için bir satır olacak ve karşılık gelen kopya kaldırıldı. Sonunda da herhangi bir değişiklik yapılmadan tekrar tam girdi olacak.

Artık tüm olası oyuncu değişimlerine sahip olduğumuza göre, en kısa sonucu (en uzun kaldırılan tekrarlamaya karşılık gelir) istiyoruz.

O$#`
$.&

Bu yüzden önce çizgileri boyuna göre sıralarız.

G1`

Ve sonra sadece ilk satırı koruruz.


Vay, bu değiştirme tekniği gerçekten zekice!
Leo

6

Jöle , 22 19 bayt

Dennis sayesinde -2 byte (argümanı tersine çevirmekten kaçının, gereksiz fazlalığı kaldırın)

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

Çevrimiçi deneyin!

Tam program ( ÐṀyakında düzeltilecek olan dyads üzerinde doğru ariteyle hareket etmemekte bir hata bulundu ; burada daha kısa kod yapabileceğinden emin değilim).

Nasıl?

Girdinin en uzun dilimlerinden ilkini girişte bir yineleme olacak şekilde bulur ve girişten kaldırır.

ẋ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 bayt

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>

Düzenleme: @ Arnauld's m[r.length]hilesini çalarak 7 bayt kurtardı .


5

Güç kalkanı , 87 bayt

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

Çevrimiçi deneyin! (tüm test durumları)

açıklama

Temelden içeriden başlayarak koşuyoruz Matches(.+)\1 , belirtilen dizge için tüm eşleşme nesnelerini döndürmek için regex ile . Düzenli ifade, kendisi tarafından takip edilen tüm karakter dizileriyle eşleşir.

Daha sonra ortaya çıkan eşleşme nesneleri sortkendi Lengthözelliklerine göre sıralanır (joker karaktere göre kısaltılır). Bu, uzunluğa göre sıralanmış artan bir dizi eşleşmesiyle sonuçlanır, bu nedenle yöntemle indeks orijinal dizeye karşı çağrılır, hiçbir şey olmadan değiştirilir ve yalnızca ilk eşleşme değiştirilir ( ).[-1] ve son öğeyi (en uzun olanı) almak için . Bu eşleşmenin değeri grup değil, eşleşmedir, bu yüzden tekrarı içerir, bu yüzden en büyük tekrarlanan dizgiyi elde etmek için Grup nesnesini ( |% Gr*) ve sonra da ( |% V*) değerini alırız . Şey, grup nesnesi aslında bir dizidir, çünkü grup 0 her zaman eşleşir, ama ben gerçek grubun (1) olmasını istiyorum, bu nedenle sonuçta elde edilen değer aslında değer s dolayısıyla ikinci eleman elde etmek için dizine,[1] . Bu değer bir regex nesnesinin kendisine ve sonraReplace|% Re* $s '' 1


5

Haskell , 101 bayt

Ana işlevi, fa alır ve döndürür 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

Çevrimiçi deneyin!

Bunu başladığımda, ithal Data.Listve kullanılmış maximum, tails, initsve isPrefixOf. Bir şekilde , buna dönüşmüş. Ama ben hala sadece 11 byte tıraş etmeyi başardım ...

notlar

  • splitAt/a verilen dizinde bir dize böler.
  • s Giriş dizesidir.
  • inumaraların listesi [0 .. length s - 1], -1bu geçici bir çözüm sağlamaktır splitAtsonunda böler bir çok büyük endeksi verilirse.
  • nedilir length seksi akım uzunluğu kale tekrarlanan kısmı için, bu şekilde seçti biz liste sözdizimi azalan ayrıntılı iki sayı listeleri ve / veya kullanmak zorunda kalmamak.
  • p, rve amaçlanan tekrarlanan kısım ile birlikte , tüçlü bir bölünmedir . orada kullanırsrfmap(,) String Functor bir ara bölme için bir değişken önlemek için.
  • !!0 eşleşme listesinin ilk elemanını seçer.


4

Mathematica, 63 60 59 bayt

Martin Ender nedeniyle 4 bayt kaydedildi .

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

Anonim işlev Bir dizeyi girdi olarak alır ve dizeyi çıktı olarak döndürür.


Bu, örnek 6'da işe yaramıyor gibi görünmüyor - ~SortBy~StringLengthuzunlukları aynı ise, dizeleri alfabetik olarak sıralar ...
Bir ağaç değil

1
@ LegionMammal978 Kısa düzeltme, sabit bir sıralama elde etmek için bir listede saklamak SortByve sarılmaktır StringLength.
Martin Ender

3

JavaScript (ES6), 70 bayt

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

Test durumları


Başarısız aaaabaaab, ama güzel kullanım reduce.
Neil

2

Bu bir yorum olmalı, ancak yorum yapacak kadar itibarım yok. Sadece @ Neil'e kodunun 77 bayta indirilebileceğini söylemek istiyorum. Regex'te ileri iddia kullanmanıza gerek yoktur. İşte azaltılmış versiyonu:

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

2
Merhaba, PPCG'ye hoş geldiniz! Bunu kendi JavaScript cevabınız olarak gönderebilirsiniz! İsterseniz yayınınızı düzenleyebilir ve nasıl görünmesi gerektiğini size gösterebilirim.
NoOneIsHere

2
Örtüşen maçlarla başa çıkmak için ileriye dönük bir iddia kullanmam gerekiyor. aababönerinizin başarısızlığa uğradığı en kısa örnektir.
Neil

0

C #, 169 bayt

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

açıklama

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

Bu kaba kuvvet yaklaşımıdır: en uzun yinelenen altlığı bulana kadar mümkün olan her alt dizgiyi deneyin. Kuşkusuz Regex daha verimlidir, fakat C # 'daki Regex ile başa çıkmak oldukça ayrıntılı olma eğilimindedir.


PPCG'ye Hoşgeldiniz! Tüm cevapların tam programlar veya çağrılabilir işlevler olması gerekir ; kodlanmış değişkenlerde girdili snippet'lerden emin değil. Ayrıca, gerçekten gereksiz tüm boşluklar kaldırılmış olarak saydığınız kodun sürümünü de gösteriniz. Tamamen golf süresinin yanı sıra her zaman daha okunabilir bir sürümü girintili olarak ekleyebilirsiniz.
Martin Ender

0

PHP, 84 82 bayt

Not: IBM-850 kodlamasını kullanır.

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

Bu şekilde koş:

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

açıklama

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.

Düzenlemeler

  • 2 bayt kaydedildi, çünkü tekrarlanan alt dizenin minimum uzunluğu yok
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.