Chinaunix首页 | 论坛 | 博客
  • 博客访问: 135325
  • 博文数量: 13
  • 博客积分: 431
  • 博客等级: 下士
  • 技术积分: 166
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-18 14:59
文章分类

全部博文(13)

文章存档

2012年(9)

2011年(4)

分类: Python/Ruby

2012-03-02 21:22:21

    我是个游戏迷,经常会下载各种游戏ROM,有的时候从不同网站会下载到相同的ROM,但是文件名称会略有不同(有的区别也非常大),因为ROM非常多,有上万个,如果要手动使用diff命令比较的话非常浪费时间,所以我决定使用脚本写一个,刚好我安装了cygwin,刚好上面的perl可以拿来用:-)

    一个最直观的想法是将每一个ROM分别与其他ROM进行比较,这种方法的时间复杂度想当可观:O(n!),我在简单的尝试一下就放弃了。大概每次调用diff需要0.1秒(这是比较两个40k的ROM需要的时间,大部分的rom都远大于此),有兴趣的可以算一下2000个ROM需要执行多久。

    显然,diff是一个非常消耗时间的操作,如果能尽可能的减少其调用次数的话,就可以显著的提高效率。并不是每两个rom都需要进行比较的,我们可以从这些rom中提取某些属性,并且认为具有相似或相同属性的rom才值得我们去比较。

    基于这种思路,我们可以使用文件的大小作为hash的key,这样一来,只有大小相同的ROM才会进行比较。这种说法并不十分准确,因为hash可能会将不同的key映射到同一个bucket,但是perl中没有map,所以只好退而求其次了。好在在我使用的过程中这种情况出现的不多。

代码如下,注释已经相当详细了。
  1. #!/usr/bin/perl -w

  2. use strict;
  3. use warnings;

  4. use lib "$ENV{'HOME'}/bin/lib/";

  5. # 个人使用的cmd库,提供了cmd函数用来执行一个shell命令,并将执行结果和输出返回
  6. use cmd;

  7. # 将命令行传入的文件名末尾的\n去掉
  8. map(chomp($_), @ARGV);

  9. # 将文件按照不同的大小放入哈希表
  10. my %size_hash;

  11. # 处理命令行传入的每一个文件
  12. foreach my $file (@ARGV) {
  13.     # 获取文件大小
  14.     my $size = sizeof($file);

  15.     # 与size大小的文件列表逐一比较
  16.     foreach my $same_size (@{$size_hash{$size}}) {
  17.         my ($rv, @outs) = cmd("diff \"$file\" \"$same_size\"");
  18.         if ($rv == 0) {
  19.             # 找到大小相同且内容一致的文件
  20.             print("$file & $same_size are the same!\n");
  21.         }
  22.     }

  23.     # 将文件放入对应size的文件列表
  24.     push(@{$size_hash{$size}}, $file);
  25. }

  26. sub sizeof {
  27.     my ($file) = @_;

  28.     # 利用du -b获取文件大小,-b参数会返回文件的字节数
  29.     my ($rv, @outs) = cmd("du -b \"$file\"");
  30.     if ($rv != 0) {
  31.         print("@outs\n");
  32.     }

  33.     # 去掉多余的空白字符,将结果保存到size中
  34.     $outs[0] =~ /(.+)\s/;
  35.     my $size = $1;

  36.     return $size;
  37. }
BTW: 有些游戏ROM本身比较大,而且大小常常比较固定,比如FC ROM的典型大小:40K/128K/256K/512K,这可能会造成我们以大小为key的哈希出现较多碰撞,其实解决方法也非常简单:压缩一下。这不仅仅使得碰撞次数减少,而且因为文件本身小了,diff也会进一步提高效率。再者,一般模拟器都会支持压缩格式的ROM。真是一举多得啊!
阅读(5179) | 评论(0) | 转发(0) |
0

上一篇:螺旋矩阵的C实现

下一篇:没有了

给主人留下些什么吧!~~