У меня огромный музыкальный плейлист, и, хотя у некоторых артистов много альбомов, у других всего одна песня. Я хотел отсортировать плейлист, чтобы один и тот же исполнитель не играл дважды подряд, или его песни не попадают в начало или конец плейлиста.
Пример плейлиста:
$ 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
Выход из sort -R
или 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.
Что я ожидаю:
$ 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
Тереза и Джуниор
источник
источник
Ответы:
Если бы мне пришлось применить эту перетасовку к колоде игральных карт, я думаю, что я сначала перетасовал колоду, а затем отображал карты подряд перед моими глазами и обрабатывал их слева направо, где бы ни находились смежные булавы или сердце ... Переместить всех, кроме одного наугад, куда-нибудь еще (хотя не рядом с другим того же типа).
Например, с рукой, как
После основной тасовки:
две группы смежных пик, мы должны переместить 1, 2 и 3. Для 1, выбор:
Мы выбираем один случайный из этих 4. Затем мы повторяем процесс для 2 и 3.
Реализовано
perl
что бы:Он найдет решение для несмежных исполнителей, если он существует (если только не более половины песен принадлежат одному исполнителю), и должен быть одинаковым AFAICT.
источник
Ваши примеры данных и ограничения на самом деле допускают только несколько решений - например, вы должны играть Джона Б. каждую другую песню. Я собираюсь предположить, что ваш настоящий полный плейлист не является по сути Джоном Б. со случайным другим материалом, чтобы разбить его .
Это еще один случайный подход. В отличие от решения @ frostschutz, оно работает быстро. Однако это не гарантирует результат, который соответствует вашим критериям. Я также представляю второй подход, который работает с данными вашего примера, но я подозреваю, что он даст плохие результаты на ваших реальных данных. Имея ваши реальные данные (обфусцированные), я добавляю подход 3 - который является равномерным случайным, за исключением того, что он избегает двух песен одного исполнителя подряд. Обратите внимание, что он делает только 5 «дро» в «колоду» оставшихся песен, если после этого он все еще сталкивается с дублирующим исполнителем, он все равно выведет эту песню - таким образом, он гарантированно завершит программу.
Подход 1
По сути, он генерирует плейлист в каждой точке, спрашивая, «от каких исполнителей у меня до сих пор нетигранные песни?» Затем выбираем случайного исполнителя и, наконец, случайную песню этого исполнителя. (То есть каждый исполнитель имеет одинаковый вес, не пропорционально количеству песен.)
Попробуйте его в своем плейлисте и посмотрите, дает ли он лучшие результаты, чем случайный.
Использование:
./script-file < input.m3u > output.m3u
Убедитесь вchmod +x
этом, конечно. Обратите внимание, что он не обрабатывает строку подписи, которая находится в верхней части некоторых файлов M3U ... но в вашем примере этого не было.Подход 2
В качестве второго подхода вместо выбора случайного исполнителя можно выбрать исполнителя с большинством песен, который также не является последним выбранным исполнителем . Последний пункт программы становится:
Остальная часть программы остается прежней. Обратите внимание, что это далеко не самый эффективный способ сделать это, но он должен быть достаточно быстрым для плейлистов любого нормального размера. С вашими примерами все сгенерированные плейлисты начнутся с песни Джона Б., затем песни Анны А., затем песни Джона Б. После этого все гораздо менее предсказуемо (поскольку у всех, кроме Джона Б., осталась одна песня). Обратите внимание, что это предполагает Perl 5.7 или новее.
Подход 3
Использование такое же, как и в предыдущем 2. Обратите внимание на
0..4
часть, откуда берется максимум 5 попыток. Вы можете увеличить количество попыток, например,0..9
даст 10 всего. (0..4
=0, 1, 2, 3, 4
, который вы заметите, на самом деле это 5 пунктов).источник
sed 's/ - .*//' output.m3u | uniq -d
). И не могли бы вы объяснить, заботится ли он о том, что некоторые артисты не попадают в начало или конец плейлиста?Если вы не возражаете, это ужасно неэффективно ...
Он просто продолжает катиться, пока не достигнет результата, в котором нет двух или более Джонов подряд. Если в вашем плейлисте так много Johns, что такая комбинация не существует или крайне маловероятно, что она будет выпадать, ну, она будет зависать.
Пример результата с вашими данными:
Если вы раскомментируете строки отладки, он скажет вам, почему это не удалось:
Это должно помочь определить причину, если она зависает на неопределенный срок.
источник
sort
он спроектирован.shuf
перемешивает плейлист в 80 раз быстрее, чемsort -R
. Я тоже этого не знал! Я оставлю его включенным на 15 минутshuf
, шансы выше!echo "$D"
доif
. Это должно сказать вам, какие дубликаты помешали выбрать результат. Это должно сказать вам, где искать проблему. (Изменить: Добавлен возможный код отладки в ответ.)sort
илиshuf
.Другой подход с использованием Bash. Он читает список воспроизведения в произвольном порядке, пытается вставить строку на другом конце списка, если он дубликат, и откладывает один дубликат, чтобы вставить его в другое место. Он потерпит неудачу, если есть тройные дубликаты (первый, последний и выделены идентичные), и он добавит эти плохие записи в самый конец списка. Похоже, что он может решить обширный список, который вы загружали большую часть времени.
Это может быть умнее ... в вашем примере с Джоном Джон обычно придерживается позиции last_artist, потому что он всегда пытается сначала добавить first_artist. Таким образом, если между двумя другими художниками окажется недостаточно, он недостаточно умен, чтобы добавить одного в начало, а другого - в конец, чтобы избежать тройного Джона. Так что со списками, которые в основном требуют, чтобы каждый другой художник был Джоном, вы получаете больше неудач, чем должны.
источник