Temukan string asli, tanpa pengulangan tanpa pengulangan di tengah

25

Kadang-kadang terjadi bahwa ketika mengetik kalimat, saya terganggu dan saya akhirnya mengetik pasangan kata yang sama dua kali pasangan kata dua kali berturut-turut.

Untuk memastikan make yakin orang lain tidak terganggu oleh ini, tugas Anda adalah untuk menulis sebuah program yang menyelesaikan masalah ini!

Tugas

Diberikan string input (jika itu penting untuk bahasa Anda, Anda dapat mengasumsikan input ASCII saja yang tidak mengandung linefeeds.) str, Yang mengandung suatu substring di suatu tempat di tengahnya yang terjadi dua kali berturut-turut segera, kembalikan string dengan satu contoh dari ini substring dihapus.

Dalam hal beberapa kemungkinan, kembalikan jawaban sesingkat mungkin (yaitu, pilih substring berulang berurutan dan hapus yang itu).

Dalam hal beberapa substring berulang yang sama-sama panjang, hapus substring pertama (yaitu, yang pertama ditemukan saat membaca string dari depan ke belakang).

Anda dapat mengasumsikan bahwa inputnya benar (yaitu selalu berisi substring berulang berurutan), yang dapat membantu menurunkannya.


Contohnya

  1. Input: hello hello world-> Output: hello world.
  2. Input: foofoo-> Output: foo. (Jadi: Ya, string hanya terdiri dari bagian berulang dua kali).
  3. Input: aaaaa-> Output:, aaakarena substring berulang berulang terpanjang ada di sini aa.
  4. Input: Slartibartfast-> Ini bukan input yang valid, karena tidak mengandung substring berulang berturut-turut, sehingga Anda tidak perlu menangani kasus ini.
  5. Input: the few the bar-> Ini adalah input lain yang tidak valid, karena bagian berulang harus segera mengikuti bagian asli. Dalam hal ini, thedan thedipisahkan oleh sesuatu yang lain di antara keduanya, maka input ini tidak valid.
  6. Input: ababcbc-> Output: abcbc. Dua substring berulang berulang terpanjang yang mungkin adalah abdan bc. Seperti abyang ditemukan sebelumnya dalam string, ini adalah jawaban yang benar.
  7. Input: Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. Output: Buffalo buffalo buffalo buffalo Buffalo buffalo. (Penggantian yang dilakukan harus peka terhadap huruf besar-kecil).
  8. Input: 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.-> Output: Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Hanya substring berulang berulang terpanjang yang dihapus.

Kode Anda harus sesingkat mungkin, karena ini adalah , jadi jawaban tersingkat dalam byte menang. Semoga berhasil!

Qqwy
sumber
@manatwork Saat mengambil kalimat pertama, yaitu 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.sebagai input, hasilnya harus Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Hanya duplikasi yang paling lama ditemukan yang dihapus.
Qqwy
1
Saya sarankan menambahkan tes yang memiliki dua kemungkinan penggantian, di mana yang kedua lebih panjang dari yang pertama. Saya menduga sebagian besar jawaban tidak akan melewati yang itu :)
aross
@aross test case 8 persis seperti itu :)
Qqwy
Kecuali saya dan kode pengujian saya salah, hanya ada satu string yang berulang di sana.
aross
@ Aross ada dobel p dihappens
Qqwy

Jawaban:

8

Perl 6 , 40 byte

{.subst: m:ex/(.*))>$0/.max(*.chars),''}

Cobalah

{
  .subst:             # substitute


    m                 # match
    :exhaustive
    /
      ( .* )          # any number of chars

      )>              # don't include the following in what is returned

      $0              # the first match again
    /.max( *.chars ), # find the first longest submatch


    ''                # substitute it with nothing
}
Brad Gilbert b2gills
sumber
8

Retina , 35 33 byte

Hitungan byte mengasumsikan penyandian ISO 8859-1.

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

Cobalah online!

Penjelasan

Karena mesin regex mencari kecocokan dari kiri ke kanan, bukan hal yang sepele untuk menemukan kecocokan terpanjang terlepas dari posisi. Itu bisa dilakukan dengan grup penyeimbang .NET, tetapi hasilnya agak lama tidak menyenangkan:

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

