String.prototype.isRepeat

41

UPDATE : Pengajuan Pyth isaacg adalah pemenang!


Banyak dari Anda pasti pernah mendengar bahwa ada versi yang lebih dingin dari JavaScript di kota (baca ES6) yang memiliki metode String.prototype.repeatsehingga Anda dapat melakukan

"Hello, World!".repeat(3)

dan dapatkan

"Hello, World!Hello, World!Hello, World!"

sebagai output.

Tugas Anda adalah menulis suatu fungsi atau program dalam bahasa pilihan Anda yang mendeteksi jika suatu string telah mengalami transformasi semacam itu.

yaitu string input dapat direpresentasikan sebagai npengulangan kali yang tepat dari string yang lebih kecil. Output (sebagai pernyataan pengembalian fungsi atau STDOUT) harus benar jika string dapat atau palsu jika string tidak dapat direpresentasikan sebagai pengulangan string yang lebih kecil.

Beberapa input sampel:

"asdfasdfasdf"  // true
"asdfasdfa"     // false
"ĴĴĴĴĴĴĴĴĴ"     // true
"ĴĴĴ123ĴĴĴ123"  // true
"abcdefgh"      // false

Perhatikan bahwa input terakhir salah, sehingga nharus lebih besar dari1

Aturan lengkap

  • Tulis fungsi / program dalam bahasa apa saja untuk memasukkan (melalui argumen fungsi / argumen baris perintah / STDIN) sebuah string
  • Kembali / Cetak nilai kebenaran jika string yang diberikan dibentuk melalui pengulangan yang tepat dari string yang lebih kecil, ulangi setidaknya dua kali.
  • Ukuran maksimum dari string input idealnya adalah Infinity
  • String dapat memiliki semua karakter ASCII yang mungkin
  • Ini adalah sehingga kode terkecil dalam karakter menang.
Pengoptimal
sumber
Apa yang harus "" - string kosong - kembali? (Ini berisi jumlah tak terhingga dari string kosong.)
billpg
@billpg nilai falsy
Pengoptimal
Apakah Anda putus asa dengan suara? Praktik umum adalah pengajuan sebelumnya saya pikir (yah, yang pertama bermain golf hingga skor mengikat). Tapi saya tidak yakin itu ditulis sebagai pemutus standar di mana saja, jadi pada akhirnya terserah Anda.
Martin Ender
Waktu antara posting mereka hanya 30 menit. Saya tidak akan menganggap itu cukup untuk menang :). Karena waktu itu tidak akan berubah sekarang, tetapi suara dapat, saya memilih dengan suara
Pengoptimal
Pertanyaan ini harus diubah namanya menjadi xnor :) Dia orangnya!
Silviu Burcea

Jawaban:

16

Pyth , 9

/:+zz1_1z

Atau

}z:+zz1_1

Ini adalah terjemahan dekat dari jawaban python @ xnor, kecuali bahwa mereka mengambil input dari STDIN dan mencetaknya. Yang pertama setara dengan:

z = input()
print((z+z)[1:-1].count(z))

0 untuk False, 1 untuk True.

Baris kedua setara dengan:

z = input()
print(z in (z+z)[1:-1])

Salah untuk Salah, Benar untuk Benar.

Kompiler resmi Pyth memiliki bug yang terkait dengan yang kedua, yang baru saja saya tambal, jadi yang pertama adalah pengiriman resmi saya.

isaacg
sumber
Saya hanya mencari cara untuk memberi tahu Anda tentang bug itu (Boolean tidak dapat dicetak). Tidak memikirkan yang pertama dan menggunakan xterlalu lama ...
Dennis
Ya, bug sudah diperbaiki sekarang. Juga, jika Anda ingin melaporkan bug, cara yang bagus mungkin adalah membuka masalah di situs github, di sini: github.com/isaacg1/pyth/issues
isaacg
Oh, ada itu. Saya tidak tahu jalan di sekitar GitHub, dan saya tidak pernah melihat panel navigasi di sebelah kanan ...
Dennis
81

Python (24)

lambda s:s in(s+s)[1:-1]

Memeriksa apakah string adalah substring dari dirinya sendiri digabung dua kali, menghilangkan karakter pertama dan terakhir untuk menghindari kecocokan sepele. Jika ya, itu harus permutasi siklik nontrivial itu sendiri, dan dengan demikian jumlah segmen berulang.

