Tengo una gran lista de reproducción de música y, aunque algunos artistas tienen muchos álbumes, otros solo tienen una canción. Quería ordenar la lista de reproducción para que el mismo artista no tocara dos veces seguidas, o sus canciones no terminarían principalmente al principio o al final de la lista de reproducción.
Ejemplo de lista de reproducción:
$ 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
Salida de sort -R
o 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.
Lo que estoy 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
fuente
fuente
Respuestas:
Si tuviera que aplicar esa barajadura a una baraja de naipes, creo que primero barajaría la baraja, luego mostraría las cartas en una fila ante mis ojos y procesaría de izquierda a derecha, donde haya clubes o corazones adyacentes. . mover todos menos uno de ellos al azar a otro lugar (aunque no al lado de otro del mismo tipo).
Por ejemplo, con una mano como
Después de barajar básico:
dos grupos de espadas adyacentes, necesitamos reubicar 1, 2 y 3. Para 1, las opciones son:
Elegimos uno al azar de esos 4. Luego repetimos el proceso para 2 y 3.
Implementado en
perl
eso sería:Encontrará una solución con artistas no adyacentes si existe (a menos que más de la mitad de las canciones sean del mismo artista), y debe ser uniforme AFAICT.
fuente
Sus datos y restricciones de ejemplo en realidad solo permiten algunas soluciones: debe tocar John B. en cualquier otra canción, por ejemplo. Asumiré que tu lista de reproducción completa real no es esencialmente John B, con otras cosas al azar para dividirla .
Este es otro enfoque aleatorio. A diferencia de la solución de @ frostschutz, se ejecuta rápidamente. Sin embargo, no garantiza un resultado que coincida con sus criterios. También presento un segundo enfoque, que funciona en sus datos de ejemplo, pero sospecho que producirá malos resultados en sus datos reales. Con sus datos reales (ofuscados), agrego el enfoque 3, que es un azar uniforme, excepto que evita dos canciones del mismo artista en una fila. Tenga en cuenta que solo hace 5 "sorteos" en el "mazo" de las canciones restantes, si después de eso todavía se enfrenta a un artista duplicado, emitirá esa canción de todos modos, de esta manera, se garantiza que el programa realmente terminará.
Enfoque 1
Básicamente, genera una lista de reproducción en cada punto, preguntando "¿de qué artistas todavía tengo canciones sin reproducir?" Luego elegir un artista al azar, y finalmente una canción al azar de ese artista. (Es decir, cada artista tiene una ponderación igual, no en proporción al número de canciones).
Pruébelo en su lista de reproducción real y vea si produce mejores resultados que al azar uniforme.
Uso:
./script-file < input.m3u > output.m3u
Asegúrese dechmod +x
ello, por supuesto. Tenga en cuenta que no maneja la línea de firma que está en la parte superior de algunos archivos M3U correctamente ... pero su ejemplo no tenía eso.Enfoque 2
Como segundo enfoque, en lugar de elegir un artista al azar , puede usar elegir el artista con más canciones, que tampoco es el último artista que elegimos . El párrafo final del programa se convierte en:
El resto del programa permanece igual. Tenga en cuenta que esta no es la forma más eficiente de hacerlo, pero debería ser lo suficientemente rápida para listas de reproducción de cualquier tamaño razonable. Con sus datos de ejemplo, todas las listas de reproducción generadas comenzarán con una canción de John B., luego una canción de Anna A., luego una canción de John B. Después de eso, es mucho menos predecible (ya que a todos menos a John B. le queda una canción). Tenga en cuenta que esto supone Perl 5.7 o posterior.
Enfoque 3
El uso es el mismo que el anterior 2. Tenga en cuenta la
0..4
parte, de ahí proviene el máximo de 5 intentos. Podría aumentar el número de intentos, por ejemplo,0..9
daría 10 en total. (0..4
=0, 1, 2, 3, 4
, lo que notarás es en realidad 5 elementos).fuente
sed 's/ - .*//' output.m3u | uniq -d
). ¿Y podría explicar si se encarga de que algunos artistas no terminen al principio o al final de la lista de reproducción?Si no te importa que sea terriblemente ineficiente ...
Simplemente sigue rodando y rodando hasta que encuentra un resultado que no tiene dos o más Johns seguidos. Si hay tantos Johns en tu lista de reproducción que dicha combinación no existe o es extremadamente improbable que se lance, bueno, se bloqueará.
Ejemplo de resultado con su entrada:
Si descomenta las líneas de depuración, le dirá por qué falló:
Eso debería ayudar a determinar la causa en caso de que se cuelgue indefinidamente.
fuente
sort
está diseñado.shuf
baraja la lista de reproducción 80 veces más rápido quesort -R
. ¡Yo tampoco lo sabía! Lo dejaré funcionando durante 15 minutosshuf
, ¡las posibilidades son mayores!echo "$D"
antes delif
. Eso debería decirle qué duplicados impidieron que se eligiera el resultado. Eso debería decirle dónde buscar el problema. (Editar: se agregó un posible código de depuración a la respuesta.)sort
oshuf
.Otro enfoque usando Bash. Lee la lista de reproducción en orden aleatorio, intenta insertar la línea en el otro extremo de la lista si es un duplicado y deja a un lado a un lado para volver a insertarla en otro lugar. Falla si hay duplicados triples (primero, último y aparte idéntico) y agregará esas entradas incorrectas al final de la lista. Parece ser capaz de resolver la extensa lista que cargó la mayor parte del tiempo.
Podría ser más inteligente ... en su ejemplo de John, John generalmente se mantendrá como el último artista porque siempre trata de agregar el primer artista primero. Entonces, si hay otros dos artistas en el medio, no es lo suficientemente inteligente como para agregar uno al principio y el otro al final para evitar el triple-John. Entonces, con listas que básicamente requieren que cada otro artista sea John, obtienes más fracasos de los que deberías.
fuente