Bagaimana cara saya membuat daftar semua permutasi yang mungkin dari string antara panjang karakter x dan y, yang berisi daftar variabel karakter.
Bahasa apa pun bisa digunakan, tetapi harus portabel.
string
language-agnostic
cross-platform
UnkwnTech
sumber
sumber
Jawaban:
Ada beberapa cara untuk melakukan ini. Metode umum menggunakan rekursi, memoisasi, atau pemrograman dinamis. Ide dasarnya adalah Anda membuat daftar semua string dengan panjang 1, lalu di setiap iterasi, untuk semua string yang dihasilkan dalam iterasi terakhir, tambahkan string yang digabungkan dengan setiap karakter dalam string secara individual. (indeks variabel dalam kode di bawah ini melacak awal iterasi terakhir dan berikutnya)
Beberapa pseudocode:
Anda kemudian harus menghapus semua string yang panjangnya kurang dari x, mereka akan menjadi entri pertama (x-1) * len (originalString) dalam daftar.
sumber
Lebih baik menggunakan backtracking
sumber
Anda akan mendapatkan banyak string, itu pasti ...
Di mana x dan y adalah bagaimana Anda mendefinisikannya dan r adalah jumlah karakter yang kami pilih dari - jika saya memahami Anda dengan benar. Anda harus menghasilkan ini sesuai kebutuhan dan tidak menjadi ceroboh dan berkata, hasilkan powerset dan kemudian filter panjang string.
Yang berikut ini jelas bukan cara terbaik untuk menghasilkan ini, tapi ini yang menarik, tidak ada yang kurang.
Knuth (volume 4, fascicle 2, 7.2.1.3) memberi tahu kita bahwa (s, t) -kombinasi sama dengan s + 1 hal yang diambil t sekaligus dengan pengulangan - an (s, t) -kombinasi adalah notasi yang digunakan oleh Knuth itu sama dengan . Kita dapat mengetahui hal ini dengan pertama-tama menghasilkan masing-masing (s, t) -kombinasi dalam bentuk biner (jadi, dengan panjang (s + t)) dan menghitung jumlah 0 di sebelah kiri masing-masing 1.
10001000011101 -> menjadi permutasi: {0, 3, 4, 4, 4, 1}
sumber
Solusi non rekursif menurut Knuth, contoh Python:
sumber
"54321"
hanya dengan SATU string yang ditampilkan (sendiri).nextPermutation()
stateless - hanya membutuhkan input untuk permutasi dan indeks tidak dipertahankan dari iterasi ke iterasi. Hal ini dapat dilakukan dengan mengasumsikan bahwa input awal diurutkan dan menemukan indeks (k0
danl0
) itu sendiri, berdasarkan di mana pemesanan dipertahankan. Menyortir input seperti "54321" -> "12345" akan memungkinkan algoritma ini untuk menemukan semua permutasi yang diharapkan. Tetapi karena ia melakukan sejumlah besar pekerjaan ekstra untuk menemukan kembali indeks-indeks tersebut untuk setiap permutasi yang dihasilkannya, ada cara-cara yang lebih efisien untuk melakukan ini secara non-rekursif.Anda mungkin melihat " Menghitung Subset Set Secara Efisien ", yang menggambarkan algoritma untuk melakukan bagian dari apa yang Anda inginkan - dengan cepat menghasilkan semua subset karakter N dari panjang x ke y. Ini berisi implementasi dalam C.
Untuk setiap subset, Anda masih harus menghasilkan semua permutasi. Misalnya jika Anda menginginkan 3 karakter dari "abcde", algoritme ini akan memberi Anda "abc", "abd", "abe" ... tetapi Anda harus mengubah setiap karakter untuk mendapatkan "acb", "bac", "bca", dll.
sumber
Beberapa kode Java yang berfungsi berdasarkan jawaban Sarp :
sumber
Berikut adalah solusi sederhana dalam C #.
Ini hanya menghasilkan permutasi yang berbeda dari string yang diberikan.
sumber
Ada banyak jawaban bagus di sini. Saya juga menyarankan solusi rekursif yang sangat sederhana di C ++.
Catatan : string dengan karakter yang diulang tidak akan menghasilkan permutasi unik.
sumber
Saya baru saja menyiapkan ini dengan cepat di Ruby:
Anda mungkin melihat ke dalam API bahasa untuk fungsi tipe permutasi bawaan, dan Anda mungkin dapat menulis kode yang lebih optimal, tetapi jika angkanya terlalu tinggi, saya tidak yakin ada banyak cara untuk mendapatkan banyak hasil .
Bagaimanapun, ide di balik kode dimulai dengan string dengan panjang 0, kemudian melacak semua string dengan panjang Z di mana Z adalah ukuran saat ini dalam iterasi. Lalu, buka setiap string dan tambahkan setiap karakter ke setiap string. Akhirnya di akhir, hapus semua yang di bawah ambang x dan kembalikan hasilnya.
Saya tidak mengujinya dengan input yang berpotensi tidak berarti (daftar karakter nol, nilai aneh x dan y, dll).
sumber
Ini adalah terjemahan dari versi Mike's Ruby, ke Common Lisp:
Dan versi lain, sedikit lebih pendek dan menggunakan lebih banyak fitur fasilitas loop:
sumber
Inilah kata sederhana solusi rekursif C #:
Metode:
Panggilan:
sumber
... dan ini adalah versi C:
sumber
Mencetak semua permutasi tanpa duplikat
sumber
Solusi rekursif dalam C ++
sumber
Di Perl, jika Anda ingin membatasi diri ke alfabet huruf kecil, Anda dapat melakukan ini:
Ini memberikan semua string yang mungkin antara 1 dan 4 karakter menggunakan karakter huruf kecil. Untuk huruf besar, ubah
"a"
ke"A"
dan"zzzz"
ke"ZZZZ"
.Untuk case campuran itu menjadi jauh lebih sulit, dan mungkin tidak bisa dilakukan dengan salah satu operator builtin Perl seperti itu.
sumber
Jawaban Ruby yang berfungsi:
sumber
sumber
Rekursi Java berikut ini mencetak semua permutasi dari string yang diberikan:
Berikut ini adalah versi terbaru dari metode "permut" di atas yang membuat n! (n faktorial) panggilan kurang rekursif dibandingkan dengan metode di atas
sumber
Saya tidak yakin mengapa Anda ingin melakukan ini sejak awal. Himpunan yang dihasilkan untuk setiap nilai x dan y yang cukup besar akan menjadi besar, dan akan tumbuh secara eksponensial ketika x dan / atau y bertambah besar.
Katakanlah set karakter Anda yang mungkin adalah 26 huruf kecil dari alfabet, dan Anda meminta aplikasi Anda untuk menghasilkan semua permutasi di mana panjang = 5. Dengan asumsi Anda tidak kehabisan memori Anda akan mendapatkan 11.881.376 (yaitu 26 pangkat dari 5) string kembali. Bump sepanjang itu hingga 6, dan Anda akan mendapatkan 308.915.776 string kembali. Jumlah ini menjadi sangat besar, sangat cepat.
Inilah solusi yang saya kumpulkan di Jawa. Anda harus memberikan dua argumen runtime (sesuai dengan x dan y). Selamat bersenang-senang.
sumber
Berikut adalah versi non-rekursif yang saya buat, dalam javascript. Itu tidak didasarkan pada yang non-rekursif Knuth di atas, meskipun memiliki beberapa kesamaan dalam pertukaran elemen. Saya telah memverifikasi kebenarannya untuk input array hingga 8 elemen.
Optimalisasi cepat akan melakukan pre-flighting pada
out
array dan menghindaripush()
.Ide dasarnya adalah:
Diberikan array sumber tunggal, buat satu set array baru pertama yang menukar elemen pertama dengan setiap elemen berikutnya secara berurutan, setiap kali membiarkan elemen lain tidak terganggu. mis: diberikan 1234, hasilkan 1234, 2134, 3214, 4231.
Gunakan setiap larik dari pass sebelumnya sebagai seed untuk pass baru, tetapi alih-alih menukar elemen pertama, tukar elemen kedua dengan setiap elemen berikutnya. Juga, kali ini, jangan sertakan array asli dalam output.
Ulangi langkah 2 sampai selesai.
Berikut ini contoh kode:
sumber
Dalam ruby:
Ini cukup cepat, tetapi akan memakan waktu =). Tentu saja, Anda bisa mulai dari "aaaaaaaa" jika string pendek tidak menarik bagi Anda.
Saya mungkin telah salah menafsirkan pertanyaan yang sebenarnya - di salah satu posting itu terdengar seolah-olah Anda hanya membutuhkan perpustakaan string bruteforce, tetapi dalam pertanyaan utama itu terdengar seperti Anda perlu permutasi string tertentu.
Masalah Anda agak mirip dengan yang ini: http://beust.com/weblog/archives/000491.html (daftar semua bilangan bulat di mana tidak ada angka yang berulang, yang mengakibatkan banyak bahasa menyelesaikannya, dengan ocaml guy menggunakan permutasi, dan beberapa cowok java menggunakan solusi lain).
sumber
Saya membutuhkan ini hari ini, dan meskipun jawaban yang sudah diberikan mengarahkan saya ke arah yang benar, mereka tidak seperti yang saya inginkan.
Berikut ini adalah implementasi menggunakan metode Heap. Panjang array harus minimal 3 dan untuk pertimbangan praktis tidak boleh lebih dari 10 atau lebih, tergantung pada apa yang ingin Anda lakukan, kesabaran dan kecepatan clock.
Sebelum Anda memasukkan loop, inisialisasi
Perm(1 To N)
dengan permutasi pertama,Stack(3 To N)
dengan nol *, danLevel
dengan2
**. Di akhir panggilan loopNextPerm
, yang akan mengembalikan false ketika kita selesai.* VB akan melakukannya untuk Anda.
** Anda dapat mengubah NextPerm sedikit untuk membuat ini tidak perlu, tetapi lebih jelas seperti ini.
Metode lain dijelaskan oleh berbagai penulis. Knuth menjelaskan dua, satu memberikan urutan leksikal, tetapi rumit dan lambat, yang lain dikenal sebagai metode perubahan biasa. Jie Gao dan Dianjun Wang juga menulis makalah yang menarik.
sumber
Kode ini dalam python, ketika dipanggil dengan
allowed_characters
set ke[0,1]
dan 4 karakter maks, akan menghasilkan 2 ^ 4 hasil:['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']
Semoga ini berguna bagi Anda. Bekerja dengan karakter apa pun, tidak hanya angka
sumber
Berikut ini tautan yang menjelaskan cara mencetak permutasi string. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-characters-in.html
sumber
Meskipun ini tidak menjawab pertanyaan Anda dengan tepat, inilah salah satu cara untuk menghasilkan setiap permutasi huruf dari sejumlah string yang sama panjangnya: misalnya, jika kata-kata Anda adalah "kopi", "joomla" dan "moodle", Anda dapat mengharapkan output seperti "coodle", "joodee", "joffle", dll.
Pada dasarnya, jumlah kombinasi adalah (jumlah kata) dengan kekuatan (jumlah huruf per kata). Jadi, pilih angka acak antara 0 dan jumlah kombinasi - 1, konversikan angka itu menjadi basis (jumlah kata), lalu gunakan setiap digit angka itu sebagai indikator dari mana kata untuk mengambil huruf berikutnya.
misalnya: dalam contoh di atas. 3 kata, 6 huruf = 729 kombinasi. Pilih nomor acak: 465. Konversikan ke basis 3: 122020. Ambil huruf pertama dari kata 1, 2 dari kata 2, 3 dari kata 2, 4 dari kata 0 ... dan Anda mendapatkan ... "joofle".
Jika Anda menginginkan semua permutasi, hanya loop dari 0 hingga 728. Tentu saja, jika Anda hanya memilih satu nilai acak, cara yang jauh
lebih sederhana dantidak membingungkan adalah dengan mengulangi huruf-huruf. Metode ini memungkinkan Anda menghindari rekursi, jika Anda ingin semua permutasi, plus itu membuat Anda terlihat seperti Anda tahu Matematika (tm) !Jika jumlah kombinasi berlebihan, Anda dapat memecahnya menjadi serangkaian kata yang lebih kecil dan menyatukannya di akhir.
sumber
c # iterative:
sumber
sumber
Ini adalah pendapat saya tentang versi non rekursif
sumber
Solusi pythonic:
sumber
Nah, inilah solusi yang elegan, non-rekursif, O (n!):
sumber