Tidak
sumber
8
Terjemahan sepele ke Golfscript menghasilkan 10 karakter:..+);(;\?)
Justin
3
Saya tidak begitu mengerti bagaimana ini bekerja. Bisakah Anda memberikan contoh yang dijelaskan secara manual tentang bagaimana ini akan menangani string?
Nzall
8
@NateKerkhofs ambil abcabc. s+smengubahnya menjadi abcabcabcabc. yang [1:-1]daging dari kedua ujung untuk menghasilkan bcabcabcabcab. dan kemudian s in ...mencoba mencari abcabcsebagai substring dari itu. Substring ini tidak dapat ditemukan di salah satu dari setengah yang asli, karena keduanya telah dipersingkat, sehingga harus merentang kedua bagian. Secara khusus, ia harus memiliki ujungnya sendiri sebelum mulai, yang menyiratkan bahwa ia harus terdiri dari substring identik (berulang).
Martin Ender
6
Anda memotongnya setelah menggandakannya. abmenjadi ababmenjadi ba, sehingga mengembalikan false, sementara aamenjadi aaaamenjadi aa, yang mengembalikan benar.
histokrat
1
@SargeBorsch Ini berfungsi sama: qweqweqwein weqweqweqweqweqwis True.
xnor
30

Regex (aroma ECMAScript), 11 byte

Kedengarannya seperti pekerjaan untuk regex!

^([^]+)\1+$

Uji di sini.

Saya telah memilih ECMAScript, karena itu satu-satunya rasa (saya tahu) yang [^]cocok dengan karakter apa pun. Di semua yang lain, saya perlu bendera untuk mengubah perilaku .atau menggunakan [\s\S]yang tiga karakter lebih lama.

Tergantung pada bagaimana kita menghitung bendera, yang bisa saja menjadi byte lebih pendek. Misalnya jika kita menghitung pola + flag (mis. Mengabaikan pembatas), PCRE / Perl yang setara akan menjadi

/^(.+)\1+$/s

Yaitu 10 byte, mengabaikan pembatas.

Uji di sini.

Ini hanya cocok dengan string yang terdiri dari setidaknya dua pengulangan beberapa substring.

Berikut ini adalah fungsi ES6 26-byte penuh, tetapi saya berpendapat bahwa pengiriman ekspresi reguler umumnya valid:

f=s->/^([^]+)\1+$/.test(s)
Martin Ender
sumber
^(.+)\1+$bekerja untuk saya, yaitu 9 byte. Itu tidak bekerja untukmu?
Pengoptimal
@ Opptizer Coba string dengan jeda baris.
Martin Ender
Saya mencoba asd\nasd\nasd\n. Ini berfungsi
Pengoptimal
@Optimizer refiddle.com/refiddles/5417fb2475622d4df7e70a00 tampaknya tidak bekerja untuk saya (dan seharusnya tidak)
Martin Ender
Ya, itu tidak berhasil. Mungkin itu luput dari \ ketika saya menulis \nsecara manual
Pengoptimal
12

CJam, 9

q__+)@+#)

Mirip dengan ide xnor.

q      " Read input. ";
__+    " Duplicate twice and concatenate them together. ";
)      " Remove the last character of the longer string. ";
@+     " Insert that character at the beginning of the shorter string. ";
#)     " Find the shorter string in the longer string, and increase by one. ";
jimmy23013
sumber
+1 wajib membatalkan ini sebelum jawaban CJam saya
Digital Trauma
Mengapa perlu untuk final )? Saya pikir masuk akal untuk memiliki -1 mean FALSE dan> = 0 mean TRUE
Digital Trauma
@ DigitalTrauma Saya pikir 0 palsu di CJam ... untuk operator seperti gdan ?.
jimmy23013
@ DigitalTrauma: Apakah diperlukan pada akhirnya tergantung pada OP, tetapi hanya nol yang dianggap salah dalam CJam.
Dennis
@ user23013 @ Dennis Tapi bagaimana dengan #operator find? Tentunya hasil dari itu juga "benar" dari perspektif keberhasilan vs kegagalan?
Digital Trauma
7

APL, 11

2<+/x⍷,⍨x←⍞

Penjelasan
mengambil input string dari layar yang
x←ditugaskan ke variabel x
,⍨menggabungkan string dengan
x⍷pencarian sendiri xdalam string yang dihasilkan. Mengembalikan array yang terdiri dari 1 di posisi awal pertandingan dan 0 di tempat lain.
+/menjumlahkan array
2<memeriksa apakah jumlahnya lebih besar dari 2 (karena akan ada 2 kecocokan sepele)

TwiNight
sumber
7

CJam, 10 byte

Saya menangkap bug CJam. Jawaban pertama saya, jadi mungkin bisa bermain golf lagi:

q__+(;);\#

Output -1 untuk FALSE dan angka> = 0 untuk TRUE

Trauma Digital
sumber
5
Selamat Datang di klub!
Dennis
5

