Eu tenho uma lista enorme de músicas e, enquanto alguns artistas têm muitos álbuns, outros têm apenas uma música. Eu queria classificar a playlist para que o mesmo artista não tocasse duas vezes seguidas, ou suas músicas não terminariam principalmente no início ou no final da playlist.
Exemplo de lista de reprodução:
$ 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
Saída de sort -R
ou 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.
O que estou esperando:
$ 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
fonte
fonte
Respostas:
Se eu tivesse que aplicar esse embaralhamento a um baralho de cartas, acho que embaralharia o baralho primeiro, depois as mostraria seguidas diante dos meus olhos e processaria da esquerda para a direita, onde quer que houvesse clubes ou coração adjacentes. mova todos, exceto um aleatoriamente, para outro lugar (embora não seja próximo a outro do mesmo tipo).
Por exemplo, com uma mão como
Após o embaralhamento básico:
Para dois grupos de espadas adjacentes, precisamos realocar 1, 2 e 3. Para 1, as opções são:
Nós escolhemos um aleatoriamente daqueles 4. Em seguida, repetimos o processo para 2 e 3.
Implementado em
perl
que seria:Ele encontrará uma solução com artistas não adjacentes, se existir (a menos que mais da metade das músicas sejam do mesmo artista) e deve ser uniforme AFAICT.
fonte
Seus dados e restrições de exemplo permitem apenas algumas soluções - você deve tocar John B. todas as outras músicas, por exemplo. Vou assumir que sua lista de reprodução completa não é essencialmente John B, com outras coisas aleatórias para separá-la .
Essa é outra abordagem aleatória. Ao contrário da solução do @ frostschutz, ele roda rapidamente. Entretanto, não garante um resultado que atenda aos seus critérios. Apresento também uma segunda abordagem, que funciona com seus dados de exemplo - mas suspeito que produzirá maus resultados em seus dados reais. Tendo seus dados reais (ofuscados), adiciono a abordagem 3 - que é aleatória uniforme, exceto que evita duas músicas seguidas pelo mesmo artista. Observe que ele só faz 5 "empates" no "deck" das músicas restantes, se depois disso ainda for confrontado com um artista duplicado, ele produzirá essa música de qualquer maneira - dessa forma, é garantido que o programa realmente será concluído.
Abordagem 1
Basicamente, ele gera uma lista de reprodução a cada momento, perguntando "de quais artistas ainda tenho músicas não reproduzidas?" Em seguida, escolha um artista aleatório e, finalmente, uma música aleatória desse artista. (Ou seja, cada artista tem o mesmo peso, não na proporção do número de músicas.)
Experimente a sua lista de reprodução real e veja se ela produz melhores resultados do que uniformemente aleatória.
Uso:
./script-file < input.m3u > output.m3u
Certifique-sechmod +x
disso, é claro. Observe que ele não lida com a linha de assinatura que está no topo de alguns arquivos M3U corretamente ... mas seu exemplo não tinha isso.Abordagem 2
Como segunda abordagem, em vez de escolher um artista aleatório , você pode usar o artista com mais músicas, que também não é o último artista que escolhemos . O parágrafo final do programa passa a ser:
O restante do programa permanece o mesmo. Observe que essa não é a maneira mais eficiente de fazer isso, mas deve ser rápida o suficiente para listas de reprodução de qualquer tamanho. Com seus dados de exemplo, todas as listas de reprodução geradas começarão com uma música de John B., depois uma música de Anna A. e, em seguida, uma música de John B. Depois disso, é muito menos previsível (já que todos, exceto John B., têm uma música). Observe que isso pressupõe Perl 5.7 ou posterior.
Abordagem 3
O uso é o mesmo que o anterior 2. Observe a
0..4
parte, é daí que vem o máximo de 5 tentativas. Você poderia aumentar o número de tentativas, por exemplo,0..9
daria 10 no total. (0..4
=0, 1, 2, 3, 4
, que você notará na verdade são 5 itens).fonte
sed 's/ - .*//' output.m3u | uniq -d
). E você poderia explicar se alguns artistas não terminam no início ou no final da lista de reprodução?Se você não se importa que seja terrivelmente ineficiente ...
Ele continua rolando e rolando até chegar a um resultado que não tem dois ou mais Johns seguidos. Se houver tantos Johns em sua lista de reprodução que essa combinação não exista ou seja improvável que seja lançada, bem, ela travará.
Exemplo de resultado com sua entrada:
Se você descomentar as linhas de depuração, ele mostrará o motivo da falha:
Isso deve ajudar a determinar a causa no caso de travar indefinidamente.
fonte
sort
foi criada.shuf
embaralha a lista de reprodução 80 vezes mais rápido quesort -R
. Também não sabia disso! Vou deixar por 15 minutosshuf
, as chances são maiores!echo "$D"
antes doif
. Isso deve indicar quais duplicatas impediram que o resultado fosse escolhido. Isso deve indicar onde procurar o problema. (Edit: Adicionado possível depurar o código para a resposta.)sort
oushuf
.Outra abordagem usando o Bash. Ele lê a lista de reprodução em ordem aleatória, tenta inserir a linha no outro extremo da lista, se for uma duplicata, e coloca um único dupe de lado para reinseri-la em outro local. Ele falhará se houver duplicatas triplas (primeira, última e deixadas de lado idênticas) e anexará essas entradas incorretas ao final da lista. Parece ser capaz de resolver a extensa lista que você carregou na maioria das vezes.
Poderia ser mais inteligente ... no seu exemplo de John, John geralmente continuará sendo o last_artist porque sempre tenta anexar o first_artist primeiro. Portanto, se houver dois outros artistas no meio, não é inteligente o suficiente acrescentar um ao começo e o outro ao final para evitar o John triplo. Assim, com listas que basicamente exigem que todos os outros artistas sejam John, você obtém mais falhas do que deveria.
fonte