perl 取出放回且子集不重复的组合情况

#!/usr/bin/env perl
use warnings;
use strict;
die "perl $0 <样本总个数> <样本子集组合> <样本子集>\n
e.g. perl $0 96 100 2 > 96.txt \n
" unless @ARGV eq 3;

my $sample =  $ARGV[0]; # 样本数目
my $n = $ARGV[1]; # 取出样本的子集数目
my $ex_samp = $ARGV[2]; # 取出样本的个数

my $fac_samp = &fac($sample);
my $fac_ex_samp = &fac($ex_samp);

die "不可能取出比样本数目还要多的情况!!!" if($sample < $ex_samp);
my $c = $fac_samp / ($fac_ex_samp * &fac($sample - $ex_samp));
die "这是一个取出有放回且子集不重复的组合,取出的子集组合不能大于全集所有可能的排列组合!!!" if($n > $c);

my %hash;
for(my $i = 0;$i < $n; $i ++)
{
	my @sub;
	for(my $j = 0; $j < $ex_samp; $j ++)
	{
		push @sub, int(rand($sample) + 1);
	}
	my $str = join "-", sort @sub;
	my $repeat;
	my %rep;
	foreach my $k(@sub)
	{
 		 $rep{$k} ++;
 		 if($rep{$k} eq 2)
		 {
 			  $repeat = 1;
 			  last;
 		 }
	}
	if(exists $hash{$str} or $repeat eq 1)
	{
		$n ++;
	}else{
		$hash{$str} = 0;
		print "$str\n";
	}
}

#print "$n\n";

sub fac(){
	if($_[0] eq 1)
	{
		return 1;
	}elsif($_[0] eq 0){
		return 1; #可以写0,不过1更好,因为涉及到组合的公式~
	}else{
		return ($_[0] * &fac($_[0] - 1));
	}
}
总的来说,满足等概率取出样本,并且组合形式不重复,涉及到了一些高中的知识,还好没忘。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值