GolfScript, 10 byte

..+(;);\?)

Namun implementasi lain dari ide pintar xnor.

Dennis
sumber
Hahaha, saya baru saja memposting ini semenit yang lalu: codegolf.stackexchange.com/questions/37851/… . Saya berpikir untuk mempostingnya sebagai jawaban, tetapi saya pikir terjemahan sepele tidak menarik.
Justin
Saya bahkan memeriksa jawaban baru kali ini, tetapi tidak untuk komentar baru ... Kode Anda tidak ada ); ketika tidak ada yang cocok, itu akan dicetak -1. Jika Anda akan memposting itu sebagai jawaban, saya dengan senang hati akan menghapus milik saya.
Dennis
Saya menambahkan )tepat sebelum Anda memposting jawaban Anda (saya mengedit komentar)
Justin
1
Peningkatan versi (di CJam): q__+)@+#). Tidak berfungsi di GolfScript.
jimmy23013
1
@ user23013: Tidak lagi. Saya hanya akan memposting itu! Ada terlalu banyak CJammers di luar sana sekarang ...: P
Dennis
3

Python - 59 57

lambda s:any([s*n==s[:n]*len(s)for n in range(2,len(s))])
Falko
sumber
3

Bash murni, 30 byte

Port sederhana dari jawaban pintar xnor :

[[ ${1:1}${1:0: -1} =~ "$1" ]]

Kode keluar adalah 0 untuk BENAR dan 1 untuk SALAH:

$ for s in 'Hello, World!Hello, World!Hello, World!' 'asdfasdfasdf' 'asdfasdfa' 'ĴĴĴĴĴĴĴĴĴ' 'ĴĴĴ123ĴĴĴ123' 'abcdefgh'; do echo "./isrepeated.sh "\"$s\"" returns $(./isrepeated.sh "$s"; echo $?)"; done
./isrepeated.sh "Hello, World!Hello, World!Hello, World!" returns 0
./isrepeated.sh "asdfasdfasdf" returns 0
./isrepeated.sh "asdfasdfa" returns 1
./isrepeated.sh "ĴĴĴĴĴĴĴĴĴ" returns 0
./isrepeated.sh "ĴĴĴ123ĴĴĴ123" returns 0
./isrepeated.sh "abcdefgh" returns 1
$ 

Catatan =~dalam [[ ... ]]adalah operator regex di bash . Namun "Bagian mana pun dari pola dapat dikutip untuk memaksa agar dicocokkan sebagai string" . Jadi seperti yang sering terjadi dengan bash, mendapatkan kutipan yang tepat sangat penting - di sini kami hanya ingin memeriksa pengiriman string dan bukan pertandingan regex.

Trauma Digital
sumber
3

TI-BASIC - 32

Saya pikir saya akan mencoba bahasa tokenized. Jalankan dengan string di Ans, mengembalikan 0 jika false dan panjang string yang diulang jika benar.

inString(sub(Ans+Ans,1,2length(Ans)-1),sub(Ans,length(Ans),1)+Ans

Luar biasa bagaimana ini hanya satu-liner.

Josiah Winslow
sumber
Tapi ... tapi ... saya akan menggunakan TI-BASIC: P +1
Timtech
@Timtech Nah, perhatikan siapa pun yang mencoba manipulasi string di TI-BASIC: Jangan coba manipulasi string di TI-BASIC. : P Itu sangat sulit untuk dibuat dan dioptimalkan.
Josiah Winslow
Ide bagus. Manipulasi string adalah salah satu hal tersulit untuk dilakukan. Namun, saya telah memposting beberapa jawaban seperti ini, jadi saya kira sekarang Anda memiliki pesaing;)
Timtech
Ayo! : P
Josiah Winslow
3

ECMAScript 6 (189)

(function(){var S=String.prototype,r=S.repeat;S.isRepeated=function(){return!1};S.repeat=function(c){var s=new String(r.call(this,c));if(c>1)s.isRepeated=function(){return!0};return s}}());

 

< console.log("abc".isRepeated(),"abc".repeat(10).isRepeated());
> false true

Tentunya ini satu-satunya solusi yang valid? Misalnya, kata (string) nanatidak harus dibuat dari"na".repeat(2)

Mardoxx
sumber
"nana"tidak, tetapi pertanyaannya bukan pengujian apakah .repeatdigunakan atau tidak. Alih-alih, apakah string itu berulang atau tidak
Pengoptimal
Saya tahu, saya hanya berusaha menjadi orang sok pintar: P
Mardoxx
2

ECMAScript 6 (34 36 )

Jawaban ES6 lain, tetapi tanpa menggunakan repeatdan menggunakan trik xnor :

