shell实现洗牌随机
洗牌问题:
洗一副扑克,有什么好办法?既能洗得均匀,又能洗得快?即相对于一个文件来说怎样
高效率的实现乱序排列?
关于洗牌问题,其实已经有了一个很好的shell解法,这里另外给三个基于AWK的方法,
有错误之处还请不吝指出。
方法一穷举:
类似于穷举法,构造一个散列来记录已经打印行出现行的次数,如果出现次数多于一
次则不进行处理,这样可以防止重复,但缺点是加大了系统的开销。
awk -v N=`sed -n '$=' data` '
BEGIN{
FS="\n";
RS=""
}
{
srand();
while(t!=N){
x=int(N*rand()+);
a[x]++;
if(a[x]==)
{
print $x;t++
}
}
}
' data
方法二变换:
基于数组下标变换的办法,即用数组储存每行的内容,通过数组下标的变换
交换数组的内容,效率好于方法一。
#! /usr/awk
BEGIN{
srand();
}
{
b[NR]=$;
}
END{
C(b,NR);
for(x in b)
{
print b[x];
}
}
function C(arr,len,i,j,t,x){
for(x in arr)
{
i=int(len*rand())+;
j=int(len*rand())+;
t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
方法三散列:
三个方法中最好的。
利用AWK中散列的特性(详细请看:info gawk 中的7.x ),只要构造一个
随机不重复的散列函数即可,因为一个文件每行的linenumber是独一无二的,所
以用:
随机数+每行linenumber ------对应------> 那一行的内容
即为所构造的随机函数。
从而有:
awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data
其实大家担心的使用内存过大的问题不必太在意,可以做一个测试:
测试环境:
PM .4GHz CPU,40G硬盘,内存256M的LAPTOP
SUSE 9.3 GNU bash version 3.00. GNU Awk 3.1.
产生一个五十几万行的随机文件,大约有38M:
od /dev/urandom |dd count= >data
拿效率较低的方法一来说:
洗牌一次所用时间:
time awk -v N=`sed -n '$=' data` '
BEGIN{
FS="\n";
RS=""
}
{
srand();
while(t!=N){
x=int(N*rand()+);
a[x]++;
if(a[x]==)
{
print $x;t++
}
}
}
' data
结果(文件内容省略):
real 3m41.864s
user 0m34.224s
sys 0m2.102s
所以效率还是勉强可以接受的。
方法二的测试:
time awk -f awkfile datafile
结果(文件内容省略):
real 2m26.487s
user 0m7.044s
sys 0m1.371s
效率明显好于第一个。
接着考察一下方法三的效率:
time awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data
结果(文件内容省略):
real 0m49.195s
user 0m5.318s
sys 0m1.301s
对于一个38M的文件来说已经相当不错了。
玩的愉快!
shell实现洗牌随机的更多相关文章
- 对数组排序进行"洗牌"(随机排序)
这段代码在这里使用Fisher Yates洗牌算法给一个指定的数组进行洗牌(随机排序). function shuffle(arr) { var i, j, tem ...
- Shell脚本实现乱序排列文件内容的多种方法(洗牌问题)
洗牌问题:洗一副扑克,有什么好办法?既能洗得均匀,又能洗得快?即相对于一个文件来说怎样高效率的实现乱序排列? ChinaUnix 确实是 Shell 高手云集的地方,只要你想得到的问题,到那里基本上都 ...
- Hard 随机洗牌函数 @CareerCup
第i个元素和index在[i,length-1]之间的一个数随机交换 package Hard; import CtCILibrary.AssortedMethods; /** * * Write a ...
- Craking the coding interview 面试题:完美随机洗牌
给定一个序列,随机打乱这个序列,新产生的序列和任意一个序列产生的可能性是一样的,就是所谓的完美随机洗牌. 看下面的运行结果: 上面第一列是原数列,下面一行是新产生的打乱的数列. 基本思想:如果n-1个 ...
- 随机洗牌算法Knuth Shuffle和错排公式
Knuth随机洗牌算法:譬如现在有54张牌,如何洗牌才能保证随机性.可以这么考虑,从最末尾一张牌开始洗,对于每一张牌,编号在该牌前面的牌中任意一张选一张和当前牌进行交换,直至洗到第一张牌为止.参考代码 ...
- 实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)
实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例) 1.namedtuple:命名元组,可以创建一个没有方法只有属性的类 from collections import namedtup ...
- random array & shuffle 洗牌算法 / 随机算法
random array & shuffle shuffle 洗牌算法 / 随机算法 https://en.wikipedia.org/wiki/Fisher–Yates_shuffle ES ...
- VB洗牌算法产生随机数组
算法图示: 运行效果: 详细代码: Option Explicit '洗16张牌(0-15),方便用十六进制显示 Dim Card() As Long Private Sub 洗牌() Dim i&a ...
- 如何随机排序数组?使用多种方式!递归,迭代,洗牌,sort方法!
方式1: 使用sort 方法 ---- // 方法1 使用sort 方法 var arr = [1,2,3,4,5,6,7,8]; function foo(arr) { var cloneArr = ...
随机推荐
- 【最小割】【Dinic】【强联通分量缩点】bzoj1797 [Ahoi2009]Mincut 最小割
结论: 满足条件一:当一条边的起点和终点不在 残量网络的 一个强联通分量中.且满流. 满足条件二:当一条边的起点和终点分别在 S 和 T 的强联通分量中.且满流.. 网上题解很多的. #include ...
- [POI2010]Frog
题目大意: 一个数轴上有n个点,现在你要在这些点上跳. 每次跳的时候你只能跳到离这个点第k近的点上,而且要连续跳m次. 问从每一个点出发,最后分别会在哪一个点结束. 思路: 首先可以维护一个大小为k+ ...
- 1.4(java学习笔记) 面向对象内存分析
首先介绍几个概念 栈: 1.栈是方法执行的内存模型,每调用一个方法都会创建一个栈帧. 2.jvm为每个线程创建一个栈,存放方法相关信息,栈属于线程私有不共享. 3.栈由系统自动分配,是连续的内存空 ...
- Problem Q: 零起点学算法12——求2个日期之间的天数
#include<stdio.h> int main() { int a1,b1,c1,a2,b2,c2,s; scanf("%d-%d-%d",&a1,&am ...
- CentOS 6.9系统时间和硬件时间设置(转)
总结一下hwclock,这个容易晕: 1)/etc/sysconfig/clock 文件,只对 hwclock 命令有效,且只在系统启动和关闭的时候才有用(修改了其中的 UTC=true 到 UTC= ...
- 在Code First中自动创建Entity模型
之前我在博客文章中介绍过如何使用Code First来创建数据库,通过CodeFirst的方式,可以大幅的减少开发人员的工作量,比传统的先创建库再ORM的方式简单了不少.但是,很多时候,特别是一些MI ...
- centos 7.3systemctl工具
http://www.cnblogs.com/tswcypy/p/4479153.html
- 转载:oracle11G 已开启监听,但远程连接依旧无监听解决过程
1.连接数据库显示无监听程序,首先查看服务器的oracle监听服务是否开启,服务名称:OracleOraDb11g_home1TNSListener(具体环境中可能不完全一样,但是认准TNSListe ...
- mysql 中查询一个字段是否为null的sql
查询mysql数据库表中字段为null的记录: select * 表名 where 字段名 is null 查询mysql数据库表中字段不为null的记录: select * 表名 where 字段名 ...
- firefox dispatchevent的问题
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8&qu ...