DVDに記録したいメディアファイルがたくさんありますが、各DVDは4.5GBにしか収まらないため、最小数のDVDを使用するようにファイルを整理する最適な方法を見つける必要があります(それ以外の場合は、それぞれの空きスペースが残ります) DVDは簡単に追加できます)。これを支援するツールはありますか?
何年も前に、フロッピーディスクでこれを行うDOSユーティリティがありました。
DVDに記録したいメディアファイルがたくさんありますが、各DVDは4.5GBにしか収まらないため、最小数のDVDを使用するようにファイルを整理する最適な方法を見つける必要があります(それ以外の場合は、それぞれの空きスペースが残ります) DVDは簡単に追加できます)。これを支援するツールはありますか?
何年も前に、フロッピーディスクでこれを行うDOSユーティリティがありました。
回答:
Jeff Shattockの答えは、これは組み合わせ最適化問題と同等(または数学者が書いているように同型)ですが、ナップザック問題ではなく、1次元のビンパッキング問題と同等です。
幸運なことに、.NET Frameworkのバージョン3.5以降がインストールされているWindowsコンピューターにアクセスして、この問題を解決するためのコードをいくつか共有しています。
まず、LINQPadをダウンロードしてインストールします。
次に、先ほど書いたばかりのLINQPadクエリをダウンロードします。ここに、生ファイルへのlinq(ha)があります。.linqファイルとして保存し、LINQPadで開きます。
パラメータを変更します。
変更する必要があるLINQPadクエリコードの部分を次に示します。
int binSizeMb = 4476; // This is the (floor of the) total size of a DVD+R reported by CDBurnerXP.
string rootFileFolderPath = @"F:\2006 - Polyester Pimpstrap Intergalactic Extravaganza multicam";
binSizeMb
CD、DVDなどの「ビン」のサイズに変更します。int binSizeMb = 650;
CD用。
注 –このbinSizeMb
値は、「メビバイト」と呼ばれることもあります。私の子供時代とは対照的に、すべてのバイトの倍数が「バイナリ」だったとき、「MB」は、コードで使用されている1,048,576バイトのメビバイト(MiB)ではなく、「10進数のメガバイト」または正確に1,000,000バイトを指すようになりました。これを変更したい場合const int bytesPerMb = 1048576;
は、コードの行をに変更してくださいconst int bytesPerMb = 1000000;
。
rootFileFolderPath
「ビンにパック」したいファイルを含むフォルダーのフルパスに変更します。string rootFileFolderPath = @"C:\MySecretBinFilesFolder";
。
いずれかの打撃でクエリを実行しF5たりクリックし実行したクエリ]タブの左側の上部にあるボタンを。
クエリコードは、rootFileFolderPath
フォルダー内のすべてのファイルを再帰的に列挙します。つまり、すべてのサブフォルダー内のファイルも含まれます。
次に、各ビン内のすべてのファイルの合計サイズが指定されたビンサイズ以下になるように、ファイルの「ビン」を作成します。
LINQPadの結果ウィンドウに2つのリストが表示されます。
最初のリストは、見つかったすべてのファイルのリストで、サイズの降順でリストされています。
2番目のリストは、「ファイルのパッキング」によって作成されたビンで、ファイルとそのサイズのリスト、およびビンの残りのサイズが含まれます。
次のスクリーンショットは、2番目のリストと作成された最初の2つのビンを示しています。
ウィキペディアによると、私が使用したアルゴリズム(First Fit Decreeasing(FFD)戦略)は悪くないはずです。ウィキペディアはこう述べています:
2007年に、FFDの11/9 OPT + 6/9の限界が厳しいことが証明されました。
「OPT」は最適な戦略を指します(到達できない可能性があるものとして、特定の実際の戦略ではありません)。
関連する数学的用語のやや曖昧な記憶に基づいて、これはFFD戦略が最悪の場合、最適な戦略が行うビンの数の〜1.22倍にアイテムをパックすることを意味するはずです。したがって、この戦略では、アイテムが4ではなく5つのビンにパックされる可能性があります。特定の「病理学的」アイテムサイズを除いて、パフォーマンスは最適に非常に近いと思われます。
同じウィキペディアの記事にも、「正確なアルゴリズム」があると記載されています。私もそれを実装することにするかもしれません。まず、アルゴリズムについて説明した論文を読む必要があります。
HitchhikerのHaskellのガイドにあるプログラムのバリアントの1つを、おそらくそのチュートリアルの一部を実行した後で使用できます。チュートリアルは、いくつかのディスクに物事を分散するというあなたの問題を正確に解決することを中心に書かれており、チュートリアルの第3章からの次の節に例示されているように、ソリューションは徐々に改良されます。
すでに十分な予備知識。いくつかのCDをパックしましょう。
すでにご存じかもしれませんが、私たちの問題は古典的な問題です。これは「ナップサックの問題」と呼ばれます (それが何であるかまだわからない場合は、グーグルで確認してください。100000以上のリンクがあります)。
貪欲な解決策から始めましょう...
これは同様の質問です(ただし、同じではありません:最適化は求められていません)。タスクに役立つソリューション/プログラムが見つかる場合があります(投稿される場合)。
一般に、Haskellコードは非常に表現力があり(Haskellは高度な抽象化をプログラミングするための言語であるため)、簡単に把握できます。
いずれかのソリューションのコードを見るとき、チュートリアルの第1章で説明したように、作成するプログラムの最上位構造は非常に単純であることを覚えておいてください。
ここで、プログラムがどのように動作し、それを疑似コードで表現するかについて少し考えてみましょう。
main = Read list of directories and their sizes. Decide how to fit them on CD-Rs. Print solution.
合理的に聞こえますか?私はそうだと思いました。
私たちの生活を少し単純化して、プログラムの外のどこかで(たとえば、 "
du -sb *
"を使用して)ディレクトリサイズを計算し、この情報をstdinから読み取ると仮定します。
ソリューションの各部分をさらに詳しく見ていきます。
何年も前に、そのようなタスクを実行するためのPHPスクリプトを作成しました:https : //bitbucket.org/borszczuk/php-backup-maker/
また、さまざまなディスク間でコピーするファイルとディレクトリを選択するDiscfitを試してください。