J'ai une énorme liste de lecture de musique et, alors que certains artistes ont de nombreux albums, d'autres n'ont qu'une seule chanson. Je voulais trier la playlist pour que le même artiste ne joue pas deux fois de suite, ou que ses chansons ne se retrouvent pas principalement au début ou à la fin de la playlist.
Exemple de liste de lecture:
$ 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
Sortie 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.
Ce que j'attends:
$ 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
la source
la source
Réponses:
Si je devais appliquer ce mélange à un jeu de cartes à jouer, je pense que je mélangerais d'abord le jeu, puis afficherais les cartes d'affilée devant mes yeux et les traiterais de gauche à droite, partout où il y a des clubs ou des cœurs adjacents .. . déplacez tous ceux sauf un au hasard ailleurs (mais pas à côté d'un autre du même type).
Par exemple, avec une main comme
Après un brassage de base:
deux groupes de piques adjacents, nous devons déplacer 1, 2 et 3. Pour 1, les choix sont:
Nous en choisissons un au hasard parmi ces 4. Ensuite, nous répétons le processus pour 2 et 3.
Mis en œuvre dans
perl
ce serait:Il trouvera une solution avec des artistes non adjacents s'il existe (à moins que plus de la moitié des chansons soient du même artiste), et devrait être uniforme AFAICT.
la source
Vos données et contraintes d'exemple ne permettent en fait que quelques solutions - vous devez jouer John B. toutes les autres chansons, par exemple. Je vais supposer que votre liste de lecture complète n'est pas essentiellement John B, avec d'autres choses aléatoires pour le casser .
Ceci est une autre approche aléatoire. Contrairement à la solution de @ frostschutz, elle s'exécute rapidement. Cependant, cela ne garantit pas un résultat qui correspond à vos critères. Je présente également une deuxième approche, qui fonctionne sur vos données d'exemple, mais je pense que cela produira de mauvais résultats sur vos données réelles. Ayant vos vraies données (obscurcies), j'ajoute l'approche 3 - qui est un aléatoire uniforme, sauf qu'elle évite deux chansons du même artiste d'affilée. Notez qu'il ne fait que 5 "tirages" dans le "deck" des chansons restantes, si après cela, il est toujours confronté à un artiste en double, il sortira cette chanson de toute façon - de cette façon, sa garantie que le programme se terminera réellement.
Approche 1
Fondamentalement, il génère une liste de lecture à chaque point, demandant "de quels artistes ai-je encore des chansons non jouées?" Puis choisir un artiste au hasard, et enfin une chanson au hasard de cet artiste. (C'est-à-dire que chaque artiste est pondéré de manière égale, non proportionnellement au nombre de chansons.)
Essayez-le sur votre liste de lecture réelle et voyez si elle produit de meilleurs résultats que uniformément aléatoire.
Utilisation:
./script-file < input.m3u > output.m3u
assurez-vouschmod +x
bien sûr. Notez qu'il ne gère pas correctement la ligne de signature qui se trouve en haut de certains fichiers M3U ... mais votre exemple ne l'a pas.Approche 2
Dans une deuxième approche, au lieu de choisir un artiste au hasard , vous pouvez utiliser choisir l'artiste avec le plus de chansons, qui n'est pas non plus le dernier artiste que nous avons choisi . Le dernier paragraphe du programme devient alors:
Le reste du programme reste le même. Notez que ce n'est de loin pas le moyen le plus efficace de le faire, mais il devrait être assez rapide pour les listes de lecture de toute taille saine. Avec vos données d'exemple, toutes les listes de lecture générées commenceront par une chanson de John B., puis une chanson d'Anna A., puis une chanson de John B. Après cela, c'est beaucoup moins prévisible (comme tout le monde sauf John B. a une chanson). Notez que cela suppose Perl 5.7 ou une version ultérieure.
Approche 3
L'utilisation est la même que la précédente. Notez la
0..4
partie, c'est de là que viennent les 5 essais max. Vous pourriez augmenter le nombre d'essais, par exemple,0..9
donner 10 au total. (0..4
=0, 1, 2, 3, 4
, ce que vous remarquerez est en fait 5 articles).la source
sed 's/ - .*//' output.m3u | uniq -d
). Et pourriez-vous s'il vous plaît expliquer si cela prend en charge certains artistes ne se retrouvant pas au début ou à la fin de la playlist?Si cela ne vous dérange pas d'être horriblement inefficace ...
Il continue de rouler et de rouler jusqu'à ce qu'il arrive sur un résultat qui n'a pas deux ou plusieurs Johns d'affilée. S'il y a tellement de Johns dans votre liste de lecture qu'une telle combinaison n'existe pas ou qu'il est extrêmement peu probable qu'elle soit roulée, eh bien, elle se bloquera.
Exemple de résultat avec votre entrée:
Si vous décommentez les lignes de débogage, il vous expliquera pourquoi il a échoué:
Cela devrait aider à déterminer la cause au cas où il se bloquerait indéfiniment.
la source
sort
.shuf
mélange la liste de lecture 80 fois plus rapidement quesort -R
. Je ne le savais pas non plus! Je vais le laisser tourner 15 minutes avecshuf
, les chances sont plus grandes!echo "$D"
avant leif
. Cela devrait vous dire quels doublons ont empêché le choix du résultat. Cela devrait vous dire où chercher le problème. (Edit: Ajout d'un code de débogage possible à la réponse.)sort
oushuf
.Une autre approche utilisant Bash. Il lit la liste de lecture dans un ordre aléatoire, essaie d'insérer la ligne à l'autre extrémité de la liste s'il s'agit d'un doublon, et met une seule dupe de côté pour la réinsérer dans un autre endroit. Il échoue s'il y a trois doublons (premier, dernier et mis de côté identiques) et il ajoutera ces entrées incorrectes à la fin de la liste. Il semble être en mesure de résoudre la longue liste que vous avez téléchargée la plupart du temps.
Cela pourrait être plus intelligent ... dans votre exemple John, John s'en tiendra généralement au dernier_artiste car il essaie toujours d'ajouter le premier_artiste en premier. Donc, s'il y a deux autres artistes entre les deux, ce n'est pas assez intelligent pour ajouter l'un au début et l'autre à la fin pour éviter le triple-John. Donc, avec des listes qui exigent essentiellement que tous les autres artistes soient John, vous obtenez plus d'échecs que vous ne devriez.
la source