Jadi saya pikir saya akan mencoba menghindarinya dengan memanfaatkan beberapa fitur Retina lainnya.

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

Kami mulai dengan menerapkan dasarnya semua kemungkinan penggantian, satu pada setiap baris. Untuk melakukan ini, kami mencocokkan posisi di depan pertandingan (bukan pertandingan itu sendiri), untuk memungkinkan pertandingan yang tumpang tindih. Ini dilakukan dengan menempatkan regex yang sebenarnya ke dalam lookahead. Penampilan itu kemudian menangkap sisanya kecuali duplikat yang ingin kami hapus di grup 2. Kami menulis kembali grup 2 (menghapus duplikat), sebuah linefeed, dan kemudian seluruh input hingga pertandingan, yang pada dasarnya memberi kami garis baru untuk diganti

Pada akhirnya kami akan memiliki satu baris untuk setiap pertandingan, dengan duplikat yang sesuai dihapus. Pada akhirnya juga akan ada input penuh lagi tanpa ada penggantian.

Sekarang kami memiliki semua pergantian yang mungkin, kami menginginkan hasil terpendek (yang sesuai dengan pengulangan yang paling lama dihapus).

O$#`
$.&

Jadi kita pertama-tama mengurutkan garis berdasarkan panjangnya.

G1`

Dan kemudian kita hanya menjaga baris pertama.

Martin Ender
sumber
Wow, teknik penggantian itu sangat pintar!
Leo
6

Jelly , 22 19 byte

-2 byte terima kasih kepada Dennis (hindari pembalikan argumen, hapus kenaikan berlebihan yang sedikit)

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

Cobalah online!

Program lengkap (bug telah ditemukan bersama ÐṀ tidak bertindak dengan arity yang benar di atas angka dua, yang akan segera diperbaiki; meskipun saya tidak yakin itu bisa membuat kode lebih pendek di sini).

Bagaimana?

Temukan irisan terpanjang pertama dari input sedemikian sehingga pengulangan ada di input dan menghapusnya dari input.

ẋ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
Jonathan Allan
sumber
6

JavaScript (ES6), 81 74 byte

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>

Sunting: Disimpan 7 byte dengan mencuri m[r.length]trik @ Arnauld .

Neil
sumber
5

PowerShell , 87 byte

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

Cobalah online!(semua kasus uji)

Penjelasan

Mulai dari dalam pada dasarnya, kita jalankan Matchesdengan(.+)\1 regex, untuk mengembalikan semua objek yang cocok untuk string yang ditentukan. Regex cocok dengan urutan karakter apa pun yang diikuti dengan sendirinya.

Kemudian objek pertandingan yang dihasilkan disalurkan ke sortuntuk diurutkan berdasarkan Lengthpropertinya (disingkat menjadi wildcard). Ini menghasilkan array pertandingan yang diurutkan berdasarkan panjang, naik, jadi indeks dengan [-1]untuk mendapatkan elemen terakhir (terpanjang). Nilai kecocokan itu adalah kecocokan, bukan grup, jadi itu termasuk pengulangan, jadi kami mengambil objek Grup ( |% Gr*) dan kemudian nilai itu ( |% V*) untuk mendapatkan string berulang yang terbesar. Masalahnya adalah objek grup sebenarnya array karena grup 0 selalu cocok, tetapi saya ingin grup yang sebenarnya (1), jadi nilai yang dihasilkan adalah nilai s , maka pengindeksan untuk mendapatkan elemen kedua [1]. Nilai ini dicor ke objek regex itu sendiri dan kemudianReplaceMetode dipanggil terhadap string asli, diganti dengan tidak ada, dan hanya pertandingan pertama yang diganti ( |% Re* $s '' 1).

briantis
sumber
5

Haskell , 101 byte

Fungsi utamanya adalah f, dibutuhkan dan mengembalikan a 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

Cobalah online!

Ketika saya mulai ini, saya diimpor Data.Listdan digunakan maximum, tails, initsdan isPrefixOf. Entah bagaimana itu berubah menjadi ini. Tapi saya hanya berhasil memotong 11 byte ...

Catatan

  • splitAt/ amembagi string pada indeks yang diberikan.
  • s adalah string input.
  • iadalah daftar angka [0 .. length s - 1], -1adalah untuk bekerja di sekitar yang splitAtterbagi pada akhirnya jika diberi indeks terlalu besar.
  • nadalah length sminus tujuan panjang saat ini untuk bagian diulang, itu memilih jalan itu sehingga kita tidak perlu menggunakan dua daftar jumlah dan / atau verbose menurun daftar sintaks.
  • p,, rdan tmerupakan pemecahan tiga jalur s, dengan rbagian yang diulang yang dimaksud. Di fmapsana menggunakan (,) String Functoruntuk menghindari variabel untuk pemisahan menengah.
  • !!0 memilih elemen pertama dari daftar kecocokan.
Ørjan Johansen
sumber
4

Jelly , 23 21 byte

ṚẆUẋ€2ẇÐf¹ṪðLHḶ+w@Ṭœp

Terima kasih kepada @JonathanAllan untuk Ṭœpidenya yang menyelamatkan 2 byte.

Cobalah online!

Dennis
sumber
4

Mathematica, 63 60 59 byte

4 byte disimpan karena Martin Ender .

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

Fungsi anonim. Mengambil string sebagai input dan mengembalikan string sebagai output.

LegionMammal978
sumber
Ini sepertinya tidak berfungsi pada contoh 6 - ~SortBy~StringLengthmengurutkan string secara alfabetis jika panjangnya sama ...
Bukan pohon
1
@ LegionMammal978 Perbaikan yang lebih pendek adalah menyimpan SortBydan membungkus StringLengthdaftar untuk mendapatkan jenis yang stabil.
Martin Ender
3

JavaScript (ES6), 70 byte

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

Uji kasus

Arnauld
sumber
Gagal aaaabaaab, tetapi penggunaan yang bagus reduce.
Neil
2

Ini harus menjadi komentar, tetapi saya tidak memiliki reputasi yang cukup untuk berkomentar. Saya hanya ingin memberi tahu @Neil bahwa kodenya dapat dikurangi menjadi 77 byte. Anda tidak perlu menggunakan pernyataan maju di regex. Berikut ini versi yang direduksi:

s=>s.replace(/(.+)\1/g,(_,m)=>(n=m.length)>l&&(l=n,r=m),l=0)&&s.replace(r,'')
TRОLL
sumber
2
Halo, dan selamat datang di PPCG! Anda dapat mengirimkan ini sebagai jawaban JavaScript Anda sendiri! Jika Anda mau, saya dapat mengedit posting Anda dan menunjukkan kepada Anda bagaimana seharusnya.
NoOneIsHere
2
Saya perlu menggunakan pernyataan ke depan untuk menangani kasus pertandingan yang tumpang tindih. aababadalah contoh terpendek di mana saran Anda gagal.
Neil
0

C #, 169 byte

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

Penjelasan

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

Ini adalah pendekatan brute-force: coba setiap substring yang mungkin sampai kami menemukan substring berulang yang terpanjang. Tidak diragukan lagi Regex lebih efisien, tetapi berurusan dengan Regex di C # cenderung sangat bertele-tele.

Luar biasa
sumber
Selamat datang di PPCG! Semua jawaban harus berupa program lengkap atau fungsi yang dapat dipanggil , tidak yakin cuplikan dengan input dalam variabel yang dikodekan dengan keras. Juga, tolong tunjukkan versi kode yang Anda hitung dengan menghapus semua spasi yang tidak perlu. Anda selalu dapat menyertakan versi yang lebih mudah dibaca dengan lekukan di samping versi yang sepenuhnya golf.
Martin Ender
0

PHP, 84 82 byte

Catatan: menggunakan pengkodean IBM-850.

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

Jalankan seperti ini:

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

Penjelasan

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.

Tweaks

  • Disimpan 2 byte karena tidak ada panjang minimum dari substring yang diulang
aross
sumber