f=i=>(i+i).slice(1,-1).contains(i)

Harus dijalankan di konsol peramban berkemampuan ES6 seperti Firefox.

Ingo Bürk
sumber
2

C 85

l,d;f(s){return l=strlen(s),strstr(d,strcpy(strcpy(d=alloca(l*2+1),s)+l,s)-1)-d-l+1;}

Ternyata cukup lama tetapi fungsi eksternal selalu seperti itu. Terlintas dalam pikiran saya bahwa saya dapat menulis ulang setiap fungsi string yang menggantinya dengan loop atau yang berulang. Tetapi dalam pengalaman saya itu akan berubah lebih lama dan terus terang saya tidak ingin mencobanya.

Setelah beberapa penelitian saya melihat solusi pada kinerja tinggi tetapi tidak sepintar (dan pendek) sebagai salah satu xnor. hanya untuk menjadi asli ... saya menulis ulang ide yang sama di c.

penjelasan:

int length, 
    duplicate;
int is_repetition(char *input)
{
    // length = "abc" -> 3
    length = strlen(input);
    // alloca because the function name is as long as "malloc" 
    // but you don't have to call free() because it uses the stack
    // to allocate memory
    // duplicate = x x x x x x + x
    duplicate = alloca(length*2 + 1);
    // duplicate = a b c 0 x x + x
    strcpy(duplicate, input);
    // duplicate = a b c a b c + 0
    strcpy(duplicate + length, input);
    if (strstr(duplicate,duplicate + length - 1) != duplicate + length - 1)
        // repetition
        // e.g. abab -> abababab -> aba[babab]
        // -> first occurence of [babab] is not aba[babab]
        // but a[babab]ab -> this is a repetition
        return 1;
    else
        // not repetition
        // e.g. abc -> abcabc -> ab[cabc]
        // -> first occurence of [cabc] is ab[cabc]
        // it matches the last "cabc"
        return 0;
}
bebe
sumber
1

ECMAScript 6 (59 62 67 73 )

Bukan pemenang, tetapi sepertinya setidaknya harus ada satu jawaban di ES6 untuk pertanyaan ini yang benar-benar menggunakan repeatfungsi:

f=i=>[...i].some((_,j)=>i.slice(0,j).repeat(i.length/j)==i)

Harus dijalankan di konsol peramban berkemampuan ES6 seperti Firefox.

Memang banyak iterasi yang tidak perlu, tapi mengapa membuatnya lebih lama hanya untuk menghindari itu, kan?

  • Sunting # 1: Menyimpan beberapa byte dengan mengubahnya menjadi fungsi. Terima kasih kepada Pengoptimal!
  • Sunting # 2: Terima kasih kepada hsl untuk trik operator penyebaran untuk menghemat lebih banyak byte!
  • Sunting # 3: Dan terima kasih kepada Rob W. untuk 3 byte lagi!
Ingo Bürk
sumber
Anda dapat mengubahnya menjadi fungsi untuk menghemat lebih banyak byte di sana
Pengoptimal
@ Opptizer Benar, saya kira itu tidak harus "stdin". Hidup Anda sesuai dengan nama Anda :)
Ingo Bürk
Saya belum menguji ini, tetapi Anda harus dapat menggunakan operator spread untuk [...i]bukannyai.split('')
NinjaBearMonkey
1
@ hsl Gila, itu berhasil. Saya tidak tahu operator spread bekerja seperti itu. Awalnya saya mati-matian mencoba menggunakannya untuk membuat array dengan jangkauan 0..N. Terima kasih!
Ingo Bürk
1
.slice(0,j)adalah satu karakter lebih pendek dari .substr(0,j). Lebih lanjut, konversi ke bilangan bulat tampaknya tidak perlu |0dapat dihapus (menggunakan |0sebenarnya mengurangi kegunaan metode karena akan gagal untuk pengulangan yang melebihi 2 ^ 31).
Rob W
0

Java 8, 28 byte

s->s.matches("(?s)(.+)\\1+")

Cobalah online.

Penjelasan:

Cek apakah input-String cocok dengan regex, di mana String#matchessecara implisit ditambahkan ^...$agar cocok dengan seluruh String.
Penjelasan dari regex itu sendiri:

^(s?)(.+)\1+$
^                Begin of the string
 (s?)            Enable DOTALL-mode, where `.` also matches new-lines
     (           Open capture group 1
      .+          One or more characters
        )        Close capture group 1
         \1+     Plus the match of the capture group 1, one or more times
            $    End of the string

Jadi pada dasarnya memeriksa apakah substring diulang dua atau lebih kali (mendukung baris baru).

Kevin Cruijssen
sumber