mp3 컬렉션을 정렬하기 위해 "ultimate shuffle"알고리즘을 작성하고 싶습니다


33

제목과 아티스트의 반복을 피하는 방식으로 mp3 파일정렬 하기위한 의사 코드 제안을 찾고 있습니다. 나는 프랭크 시나트라 (Frank Sinatra), 토니 베넷 (Tony Bennett), 엘라 피츠 제럴드 (Ella Fitzgerald) 등 오래된 기준을 부르는 크루 너를 듣는다. 각 아티스트는 같은 노래를 많이 녹음합니다. Fly Me To The Moon, The To You Tonight, Stardust 등. 내 목표는 아티스트와 노래 제목 사이의 최대 공간으로 노래를 정렬하거나 재생 목록을 주문하는 것입니다. 만약 내가 2000 곡을 가지고 있고 20 곡이 Ella에 의해 있다면 100 곡마다 한번씩 그녀를 듣고 싶습니다. 10 명의 아티스트가 Fly Me To The Moon을 부르면 200 곡마다 한 번씩 듣고 싶습니다. 물론이 두 가지 요구 사항을 결합하여 "궁극적 인 셔플"을 만들고 싶습니다.

나는 이것이 상당히 광범위한 질문이라는 것을 알고 있습니다. 나는 아직 프로그래밍을 시작하지 않았으므로 좋은 접근 방식에 대한 제안을 찾고 있습니다. 실제로 다른 노래 속성의 간격을 균일하게하는 데 필요한 다른 요구 사항이 있지만 여기서는 다루지 않습니다.


시작 지점으로 내가 코드를 수정하고있어 여기 MP3 파일을 조작하고 ID3 태그를 읽을 수 있습니다.

아래 parsifal의 답변을 사용하여 내 요구를 충족시키는 작은 응용 프로그램을 작성했습니다. 나는 또한 여기에 후속 질문을 썼습니다 . 모든 훌륭한 답변에 감사드립니다!


3
멋진 질문, 멋진 문제, 알고리즘을 잘 아는 사람은 공식적인 방법을 기반으로 훌륭한 답변을 얻을 것입니다.
Jimmy Hoffa

따라서 음악 컬렉션의 50 %가 같은 아티스트의 음악이라면 다른 아티스트 수에 관계없이 2 곡마다 아티스트의 음악을 듣고 싶습니다. 아마 50 % 정도는 아니지만 생각. 어쩌면 내 의견 일 수도 있지만, 모든 아티스트의 노래가 거의 같지 않으면 "궁극의 셔플"처럼 들리지 않습니다. 반면에 한 아티스트의 노래가 하나만 있다면 너무 많이 연주하고 싶지 않습니다. 2 사이의 균형을 찾는 것은 어렵지 않습니다.
Dukeling

나는이 의사 코드와 같은 것을 할 것입니다. while (length(songs) > 0) { x := rand(); addElem(shuffle, songs[x]); remElem(songs, x); }그러나 "궁극의 셔플"을 원한다고 말합니다. 난 당신이 정말로 무엇을 원하는지 모르겠어요, 심지어 질문을 읽고 ...
Cole Johnson

당신은 당신의 노래 목록 곳을 업로드 할 수 있습니다 - 제목과 아티스트 탭 또는 파이프 구분 또는 XML
tgkprog

밴시에서 (플러그인 또는 코어로) 멋지다!
phw

답변:


5

프로그램을 한 번 실행하여 재생 목록을 생성하거나 다음 노래를 라이브로 선택 하시겠습니까?

후자의 경우 대답은 간단합니다.

  • 아티스트와 제목으로 모든 노래가 포함 된 배열 만들기
  • 최근에 재생 한 노래 제목을 보유 할 목록 (링크 된 목록 선호)을 만듭니다. 이 목록은 비어 있으며 노래를 재생할 때마다 목록에 추가됩니다. 목록이 원하는 "노래 반복 없음"크기에 도달하면 가장 오래된 (첫 번째) 항목을 삭제하십시오.
  • 아티스트 목록을위한 Ditto.

노래를 고르면 다음과 같은 순서로 진행됩니다.

  1. "모든 노래"배열에서 임의로 노래를 선택하십시오. 이것은 0과 배열의 크기 사이의 임의의 숫자입니다.
  2. 해당 노래가 이미 재생 된 노래 목록에 있는지 확인하십시오. 그렇다면 1 단계로 돌아가십시오.
  3. 아티스트가 이미 재생중인 아티스트 목록에 있는지 확인하십시오. 그렇다면 1 단계로 돌아가십시오.
  4. 노래 아티스트 / 타이틀을 적절한 목록에 추가하고 필요한 경우 이전 항목을 삭제하십시오.
  5. 노래를 재생합니다.

