[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[技术讨论] 玩Perl的还活着吗?出个锻炼题:给出两堆数,找出和相同的组合

本帖最后由 523066680 于 2014-8-29 11:55 编辑

其实我刚刚写出来。

实际应用举例:你出了N批货给不同客户,有的客户是一批货分好几次转账付款,有些客户是几批货合并为1个款项转账付款。
但是这些客户一直没有找你对账,有的货款还未收到,他们的付款人姓名也不是其本人,难以分辨哪一笔相对应。通过程序筛出配对的组合,可以辅助判断

俩数组:
@numa = qw/
1
14
72
24
53
66
77
8
/;

@numb = qw/123 344 22 77/;


求出的他们之中,和相同的部分,包括单个元素等于另一个数组多个元素相加的情况:

───────────────────────┐
200                                           │
        A -> 1,72,53,66,8                     │
        B -> 123,77                           │
145                                           │
        A -> 1,14,53,77                       │
        B -> 123,22                           │
99                                            │
        A -> 1,24,66,8 | 14,24,53,8 | 14,77,8 │
        B -> 22,77                            │
77                                            │
        A -> 24,53 | 77                       │
        B -> 77                               │
123                                           │
        A -> 14,24,77,8                       │
        B -> 123                              │
22                                            │
        A -> 14,8                             │
        B -> 22                               │
───────────────────────┘

题目看着挺难的,,,目前perl还停留在helloworld阶段。

TOP

Mark,let me think.

TOP

本帖最后由 523066680 于 2014-9-1 21:49 编辑

直接贴代码了。
思路就是通过组合方法,递归列出两列数各自的组合情况,将每一个组合的合计存储到
%A, %B 哈希表中,然后遍历%A %B 把同类项并排列出。如果是对小范围随机数据
进行匹配,相同的情况可能会很多。但实际应用中,合计金额的独立性会强很多。
  1. use IO::Handle;
  2. STDOUT->autoflush(1);
  3. my (@cupa, @cupb);
  4. my (@numa, @numb);
  5. my (%A, %B);
  6. @numa = qw/
  7. 1
  8. 14
  9. 72
  10. 24
  11. 53
  12. 66
  13. 77
  14. 8
  15. /;
  16. @numb = qw/123 344 22 77/;
  17. &func(\@cupa, \@numa, \%A);
  18. &func(\@cupb, \@numb, \%B);
  19. my ($fa, $fb);
  20. foreach $fa (keys %A) {
  21.     foreach $fb (keys %B) {
  22.         if ($fa == $fb) {
  23.             print $fa, "\n",
  24.                 "\tA -> ",
  25.                 join(" | ", @{$A{$fa}}),
  26.                 "\n\tB -> ",
  27.                 join(" | ", @{$B{$fb}}),
  28.                 "\n";
  29.         }
  30.     }
  31. }
  32. sub func {
  33.     my ($a, $b, $h) = (shift, shift, shift);
  34.     my @ar;
  35.     my @br;
  36.     my $i;
  37.     my $sum=0;
  38.     my $allnum="";
  39.     if (scalar(@{$a}) > 0) {
  40.         foreach (@{$a}) {
  41.             $sum += $_;
  42.         }
  43.         $allnum = join(",",@{$a});
  44.         push @{$h->{$sum}}, $allnum;
  45.     }
  46.     foreach $i (0..$#{$b}) {
  47.         @ar=(@{$a}, $b->[$i]);
  48.         @br=@{$b}[$i+1..$#{$b}];
  49.         &func(\@ar, \@br, $h);
  50.     }
  51. }
复制代码

TOP

用Win32::OLE 操作EXCEL 进行数据连线的东西也写好了
首先进行一一匹配,然后才对剩下的数据进行组合匹配,尽量使用元素较少的组合进行连线:
(以下数据纯属虚构)

TOP

真的没有人玩perl啊?

TOP

呵呵,以前工作上有要用到类似的情况,也写过一个简单的Perl Script:
  1. use Math::Combinatorics;
  2. #sum.pl by y6cmE 9044185@qq.com
  3. $|=1;
  4. print "请输入要计算的合计数:";
  5. my $C=<>;
  6. chomp $C;
  7. print "请输入要匹配一次或多次,一次为1,多次为其它数,如2:";
  8. my $B=<>;
  9. chomp $B;
  10. print "请输入最少几个数开始匹配,如1:";
  11. my $X=<>;
  12. chomp $X;
  13. print "请输入最多几个数结束匹配,如9:";
  14. my $Y=<>;
  15. chomp $Y;
  16. open(C,">结果.txt") or die;
  17. open(A,"数组.txt") or die;
  18. while(my $line=<A>){
  19. chomp $line;
  20. push(@N,$line);
  21. }
  22. close A;
  23. foreach my $p($X..$Y){
  24. my $combinat=Math::Combinatorics->new(count=>$p,data=>[@N]);
  25. while(my @combo=$combinat->next_combination){
  26. my $num=0;
  27. foreach my $o(@combo){
  28. $num=$num+$o;
  29. }
  30. if($num eq $C){
  31. print "@combo\n";
  32. print C "@combo\n";
  33. if($B == 1){
  34. close C;
  35. <>;
  36. exit;
  37. }
  38. }
  39. }
  40. }
  41. close C;
  42. <>;
复制代码
1

评分人数

Just another Perl hacker

TOP

返回列表