কিছু অতিরিক্ত বাধা দিয়ে এলোমেলোভাবে ফাইল সাফ করুন


12

আমার একটি বিশাল সংগীত প্লেলিস্ট রয়েছে এবং কিছু শিল্পীর অনেক অ্যালবাম রয়েছে, অন্যের কাছে কেবল একটি গান রয়েছে। আমি প্লেলিস্টটি বাছাই করতে চেয়েছিলাম যাতে একই শিল্পী পরপর দু'বার না বাজায় বা তার গানগুলি প্লেলিস্টের শুরু বা শেষদিকে শেষ হয় না।

প্লেলিস্ট উদাহরণ:

$ 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

13
প্রযুক্তিগতভাবে, আপনি যা চেয়েছেন তা কম এলোমেলোতা এবং আরও কাঠামো। এটি অসম্ভব নয়, তবে এটির জন্য (ব্যাশ / অ্যাজক / পারল / পাইথন / ইত্যাদি) স্ক্রিপ্টের প্রয়োজন হবে।
স্বর্ণলোকগুলি

বা একটি কাঠামোগত র্যান্ডমনেস :)
তেরেসা ই জুনিয়র

একদম ঠিক! পার্ল বা অজগরটিতে এটি একটি ভাল অনুশীলন হবে। আমি মনে করি এটি ব্যাশের সাথে মাথা ব্যথা হবে, যদিও এটি অ্যাজকের সাথে ভালভাবে কাজ করতে পারে - আমি বলার মতো যথেষ্ট ভালভাবে জানি না।
স্বর্ণিলকস

যেহেতু এটি করার কোনও সরঞ্জাম বলে মনে হচ্ছে না, তাই কোনও স্ক্রিপ্টটি যাওয়ার উপায় বলে মনে হচ্ছে। এটি এমন নয় যে আমি অলস, তবে আমি ধারণার বাইরে।
তেরেসা ই জুনিয়র

1
আপনি একটি সাধারণ অ্যালগরিদম দিয়ে এটি করতে সক্ষম হতে পারেন: প্রতিটি শিল্পীর পালাক্রমে একটি এলোমেলো গান নির্বাচন করে প্লেলিস্ট তৈরি করুন (যেখানে মোড়টি এলোমেলোভাবে করা যায় তবে শিল্পীর পুনরাবৃত্তি ছাড়াই)। যখন কোনও শিল্পীর সমস্ত গান শেষ হয়ে যায়, তখন একই শিল্পীর গানের সংলগ্নতা হ্রাস করতে এমন প্লেলিস্টটি এমনভাবে অবশিষ্ট শিল্পীদের (আবার পরিবর্তে তাদের মধ্যে পরিবর্তিত করে) আন্তঃলিখনের গানগুলি শুরু করুন। আপনার কাজ শেষ না হওয়া পর্যন্ত পুনরাবৃত্তি করুন। আমি দুঃখিত যে এটির সত্যিকারের স্ক্রিপ্টে প্যান করার আমার কাছে সময় নেই; আমি কেবল ভেবেছিলাম আপনার নিজের রোল দেওয়ার জন্য এটি দরকারী হতে পারে।
জোসেফ আর।

উত্তর:


5

যদি আমাকে সেই ডাবের বদলে কার্ড খেলতে হয় তবে আমি মনে করি যে আমি প্রথমে ডেকটি বদলে ফেলব, তারপরে আমার চোখের সামনে একের পর এক কার্ড প্রদর্শন করব এবং বাম থেকে ডানে প্রসেসিং করব, যেখানেই সংলগ্ন ক্লাব বা হার্ট রয়েছে .. সকলকে এলোমেলোভাবে অন্য কোথাও স্থানান্তর করুন (যদিও একই ধরণের অন্যটির পাশে নয়)।

যেমন একটি হাত দিয়ে

🂡 🂢 🂣 🂤 🂥 🂦 🂧 🂨 🂱 🂲 🂳 🃁 🃂 🃃 🃑 🃒

বেসিক বদলানোর পরে:

🂣 🃑 🂲 🂦 🂳 🃁<🂧 🂡 🂨>🃂<🂤 🂢>🃃 🂱 🂥 🃒
                   1  2       3

সংলগ্ন কোদাল দুটি গ্রুপ, আমাদের 1, 2 এবং 3 স্থানান্তরিত করতে হবে 1 এর জন্য পছন্দগুলি হ'ল:

🂣 🃑 🂲 🂦 🂳 🃁 🂧 🂡 🂨 🃂 🂤 🂢 🃃 🂱 🂥 🃒
    ↑        ↑                    ↑        ↑

আমরা সেই 4 থেকে এলোমেলোভাবে একটি বাছাই করি তারপরে আমরা প্রক্রিয়াটি 2 এবং 3 এর জন্য পুনরাবৃত্তি করি।

এতে প্রয়োগ করা perlহবে:

shuf list | perl -e '
  @songs = map {/(.*?)-/; [$1,$_]} <>;
  for ($i = 0; $i < @songs; $i++) {
    if (($author = $songs[$i]->[0]) eq $previous) {
      my @reloc_candidates, $same;
      for($j = 0; $j < @songs; $j++) {
        # build a list of positions where we could move that song to
        if ($songs[$j]->[0] eq $author) {$same = 1} else {
          push @reloc_candidates, $j unless $same;
          $same = 0;
        }
      }
      push @reloc_candidates, $j unless $same;

      if (@reloc_candidates) {
        # now pick one of them at random:
        my $chosen = $reloc_candidates[int(rand(@reloc_candidates))];
        splice @songs, $chosen - ($chosen > $i), 0, splice @songs, $i, 1;
        $i -= $chosen > $i;
      }
    }
    $previous = $author;
  }
  print map {$_->[1]} @songs'

এটি অ-সংলগ্ন শিল্পীদের সাথে সমাধান পাওয়া যাবে যদি এটি উপস্থিত থাকে (যদি না অর্ধেকের বেশি গান একই শিল্পীর থেকে থাকে), এবং এটি অএফএআইসিটি হওয়া উচিত।


তিনটি পৃথক স্ক্রিপ্ট (পারল এবং বাশ) চেষ্টা করার পরে, তারা সবাই প্যাসটবিনে রেখে যাওয়া প্লেলিস্টটি সংলগ্ন গানগুলি ছাড়াই বদলে দিয়েছে, তবে আপনার মনে হয় এটি আরও স্মার্ট উপায়ে এটি করেছে। তদ্ব্যতীত, শুধুমাত্র আপনার জন জন বি উদাহরণে নিখুঁতভাবে কাজ করে যা নিঃসন্দেহে এটি সেরা উত্তরের জন্য তৈরি করে। আমি ডার্বার্টকে তার উত্তরটি মেনে নেওয়ার প্রতিশ্রুতি দিয়েছিলাম, যেহেতু তিনি আমার পক্ষে অত্যন্ত ধৈর্যশীল এবং সহায়ক ছিলেন এবং তাঁর তৃতীয় পদ্ধতিটিও খুব ভাল। তাই আমি আপনাকে সেরা উত্তর এবং তাকে অনুগ্রহ দেব, এবং আমি আশা করি তিনি আমার উপর রাগ করবেন না :)
তেরেসা ই জুনিয়র

7

আপনার উদাহরণস্বরূপ ডেটা এবং সীমাবদ্ধতাগুলি কেবলমাত্র কয়েকটি সমাধানের অনুমতি দেয় — আপনার অবশ্যই জন বি বাজানো উচিত, উদাহরণস্বরূপ other আমি ধরে নিচ্ছি যে আপনার আসল পুরো প্লেলিস্টটি মূলত জন বি নয়, এলোমেলোভাবে অন্যান্য জিনিসগুলি এটি ভেঙে দেবে

এটি অন্য এলোমেলো পদ্ধতির। @ ফ্রয়েস্টছুটজের সমাধানের বিপরীতে, এটি দ্রুত চলে। এটি আপনার মানদণ্ডের সাথে মেলে এমন কোনও ফলাফলের গ্যারান্টি দেয় না। আমি একটি দ্বিতীয় পদ্ধতিরও উপস্থাপন করি যা আপনার উদাহরণের ডেটাতে কাজ করে - তবে আমার সন্দেহ হয় যে আপনার আসল তথ্যগুলিতে খারাপ ফলাফল আসবে। আপনার আসল ডেটা (অবরুদ্ধ) থাকায় আমি 3 approach পদ্ধতির যোগ করি যা একটি অভিন্ন র্যান্ডম, এটি এককভাবে একই শিল্পীর দুটি গান এড়ানো ব্যতীত। মনে রাখবেন যে এটি কেবলমাত্র বাকী গানের "ডেক" এর মধ্যে 5 টি "আঁক" তোলে, যদি তার পরেও এটি কোনও নকল শিল্পীর মুখোমুখি হয় তবে এটি যেভাবেই গানের আউটপুট পাবে — এইভাবে, এটির গ্যারান্টিযুক্ত যে প্রোগ্রামটি শেষ হবে।

পদ্ধতির ঘ

মূলত, এটি প্রতিটি পয়েন্টে একটি প্লেলিস্ট উত্পন্ন করে জিজ্ঞাসা করে, "আমার কাছে এখনও কোন শিল্পীর গান নেই?" তারপরে একটি এলোমেলো শিল্পীকে বাছাই করা এবং অবশেষে সেই শিল্পীর একটি এলোমেলো গান। (এটি, প্রতিটি শিল্পী গানের সংখ্যার অনুপাতে নয়, সমানভাবে ওজনযুক্ত))

আপনার প্রকৃত প্লেলিস্টে একবার ব্যবহার করে দেখুন এবং দেখুন এটি অভিন্নভাবে এলোমেলো চেয়ে ভাল ফলাফল দেয় কিনা।

ব্যবহার:./script-file < input.m3u > output.m3uchmod +x অবশ্যই এটি নিশ্চিত করুন । নোট করুন এটি কিছু এম 3 ইউ ফাইলের শীর্ষে থাকা স্বাক্ষর রেখাটি সঠিকভাবে পরিচালনা করে না ... তবে আপনার উদাহরণটিতে এটি নেই।

#!/usr/bin/perl
use warnings qw(all);
use strict;

use List::Util qw(shuffle);

# split the input playlist by artist
my %by_artist;
while (defined(my $line = <>)) {
    my $artist = ($line =~ /^(.+?) - /)
        ? $1
        : 'UNKNOWN';
    push @{$by_artist{$artist}}, $line;
}

# sort each artist's songs randomly
foreach my $l (values %by_artist) {
    @$l = shuffle @$l;
}

# pick a random artist, spit out their "last" (remeber: in random order)
# song, remove from the list. If empty, remove artist. Repeat until no
# artists left.
while (%by_artist) {
    my @a_avail = keys %by_artist;
    my $a = $a_avail[int rand @a_avail];
    my $songs = $by_artist{$a};
    print pop @$songs;
    @$songs or delete $by_artist{$a};
}

পদ্ধতির ঘ

দ্বিতীয় পদ্ধতির হিসাবে, এলোমেলো শিল্পী বাছাইয়ের পরিবর্তে , আপনি সবচেয়ে বেশি গান সহ শিল্পীকে বাছাই করতে ব্যবহার করতে পারেন , তিনিও আমরা বেছে নেওয়া শেষ শিল্পী নন । প্রোগ্রামটির চূড়ান্ত অনুচ্ছেদটি তখন পরিণত হয়:

# pick the artist with the most songs who isn't the last artist, spit
# out their "last" (remeber: in random order) song, remove from the
# list. If empty, remove artist. Repeat until no artists left.
my $last_a;
while (%by_artist) {
    my %counts = map { $_, scalar(@{$by_artist{$_}}) } keys %by_artist;
    my @sorted = sort { $counts{$b} <=> $counts{$a} } shuffle keys %by_artist;
    my $a = (1 == @sorted)
        ? $sorted[0]
        : (defined $last_a && $last_a eq $sorted[0])
            ? $sorted[1]
            : $sorted[0];
    $last_a = $a;
    my $songs = $by_artist{$a};
    print pop @$songs;
    @$songs or delete $by_artist{$a};
}

প্রোগ্রামের বাকি অংশগুলি একই থাকে। দ্রষ্টব্য যে এটি এখন পর্যন্ত এটি করার পক্ষে সবচেয়ে কার্যকর উপায় নয় তবে কোনও বুদ্ধিমান আকারের প্লেলিস্টের জন্য এটি যথেষ্ট দ্রুত হওয়া উচিত। আপনার উদাহরণের ডেটা দিয়ে, সমস্ত উত্পন্ন প্লেলিস্টগুলি জন বি গান, তারপরে আন্না এ। গান, তারপরে একটি জন বি গান দিয়ে শুরু হবে। তারপরে, এটি অনেক কম অনুমানযোগ্য (জন বি ছাড়া সবাই যেমন একটি গান বাকি আছে)। নোট করুন যে এটি পার্ল ৫.7 বা তার পরেও ধরেছে।

পদ্ধতির ঘ

ব্যবহারটি পূর্ববর্তী ২ এর মতোই the 0..4অংশটি নোট করুন , সেখান থেকে 5 টি সর্বোচ্চ ব্যবহারের চেষ্টা করে। আপনি চেষ্টা সংখ্যা আপ করতে পারে, উদাহরণস্বরূপ, 0..910 মোট দিতে হবে। ( 0..4= 0, 1, 2, 3, 4, আপনি লক্ষ্য করবেন যে আসলে 5 টি আইটেম)।

#!/usr/bin/perl
use warnings qw(all);
use strict;

# read in playlist
my @songs = <>;

# Pick one randomly. Check if its the same artist as the previous song.
# If it is, try another random one. Try again 4 times (5 total). If its
# still the same, accept it anyway.
my $last_artist;
while (@songs) {
    my ($song_idx, $artist);
    for (0..4) {
        $song_idx = int rand @songs;
        $songs[$song_idx] =~ /^(.+?) - /;
        $artist = $1;
        last unless defined $last_artist;
        last unless defined $artist; # assume unknown are all different
        last if $last_artist ne $artist;
    }

    $last_artist = $artist;
    print splice(@songs, $song_idx, 1);
}

@ টেরেজে জুনিয়র আপনি কি দুটি প্রোগ্রামকে আসল উপাত্তে চেষ্টা করে দেখেছেন এবং হয় আপনার পছন্দ অনুসারে হয় কিনা? (এবং, বাহ, এটি তাকান, এটি খুব "Fhk Hhck" ভারী ... আমি একটি পন্থা 3 যোগ করতে যাচ্ছি)
ডারবার্ট

কিছু শিল্পী আসলে পরপর দু'বার বাজায় (আপনি এটি দিয়ে পরীক্ষা করতে পারেন sed 's/ - .*//' output.m3u | uniq -d)। এবং আপনি দয়া করে ব্যাখ্যা করতে পারেন যদি এটি প্লেলিস্টের শুরু বা শেষের না শেষ পর্যন্ত কিছু শিল্পীর যত্ন নেয়?
তেরেসা ই জুনিয়র

পন্থা 1 সত্যই পর পর দুটি (বা আরও) অনুমতি দেয়। অ্যাপ্রোচ 2 না। 3 পদ্ধতি (এটি সম্পাদনা করতে প্রায়) এছাড়াও (ভাল, বেশিরভাগ) নেই। পন্থা 2 অবশ্যই খুব সাধারণ শিল্পীদের দ্বারা প্লেলিস্টের শুরুটিকে ওজন করে we অ্যাপ্রোচ 3 হবে না।
ডারোবার্ট

1
@ তেরেসি জুনিয়র আমি তৃতীয় যেটি কাজ করেছে তাতে আমি আনন্দিত! আমি নিশ্চিত না 4 কী পদ্ধতির সঠিকভাবে হবে, তবে এটি ভীতিজনক হবে ...
ডার্বার্ট

1
@JosephR। # 3 কাছে নেই , যেমন একটি ওজন-পরোক্ষভাবে প্রতিটি শিল্পীর গান নম্বর ব্যবহার একটি র্যান্ডম গান অবচয় দ্বারা। একজন শিল্পীর যত বেশি গান থাকবেন শিল্পীর বাছাই হওয়ার সম্ভাবনা তত বেশি। # 1 হ'ল একমাত্র গান যা গানের সংখ্যায় ওজন করে না।
ডারোবার্ট

2

যদি আপনি এটি মারাত্মকভাবে অকার্যকর বলে মনে করেন না ...

while [ 1 ]
do
    R="`shuf playlist`"
    D="`echo "$R" | sed -e 's/ - .*//' | uniq -c -d`"
    if [ "$D" == "" ]
    then
        break
    #else # DEBUG ONLY:
    #    echo --- FAIL: ---
    #    echo "$D"
    #    echo -------------
    fi
done

echo "$R"

এটি কেবল ঘূর্ণায়মান এবং ঘূর্ণায়মান রাখে যতক্ষণ না এটির ফলাফলটি আসে যতক্ষণ না পর পর দুটি বা আরও বেশি জন থাকে না। আপনার প্লেলিস্টে যদি এমন অনেক জনস থাকে যে এই ধরনের সংমিশ্রণটির অস্তিত্ব নেই বা ঘূর্ণায়িত হওয়ার খুব সম্ভাবনা নেই, ভাল, এটি স্থির হয়ে যাবে।

আপনার ইনপুট সহ উদাহরণ ফলাফল:

John B. - Song 4
Kyle C. - Song 1
Anna A. - Song 2
John B. - Song 3
Anna A. - Song 1
John B. - Song 1
U--Rock - Song 1
John B. - Song 2
I--Rock - Song 1
John B. - Song 5

আপনি যদি ডিবাগ লাইনগুলি আপত্তিহীন করেন তবে এটি আপনাকে বলবে কেন এটি ব্যর্থ হয়েছে:

--- FAIL: ---
      3 John B.
-------------
--- FAIL: ---
      2 John B.
      2 John B.
-------------

এটি অনির্দিষ্টকালের জন্য স্থগিত হওয়ার ক্ষেত্রে কারণ নির্ধারণে সহায়তা করা উচিত।


আমি ধারণাটি পছন্দ করি তবে স্ক্রিপ্টটি প্রায় 15 মিটার ধরে চলছে এবং উপযুক্ত সংমিশ্রণটি খুঁজে পেল না। এটি এমন নয় যে আমার কাছে জন দ্বারা অনেকগুলি গান রয়েছে, তবে প্লেলিস্টটি 7000 লাইনেরও বেশি, এবং মনে হয় এটি কীভাবে sortডিজাইন করা হয়েছে।
তেরেসা ই জুনিয়র

1
পারফরম্যান্স সম্পর্কে, shufপ্লেলিস্টটি 80 গুণ বেশি দ্রুত গতিতে পরিবর্তন করে sort -R। আমি তাও জানতাম না! আমি এটি 15 মিনিটের জন্য চলমান রেখে দেব shuf, সম্ভাবনা বেশি!
তেরেসা ই জুনিয়র

ডিবাগ করতে, echo "$D"আগে if। এটি আপনাকে বলা উচিত যে কোন সদৃশ ফলাফল ফলাফল নির্বাচন থেকে বাধা দিয়েছে। এটি আপনাকে কোথায় সমস্যার সন্ধান করবে তা জানানো উচিত। (সম্পাদনা করুন: উত্তরে সম্ভাব্য ডিবাগ কোড যুক্ত করা হয়েছে))
frostschutz

ডিইবিইউজি সর্বদা প্রায় 100 টি লাইন দেখায় তবে এলোমেলো শিল্পীদের থেকে তাই দেখে মনে হয় অনেক শিল্পী সমস্যা সৃষ্টি করছেন। আমার মনে হয় এটা সম্ভব সত্যিই নয় sortবা shuf
তেরেসা ই জুনিয়র

1

বাশ ব্যবহার করে আরেকটি পন্থা। এটি প্লেলিস্টটি এলোমেলোভাবে ক্রমে পড়ে, তালিকার অন্য প্রান্তে লাইনটি যদি নকল হয় তবে এটি সন্নিবেশ করানোর চেষ্টা করে এবং অন্য জায়গায় আবার সন্নিবেশ করানোর জন্য একক ডুপিকে আলাদা করে রাখে। এটি ব্যর্থ হয় যদি ট্রিপল ডুপ্লিকেট থাকে (প্রথম, শেষ এবং একইরকম সেট করা) এবং এটি সেই খারাপ এন্ট্রিগুলিকে তালিকার একেবারে প্রান্তে যুক্ত করবে। মনে হয় আপনি বেশিরভাগ সময় আপলোড করা বিস্তৃত তালিকাটি সমাধান করতে সক্ষম হবেন।

#!/bin/bash

first_artist=''
last_artist=''
bad_artist=''
bad_line=''
result=''
bad_result=''

while read line
do
    artist=${line/ - */}
    line="$line"$'\n'

    if [ "$artist" != "$first_artist" ]
    then
        result="$line""$result"
        first_artist="$artist"

        # special case: first = last
        if [ "$last_artist" == '' ]
        then
            last_artist="$artist"
        fi

        # try reinserting bad
        if [ "$bad_artist" != '' -a "$bad_artist" != "$first_artist" ]
        then
            first_artist="$bad_artist"
            result="$bad_line""$result"
            bad_artist=''
            bad_line=''
        fi
    elif [ "$artist" != "$last_artist" ]
    then
        result="$result""$line"
        last_artist="$artist"

        # try reinserting bad
        if [ "$bad_artist" != '' -a "$bad_artist" != "$last_artist" ]
        then
            last_artist="$bad_artist"
            result="$result""$bad_line"
            bad_artist=''
            bad_line=''
        fi
    else
        if [ "$bad_artist" == '' ]
        then
            bad_artist="$artist"
            bad_line="$line"
        else
            # first, last and bad are the same artist :(
            bad_result="$bad_result""$line"
        fi
    fi
done < <(shuf playlist)

# leftovers?
if [ "$bad_artist" != '' ]
then
    bad_result="$bad_result""$bad_line"
fi

echo -n "$result"
echo -n "$bad_result"

এটি আরও চৌকস হতে পারে ... আপনার জন উদাহরণে জন সাধারণত সর্বশেষ_আরবাদী হিসাবে আঁকড়ে থাকবেন কারণ এটি সর্বদা প্রথম_আরবাদীটিকে প্রথমে যুক্ত করার চেষ্টা করে। সুতরাং এটি যদি অন্য দুজন শিল্পীর মাঝে পাওয়া যায় তবে ট্রিপল জনকে এড়াতে এটির শুরুতে এবং অন্যটি শেষ পর্যন্ত যুক্ত করা যথেষ্ট স্মার্ট নয়। সুতরাং যে তালিকাগুলির সাথে মূলত প্রতিটি অন্যান্য শিল্পীকেই জন হতে হয়, আপনি নিজের চেয়ে বেশি ব্যর্থতা পান।


এই বাশ স্ক্রিপ্ট জন্য আপনাকে ধন্যবাদ। এটিই কেবলমাত্র আমি ইচ্ছামতই বুঝতে এবং সংশোধন করতে পারি!
তেরেসা ই জুনিয়র
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.