몇 가지 가능한 문제가 있지만 실제 프로젝트가 아닌 숙제로 수행하는 경우에만 중요합니다.

  • 댓글에서 @Dukeling이 말했듯이, 컬렉션이 단일 아티스트 또는 노래 제목을 위해 균형이 불균형하면 노래를 끊임없이 거부하는 루프에 빠질 수 있습니다. 실제로 이것은 문제가되지 않습니다. 해결책은 "이미 본"목록의 크기를 줄여야한다는 것입니다. 그리고 2 단계와 3 단계에서 카운터를 추가하면 문제가 있는지 알 수 있습니다 (10 회 연속 실패가 발생하면 경고를 발생 시키거나 목록의 크기를 줄입니다).
  • 한 번만 재생 된 모든 노래가 포함 된 재생 목록을 생성하려는 경우 소스 배열에서 노래를 제거해야합니다. 너무 많은 "최근에 재생 된"실패를 처리하는 방법도 변경됩니다 (결국 소스 배열에 한 명의 아티스트 만있을 수 있기 때문에).
  • ID3 태그가 내 것과 비슷한 경우 철자가 틀립니다. "Duke Ellington"은 "Duke Elingten"과 달라야합니까? 그렇다면 "최근에 재생 된"목록을 스캔 할 때 Levenstein 매처를 사용해보십시오.

나는 락박스 (사용 rockbox.org )를. 모든 노래 폴더에 대해 동적 재생 목록을 생성 할 수 있습니다 (저장 및 북마크도 가능). 각 노래 제목 0001, 0002를 접두사 순서로 연주하려고합니다.
DeveloperDan

@DeveloperDan-동일한 프로세스가 작동하지만 마지막에 알 수 있듯이 규칙에 맞지 않는 노래가있을 수 있습니다. 두 가지 중에서 선택할 수 있습니다. 규칙을 조정하고 다시 실행하거나 (많지 않은 경우) 노래를 무작위로 삽입하십시오.
parsifal

1 단계에서 목록을 만들고 2와 3에서 제거합니다. 그러면 루프에 빠질 수 없으며 목록이 비어 있으면 규칙을 변경하고 다시 스캔해야한다는 것을 알고 있습니다. 보다 강력한 방법입니다.
Macke

13

생성기 (C #에서는 yield각 루프 반복을 수행 하는 무한 루프)를 사용하기 전에 이와 같은 작업을 수행했습니다 . 각 반복은 노래의 풀 (또는 무엇이든)을보고 너무 최근에 재생 된 (또는 부정적인 기준) 것을 던집니다. 그런 다음 필터링 된 목록에서 하나를 선택하고 상태를 업데이트하십시오. 주가 표류함에 따라 (Sinatra 이외의 노래를 재생 함) 기준이 깨지고 제외 된 노래가 다시 포함되기 시작합니다.

물론 다루어야 할 코너 케이스가 있습니다.

  • 모든 노래를 버리면 어떻게됩니까? (보통 상태를 불안정하게하기를 희망하면서 무작위로 하나를 선택하십시오)
  • 어떤 기준이 선호되어야합니까? (보통, 경우에 따라, 당신은 달에 다시 플라이를 재생하고 싶지 않으며, Sinatra를 연속해서 재생하는 것을 선호하지 않지만, 그것이 전부라면 ...)
  • 노래 모음이 싸움 중에 업데이트되면 어떻게 되나요? (일반적으로 다루기 쉽지만 동시성에는 사용량에 따라 문제가있을 수 있음)

11

Telastyn이 제기 한 질문의 특이 치를 무시하면 배낭 문제 에 변화가있는 것처럼 들립니다 . 다행스럽게도 문서화가 잘 된 알고리즘입니다.

위키 백과에서

각각 가중치와 값이있는 항목 세트가 제공되면 컬렉션에 포함 할 각 항목의 수를 결정하여 총 가중치가 주어진 한도보다 작거나 같고 총 값이 최대한 커지도록합니다.

배낭 문제 의 추가 목록 과 함께 해당 기사에 잠재적으로 관련이있는 변형이 있습니다.


배낭 문제의 한 가지 변형은 다목적 배낭 문제입니다. 개미 식민지 알고리즘은 문제를 해결하는 수단으로 권장합니다. 개미 식민지 접근 방식은 질문의 NP-hard 측면을 피하는 가장 쉬운 방법 일 수 있습니다.

또한 귀하의 문제를 여행하는 판매원 문제 의 극단적 인 변형으로 간주하는 것을 볼 수 있습니다 . 방문 할 각 도시는 실제로 연주하려는 노래이지만 아티스트 간 간격을 어떻게 지정할지 잘 모르겠습니다. 이 제안은 또한 개미 식민지 접근법과 관련이 있거나 해결 될 수 있습니다.


8

나는 이것이 "여기서 나의 라이브러리가 있고,이 프로그램을 실행하고 노래를 연주하는 순서를 생성한다"라는 가정하에 일하고있다.

이것은 구현되지 않았으며 셔플 링이 얼마나 잘 수행되는지 확실하지 않습니다. 내가 조금임을있을 수 있습니다 너무 노래의 초기 설정 주어진 나머지 규정 된 순서로 초래 필터, (내가 믿는)에서 엄격한.

하나는 ideal_gap해시가 있습니다. 이것은 주어진 속성 (아티스트, 앨범, 타이틀)을 가진 노래의 밀도에 의해 계산됩니다. 한 곡에 2000 곡이 있고 그 중 20 곡이 Ella라는 아티스트의 곡이면 100 곡이됩니다 ideal_gap{'artist'}{"ella"}.

이 정보를 가지고 있으면 최대 ideal_gap 값이 있습니다. 이것을 호출 할 수 max_gap있습니다.

다음을 고려하십시오. ideal_gap두 명의 아티스트 만 노래 한 노래 만 다른 노래가 1000 곡을 재생하지 못하도록 막고 max_gap 값을 크게 증가시켜 "백 오프, 노래 없음, 반복 재생"을 많이 반복 할 수있는 최대 값을 갖습니다. 노래가 없습니다 "

마지막으로 재생 된 max_gap 노래 검토 (이것은 Frank Sinatra 노래 Fly Me To the Moon로 끝난 경우 다음 곡이 우연히 같은 곡으로 시작하지 않도록 이전 곡에서 채울 수 있음) 라이브러리는 후보 노래 세트를 생성합니다. 곡의 모든 간격이 ideal_gap해당 특성에 대한 간격보다 작 으면 곡은 후보 곡에만 포함됩니다.

후보 곡 세트에서 무작위로 하나를 선택하십시오.

최대 간격이 더 높은 속성의 노래에 가중치를 부여 할 수 있도록 세트에 가중치를 부여하십시오. 이런 식으로 재생 목록의 끝에서 더 큰 최대 간격 곡이 모두 쌓이지 않습니다.

세 가지 속성이 모두 이상적인 차이보다 크지 않고 세 가지 중 두 가지만 고려하십시오. 이것은 이상적인 이상보다 빨리 연주 할 수 있지만 후보 곡 세트의 크기가 커지면 "임의로 하나 선택"에 더 많은 옵션이 있음을 의미합니다.

요구 사항을 채우는 노래가없는 경우, max_gap1을 기준으로 취소 하고 모든 ideal_gaps를 n/max_gap백분율 n로 표시합니다 (백 오프 된 횟수). 이 방법 max_gap으로 100이 있고이 반복에서 5 번 백 오프 된 경우 ideal_gap 100은 일시적으로 95로 조정되고 ideal_gap 20은 일시적으로 19로 조정됩니다. 후보 곡이 하나 이상있을 때까지 간격을두고 위와 같이 선택합니다.

고려하십시오 : 최소 수영장 크기가 있어야합니다. 이로 인해 차이가 커지지 만 재생할 수있는 다른 노래가있을 때 이상적인 간격보다 빨리 노래가 재생 될 수 있습니다.


1

이 최적화 작업, 그리고 꽤 복잡한 일이 당신이 찾고있는 경우 최적의 솔루션입니다. 다행히도 나는 그것이 충분히 좋은 경우라고 생각합니다.

가장 먼저 할 일은 수학적 품질 기준을 설정하는 것입니다. 즉, 목록의 순열이 주어진 수식은 순열이 얼마나 좋은지 나쁜지를 나타내는 단일 숫자를 반환합니다.

간단한 공식 제안, 고려할 각 기준에는 가중치를 부여하고, 중요한 기준에 대해 높은 가중치를 부여하고, 많은 노래가 동일한 속성을 공유하는 기준에 대해 가중치를 낮추어야합니다. :

For each song on the list
    For each other song on the list
        For each criteria
            If the two songs share that criteria
                Add to the quality value: square root( [criteria weight]/[distance between the two songs] )

이 절차에서 생성되는 값이 작을수록 목록 순열이 더 좋습니다.

순열 만들기

이제이 수식을 math.stackexchange에 가져 와서 사소한 수의 노래 이외의 다른 것에 대한 최적의 솔루션을 찾는 것이 얼마나 어려우며 실제로 불가능한지 말해 줄 수 있습니다. 또는 클럭 사이클을 던져서 얻을 수 있습니다. 좋은 해결책.

이를 수행하는 방법에는 여러 가지가 있습니다. 여기에 하나가 있습니다.

Start with a random permutation of the list.
Several million times do the following:
    Select two entries at random
    For each of those two entries calculate their contribution to the quality value
    Swap the positions of the two entries
    Calculate the contribution to the quality value of the two entries at their new position
    If the sum of the calculations in the new positions is greater than the sum in the old positions
        Swap back

이것은 다소 낭비적인 알고리즘이지만 구현하기 쉽고 하나의 원하는만큼 많은 기준을 처리 할 수 ​​있습니다.

최적화

다양한 조정 및 최적화를 적용 할 수 있습니다. 여기 몇 가지가 있습니다.

음질 값 계산에서 목록의 다른 모든 노래와 비교하여 노래를 확인하지 말고 100 개 정도의 가장 가까운 노래와 비교하여 확인하십시오. 공통 값의 경우이 속도 최적화는 결과의 품질에 실질적으로 영향을 미치지 않습니다.

주어진 속성의 드문 값의 경우 검색하는 것보다 해당 값의 기존 인스턴스를 추적하는 것이 더 효율적일 수 있습니다.

인스턴스가 적은 값이 간격을 두지 않고 균일 한 간격으로 배치하는 것이 중요하다고 생각되면 해당 특정 값의 가중치를 늘려야하지만 해당 기준의 다른 값은 그렇지 않아야합니다.

등분 포로리스트에서 가능한 모든 쌍을 선택하는 의사 랜덤 함수는 일반 무작위 선택보다 선택마다 약간 더 나은 효율성을 가질 수 있습니다.


귀하의 알고리즘은 시뮬레이션 어닐링 의 한 형태라고 생각합니다 .

@MichaelT 아니요, 시뮬레이트 어닐링은 "온도"를 사용하여 로컬 최대 값에 걸리지 않도록 낮은 상태로 되돌릴 수 있습니다. 이것은 로컬 검색 일뿐입니다. 시뮬레이션 어닐링 또는 기타 여러 확률 적 검색 알고리즘으로 비교적 쉽게 수정할 수 있지만 그럴 필요는 없다고 생각합니다. 기본적으로 다른 모든 알고리즘이 다르게하는 것은 로컬 최대 값을 피하는 것입니다.하지만이 문제에 대한 로컬 최대 값을 찾을 수 있다고 생각하지 않습니다.
aaaaaaaaaaaa

0

사람들이 취하는 다양한 접근법이 흥미 롭습니다. 나는 다음을 할 것이다 :

지금까지 연주 한 모든 트랙을 기준으로 각 트랙에 점수를 매 깁니다. 최저 점수 (또는 동일한 점수의 경우 최저 점수와 일치하는 임의의 점수)로 트랙을 재생합니다. 반복.

물론 어려운 점은 점수를 제공하는 것입니다. 다음에 재생할 수있는 각 트랙에 대해 이미 재생 한 각 트랙 또는 제한된 수의 트랙을 거쳐야합니다. [다음에 가능] 트랙과 [최근에 재생 된] 트랙에 공통점이있는 경우 공통점이 얼마인지, 공통점이 무엇인지, [최근에 연주 한] 트랙이 얼마나 오래 전인지에 따라 점수에 추가됩니다. 연주했다. 당신은 아마 "공통 아무것도 없음"을 0으로하고 싶을 것이므로 모든 트랙을 0으로 시작할 수 있습니다.

수작업으로 만든 재생 목록부터 실험하고 수학을 올바르게하기를 원할 것입니다. 공통 단어 수, 공통 단어 수의 제곱 또는 숫자의 제곱근을 원하십니까? 공통의 단어? 전체 재생 목록을 실행하고 어떤 항목이 상단에 '가장 일반적인'항목으로 표시되는지 확인하고, 균형을 맞추기 위해 요소를 직접 조정하세요. 편지별로 가고 싶을 수도 있으므로 "Duke Ellington"은 "Duke Elington"과 비교할 때 높은 점수를 얻지 만 "King Elle Duton"과 비교할 때 더 높은 점수를 얻습니다 (문자를 잃지 않은 경우 :) . 비교할 필드와 필드를 비교하려는 경우 매우 신중하게 고려해야합니다. bigrams (문자 쌍; Duke ellington의 경우 "Du",

특정 아티스트가 많은 경우 해당 아티스트가 우선 순위가 낮아질 수 있습니다. Duke Ellington 트랙 10 개를 모두 듣기 전에 고유 아티스트의 트랙을 5 번들을 수 있습니다. 이것은 당신이 원하는 것일 수도 아닐 수도 있습니다. Duke Ellington 트랙이 많으면 Duke Ellington의 트랙 두 개가 Billy Joe Shaver의 두 개 트랙보다 "덜 비슷합니다"라는 비교를해야합니다. .

두 쌍의 노래의 모든 조합으로 테이블을 미리 계산할 가치가 있습니다. 또한 다음에 재생할 곡을 고려할 때 지금까지 가장 좋은 곡만 기억하면됩니다. 고려할 다음 곡이 지금까지 최고의 곡보다 악보가 높으면 다음 곡으로 건너 뛸 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.