Saya memiliki daftar putar musik yang sangat besar dan, sementara beberapa artis memiliki banyak album, yang lain hanya memiliki satu lagu. Saya ingin mengurutkan daftar putar sehingga artis yang sama tidak akan bermain dua kali berturut-turut, atau lagu-lagunya sebagian besar tidak akan berakhir di awal atau akhir daftar putar.
Contoh daftar putar:
$ cat /tmp/playlist.m3u
Anna A. - Song 1
Anna A. - Song 2
I--Rock - Song 1
John B. - Song 1
John B. - Song 2
John B. - Song 3
John B. - Song 4
John B. - Song 5
Kyle C. - Song 1
U--Rock - Song 1
Output dari sort -R
atau shuf
:
$ sort -R /tmp/playlist.m3u
Anna A. - Song 1 #
U--Rock - Song 1
Anna A. - Song 2 # Anna's songs are all in the beginning.
John B. - Song 2
I--Rock - Song 1
John B. - Song 1
Kyle C. - Song 1
John B. - Song 4 #
John B. - Song 3 #
John B. - Song 5 # Three of John's songs in a row.
Apa yang saya harapkan:
$ some_command /tmp/playlist.m3u
John B. - Song 1
Anna A. - Song 1
John B. - Song 2
I--Rock - Song 1
John B. - Song 3
Kyle C. - Song 1
Anna A. - Song 2
John B. - Song 4
U--Rock - Song 1
John B. - Song 5
text-processing
sort
random
Teresa e Junior
sumber
sumber
Jawaban:
Jika saya harus menerapkan pengocokan tersebut ke setumpuk kartu remi, saya pikir saya pertama-tama akan mengocoknya, kemudian menampilkan kartu-kartu tersebut secara beruntun di depan mata saya dan memproses dari kiri ke kanan, di mana pun ada klub atau hati yang berdekatan .. Pindahkan semua kecuali satu dari mereka secara acak di tempat lain (meskipun tidak di sebelah yang lain dari jenis yang sama).
Misalnya dengan tangan suka
Setelah pengocokan dasar:
dua kelompok sekop yang berdekatan, kita perlu pindah 1, 2 dan 3. Untuk 1, pilihannya adalah:
Kami memilih satu secara acak dari 4. Itu. Kemudian kami ulangi proses untuk 2 dan 3.
Diimplementasikan dalam
perl
hal itu adalah:Ini akan menemukan solusi dengan artis yang tidak berdekatan jika ada (kecuali lebih dari setengah lagu dari artis yang sama), dan harus seragam AFAICT.
sumber
Contoh data dan batasan Anda sebenarnya hanya memungkinkan beberapa solusi β Anda harus memainkan John B. setiap lagu lainnya, misalnya. Saya akan menganggap daftar putar lengkap Anda yang sebenarnya pada dasarnya bukan John B, dengan hal-hal acak lainnya untuk dipecah .
Ini adalah pendekatan acak lain. Tidak seperti solusi @ frostschutz, ini berjalan dengan cepat. Namun, itu tidak menjamin hasil yang cocok dengan kriteria Anda. Saya juga menyajikan pendekatan kedua, yang bekerja pada data contoh Anda β tetapi saya curiga akan menghasilkan hasil yang buruk pada data Anda yang sebenarnya. Memiliki data asli Anda (dikaburkan), saya menambahkan pendekatan 3 β yang merupakan acak seragam, kecuali itu menghindari dua lagu oleh artis yang sama berturut-turut. Perhatikan bahwa itu hanya membuat 5 "menarik" ke dalam "dek" dari lagu yang tersisa, jika setelah itu masih dihadapkan dengan artis duplikat, itu akan tetap menghasilkan lagu itu β dengan cara ini, dijamin bahwa program akan benar-benar selesai.
Pendekatan 1
Pada dasarnya, ini menghasilkan daftar putar pada setiap titik, menanyakan "dari artis mana saya masih memiliki lagu yang belum diputar?" Kemudian memilih artis acak, dan akhirnya lagu acak dari artis itu. (Artinya, masing-masing artis diberi bobot yang sama, tidak sebanding dengan jumlah lagu.)
Cobalah daftar putar Anda yang sebenarnya, dan lihat apakah itu menghasilkan hasil yang lebih baik daripada acak yang seragam.
Penggunaan:
./script-file < input.m3u > output.m3u
Pastikan untukchmod +x
itu, tentu saja. Catatan itu tidak menangani garis tanda tangan yang ada di bagian atas beberapa file M3U dengan benar ... tetapi contoh Anda tidak memilikinya.Pendekatan 2
Sebagai pendekatan kedua, alih-alih memilih artis acak , Anda dapat menggunakan memilih artis dengan lagu terbanyak, yang juga bukan artis terakhir yang kami pilih . Paragraf akhir program kemudian menjadi:
Sisa program tetap sama. Perhatikan bahwa ini sejauh ini bukan cara yang paling efisien untuk melakukan ini, tetapi harus cukup cepat untuk daftar putar dengan ukuran waras apa pun. Dengan data contoh Anda, semua daftar putar yang dihasilkan akan mulai dengan lagu John B., kemudian lagu Anna A., lalu lagu John B. Setelah itu, itu jauh lebih mudah diprediksi (karena semua orang kecuali John B. memiliki satu lagu yang tersisa). Perhatikan bahwa ini mengasumsikan Perl 5.7 atau lebih baru.
Pendekatan 3
Penggunaannya sama dengan 2. sebelumnya. Perhatikan
0..4
bagiannya, dari situlah 5 mencoba maks berasal. Anda dapat meningkatkan jumlah percobaan, misalnya,0..9
akan memberikan 10 total. (0..4
=0, 1, 2, 3, 4
, yang akan Anda perhatikan sebenarnya adalah 5 item).sumber
sed 's/ - .*//' output.m3u | uniq -d
). Dan bisakah Anda jelaskan jika beberapa artis tidak berakhir di awal atau akhir daftar putar?Jika Anda tidak keberatan itu menjadi sangat tidak efisien ...
Itu hanya terus bergulir dan bergulir sampai tiba pada hasil yang tidak memiliki dua atau lebih Johns berturut-turut. Jika ada begitu banyak John di daftar putar Anda sehingga kombinasi seperti itu tidak ada atau sangat tidak mungkin untuk digulirkan, yah, itu akan menggantung.
Contoh hasil dengan input Anda:
Jika Anda menghapus tanda komentar pada garis debug, itu akan memberi tahu Anda mengapa gagal:
Itu akan membantu menentukan penyebabnya jika ia hang tanpa batas.
sumber
sort
desainnya.shuf
mengocok daftar putar 80 kali lebih cepat darisort -R
. Saya juga tidak tahu itu! Saya akan membiarkannya berjalan selama 15 menit denganshuf
, kemungkinan lebih tinggi!echo "$D"
sebelumif
. Itu akan memberi tahu Anda duplikat mana yang mencegah hasil dipilih. Itu akan memberi tahu Anda di mana mencari masalah. (Edit: Menambahkan kemungkinan kode debug ke jawabannya.)sort
ataushuf
.Pendekatan lain menggunakan Bash. Bunyinya daftar putar dalam urutan acak, mencoba untuk memasukkan baris di ujung daftar lain jika itu adalah duplikat, dan menempatkan satu dupe samping untuk memasukkannya kembali di tempat lain. Gagal jika ada duplikat rangkap tiga (pertama, terakhir, dan disisihkan identik) dan itu akan menambahkan entri buruk itu ke bagian paling akhir daftar. Tampaknya dapat menyelesaikan daftar ekstensif yang Anda unggah sebagian besar waktu.
Bisa jadi lebih pintar ... dalam contoh John Anda, John biasanya akan tetap menjadi yang terakhir_artis karena selalu mencoba untuk menambahkan yang pertama_artis dulu. Jadi jika ada dua artis lain di antaranya, itu tidak cukup pintar untuk menambahkan satu ke awal dan yang lainnya sampai akhir untuk menghindari triple-John. Jadi dengan daftar yang pada dasarnya mengharuskan setiap artis lain menjadi John, Anda mendapatkan lebih banyak kegagalan daripada yang seharusnya.
sumber