免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4095 | 回复: 19
打印 上一主题 下一主题

关于perl的排列组合问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-10-10 17:55 |只看该作者 |倒序浏览
今天碰到一个问题,特来请教
有8个数,(01,13,15,18,33,55,99,109),从中取出4个,列出所有的组合,组合中不能有重复的,就是说01,13,15,18和18,13,15,01算一种,大家看看这个怎么弄,我查了很多算法,没有想到好的办法.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2006-10-10 18:35 |只看该作者
刚写了一个,不太好。估计用 map 可以在 3 行之内搞定。
  1. use strict;
  2. use warnings;

  3. sub foo($$$);

  4. my @array = (01,13,15,18,33,55,99,109);

  5. foo(\@array, 4, []);

  6. sub foo($$$){
  7.     my ($rarry, $level, $result) = @_;

  8.     unless($level){
  9.         print join ',', @$result, "\n";
  10.         return;
  11.     }

  12.     foreach my $i (0..@$rarry-1){
  13.         push @$result, $rarry->[$i];
  14.         foo( [@$rarry[0..$i-1], @$rarry[$i+1..$#$rarry]], $level-1, $result );
  15.         pop @$result;
  16.     }
  17. }
复制代码

论坛徽章:
0
3 [报告]
发表于 2006-10-10 19:39 |只看该作者
我运行了一下,发现有重复的

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
4 [报告]
发表于 2006-10-10 20:01 |只看该作者
这是使用 Recursive call 去写吗??
sub foo($$$){

}

可以写成下面那样吗??
sub foo{
}

($$$) 加上这用意为什么??? 是因为前面有sub foo($$$); 宣告吗??

foo(\@array, 4, []); #  参数 [] 是什么意思???

谢谢

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2006-10-10 21:08 |只看该作者
原帖由 shucho 于 2006-10-10 19:39 发表
我运行了一下,发现有重复的

没有的。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2006-10-10 21:09 |只看该作者
原帖由 shihyu 于 2006-10-10 20:01 发表
这是使用 Recursive call 去写吗??
sub foo($$$){

}

可以写成下面那样吗??
sub foo{
}

($$$) 加上这用意为什么??? 是因为前面有sub foo($$$); 宣告吗??

foo(\@array, 4, []); #  参数 [] 是什么意 ...

sub foo($$$) 这个是原型,参见 perldoc perlsub
原型的作用是在调用时进行强制性的参数检查。不过调用时前面加 & 可以规避检查。
[] 是匿名数组。

论坛徽章:
0
7 [报告]
发表于 2006-10-10 21:31 |只看该作者
原帖由 flw 于 2006-10-10 21:08 发表

没有的。



  1. use strict;
  2. use warnings;

  3. sub foo($$$);

  4. my @array = (01,13,15,18);

  5. foo(\@array, 4, []);

  6. sub foo($$$){
  7.     my ($rarry, $level, $result) = @_;

  8.     unless($level){
  9.         print join ',', @$result, "\n";
  10.         return;
  11.     }

  12.     foreach my $i (0..@$rarry-1){
  13.         push @$result, $rarry->[$i];
  14.         foo( [@$rarry[0..$i-1], @$rarry[$i+1..$#$rarry]], $level-1, $result );
  15.         pop @$result;
  16.     }
  17. }
复制代码


如果是4个元素的数组,那么应该只有一种组合,但是如果运行一下,会发现
$ perl prog | wc -l
      24
这应该不对吧

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2006-10-10 22:08 |只看该作者
哦,我搞成排列了,不是组合。

论坛徽章:
0
9 [报告]
发表于 2006-10-10 22:19 |只看该作者
我想到一个很笨的办法。

一开始还是做排列组合,定义中间结果为一个HASH, 数据结构为:
HASH =
{
[01,13,15,18] => 6, ## 6 = 0+1+2+3,为下标的和
[13,01,15,18] => 6, ## 6 = 1+0+2+3, 同上
[...] => N,
...,
...
}
然后反转一下HASH,这样就得到了最终结果(values HASH)
虽然很土,但是应该奏效。

我看了一下算法书,可能是图论(有向图)或者计算几何(多边形)的内容,不过我不是学计算机的,不是很清楚,别笑我

[ 本帖最后由 shucho 于 2006-10-10 22:20 编辑 ]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
10 [报告]
发表于 2006-10-10 22:56 |只看该作者
原帖由 shucho 于 2006-10-10 22:19 发表
我想到一个很笨的办法。

一开始还是做排列组合,定义中间结果为一个HASH, 数据结构为:
HASH =
{
[01,13,15,18] => 6, ## 6 = 0+1+2+3,为下标的和
[13,01,15,18] => 6, ## 6 = 1+0+2+3, 同上
[.. ...





6 = 0+1+2+3
6 = 1+0+2+3

用组数组存放组合数总和如果又出现一样总和就不要

  1. sub foo($$$){

  2. 我是觉得可以在这里面直接判断 用 if + 数组判断
  3. }
复制代码

[ 本帖最后由 shihyu 于 2006-10-10 22:58 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP