免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: mpstat
打印 上一主题 下一主题

[文本处理] 码农的欧洲杯:欢迎各路神仙和高手挑战! [复制链接]

论坛徽章:
0
51 [报告]
发表于 2012-06-15 11:23 |只看该作者
回复 57# hjason2042

所以用我的比较好,直接比较日期,就是逻辑比较绕
   

论坛徽章:
0
52 [报告]
发表于 2012-06-15 16:22 |只看该作者
赌。。。

论坛徽章:
0
53 [报告]
发表于 2012-06-17 00:06 |只看该作者
回复 1# mpstat
题目很有意思,谢谢lz提供了这么有趣的题目~膜拜一下前面的awk大牛们~
我用的是perl。
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;

  4. open my $fi, '<', "name.txt";
  5. my ( %hash, $group, $nation, $coach, $caption );
  6. while ( <$fi> ) {
  7.     chomp;
  8.     if ( /^\s*$/ or /^\s*#/) {
  9.         next;
  10.     }
  11.     if ( /^Group (\w)$/ ) {
  12.         $group = $1;
  13.         next;
  14.     }
  15.     if ( /^(\w+)$/ ) {
  16.         $nation = $1;
  17.         next;
  18.     }
  19.     if ( /^Head coach:\s+(.*) \((.*)\)$/ ) {
  20.         $coach = { 'name' => $1, 'nation' => $2,};
  21.         next;
  22.     }
  23.     if ( /^\s+\d+/ ) {
  24.         if    (/^\s+\d+  (\w{2})  (.+?) \(c\)\s+\((\d{4})-(\d{2})-(\d{2})\)\s+\(aged (\d+)\)\s+(.+)$/ ) {
  25.             #              posi    name                      birth                    age      club
  26.             $caption = 1;
  27.         }
  28.         elsif (/^\s+\d+  (\w{2})  (.+?)\s+\((\d{4})-(\d{2})-(\d{2})\)\s+\(aged (\d+)\)\s+(.+)$/ ) {
  29.             #              posi    name                 birth                   age       club
  30.             $caption = 0;
  31.         }
  32.         # some player with the same name, and set the key = $nation.'_'.$name
  33.         $hash{$nation.'_'.$2} = { 'posi'    => $1,
  34.                                   'birth'   => $3.$4.$5,
  35.                                   'age'     => $6,
  36.                                   'club'    => $7,
  37.                                   'caption' => $caption,
  38.                                   'group'   => $group,
  39.                                   'nation'  => $nation,
  40.                                   'coach'   => $coach->{'name'},
  41.                                 };
  42.     }
  43. }
  44. close $fi;

  45. # 1. Get the Youngest player
  46. my @names = map { (split /_/, $_)[1] } keys %hash;
  47. my @birth = map { $hash{$_}->{'birth'} } keys %hash;
  48. my @a = sort {$birth[$a]<=>$birth[$b]} 0..$#birth;
  49. print "\n1. The youngest player(s) is(are):\n";
  50. print "\t$names[$a[$_]]\t$birth[$a[$_]]\n" foreach &get_idx_with_same_value(\@a, \@birth, 'end');

  51. # 2. Get the Oldest player
  52. print "\n2. The oldest player(s) is(are):\n";
  53. print "\t$names[$a[$_]]\t$birth[$a[$_]]\n" foreach &get_idx_with_same_value(\@a, \@birth, 'head');

  54. # 3. Get the day on which most people are birth
  55. my %hash3;
  56. foreach ( @birth ) {
  57.     /(\d\d)$/;
  58.     $hash3{$1}++;
  59. }
  60. my @keys = keys %hash3;
  61. my @values = values %hash3;
  62. @a = sort {$values[$a]<=>$values[$b]} 0..$#values;
  63. print "\n3. The most birth day(s) is(are):\n";
  64. print "\t$keys[$a[$_]]\t$values[$a[$_]]\n" foreach &get_idx_with_same_value(\@a, \@values, 'end');

  65. # 4. Get the same birthday with me
  66. my @same_birth;
  67. foreach ( keys %hash ) {
  68.     push @same_birth, $_ if $hash{$_}->{'birth'} == '19820501';
  69. }
  70. my $same_birth = join ', ', map { (split /_/, $_)[1] } @same_birth;
  71. if ( $same_birth ) {
  72.     print "\n4. Player with the same birthday with me are(is):\n\t$same_birth\n";
  73. }
  74. else {
  75.     print "\n4. No one has the same birthday with me.\n";
  76. }

  77. # 5. Get the nation and coach and group of one input name
  78. print "\n5. Please input one player name:\n";
  79. my $flag = 0;
  80. my $input = <STDIN>;
  81. chomp $input;
  82. foreach ( keys %hash ) {
  83.     if ( $input eq (split /_/, $_)[1] ) {
  84.         $flag = 1;
  85.         print "$input:\n\tnation: ".$hash{$_}->{'nation'}."\n\tcoach: ".$hash{$_}->{'coach'}."\n\tgroup: ".$hash{$_}->{'group'}."\n"
  86.     }
  87. }
  88. print "ERROR: non exist player: \"$input\"\n" if $flag == 0;

  89. # 6. Get the club with most people
  90. my %hash6;
  91. $hash6{$hash{$_}->{'club'}}++ for keys %hash;
  92. @keys = keys %hash6;
  93. @values = values %hash6;
  94. @a = sort {$values[$a]<=>$values[$b]} 0..$#values;
  95. print "\n6. The club(s) with most people is(are):\n";
  96. print "\t$keys[$a[$_]]\t$values[$a[$_]]\n" foreach &get_idx_with_same_value(\@a, \@values, 'end');

  97. # 7. Get the position that most caption play
  98. my %hash7;
  99. foreach ( keys %hash ) {
  100.     $hash7{$hash{$_}->{'posi'}}++ if $hash{$_}->{'caption'};
  101. }
  102. @keys = keys %hash7;
  103. @values = values %hash7;
  104. @a = sort {$values[$a]<=>$values[$b]} 0..$#values;
  105. print "\n7. The position(s) with most caption is(are):\n";
  106. print "\t$keys[$a[$_]]\t$values[$a[$_]]\n" foreach &get_idx_with_same_value(\@a, \@values, 'end');

  107. # 8. Get the number of people older than me
  108. my $older_than_me = 0;
  109. foreach ( keys %hash ) {
  110.     $older_than_me++ if $hash{$_}->{'birth'} < '19771029';
  111. }
  112. if ( $older_than_me ) {
  113.     print "\n8. The number older than me is: $older_than_me\n";
  114. }
  115. else {
  116.     print "\n8. No one is older than me!\n";
  117. }

  118. # 9. Get the day no one is birth
  119. my @first_9_day = qw(01 02 03 04 05 06 07 08 09);
  120. my @monthes = @first_9_day;
  121. push @monthes, qw(10 11 12);
  122. my @days = @first_9_day;
  123. push @days, 10..29;
  124. my $num;
  125. my @birth_days;
  126. for $num ( @monthes ) {
  127.     push @birth_days, $num.$_ foreach @days;
  128. }
  129. push @birth_days, qw(0130 0131 0330 0331 0530 0531 0730 0731 0830 0831 1030 1031 1230 1231 0430 0630 0930 1130);

  130. my %hash9 = map { $_ => 1 } @birth_days;
  131. foreach ( keys %hash ) {
  132.     my $player = $_;
  133.     $hash{$player}->{'birth'} =~ /(\d\d\d\d)$/;
  134.     $hash9{$1} = 0;
  135. }
  136. my @no_one_birth = sort { $a<=>$b } grep { $hash9{$_} } keys %hash9;
  137. if ( @no_one_birth ) {
  138.     print "\n9. The day(s) no one is birth is(are):\n\t@no_one_birth\n"
  139. }
  140. else {
  141.     print "\n9. Any day has a player birth\n";
  142. }

  143. # 10. Get the number of each position
  144. my %hash10;
  145. foreach ( keys %hash ) {
  146.     my $posi = $hash{$_}->{'posi'};
  147.     $hash10{$posi}++;
  148. }
  149. print "\n10. The numbers of each postion are:\n";
  150. print "\t$_: $hash10{$_}\n" for keys %hash10;

  151. # subroutine(s)
  152. sub get_idx_with_same_value {
  153.     my ( $r_idx, $r_array, $locate ) = @_;
  154.     my @array;
  155.     if ( $locate eq 'head' ) {
  156.         my $cnt = 0;
  157.         my $mark = $r_array->[$cnt];
  158.         while ( $mark == $r_array->[$cnt] ) {
  159.             push @array, $cnt;
  160.             $cnt++;
  161.         }
  162.     }
  163.     elsif ( $locate eq 'end' ) {
  164.         my $cnt = @$r_idx - 1;
  165.         my $mark = $r_array->[$cnt];
  166.         while ( $mark == $r_array->[$cnt] ) {
  167.             push @array, $cnt;
  168.             $cnt--;
  169.         }
  170.     }
  171.     else {
  172.         die "ERROR!!!\n";
  173.     }
  174.     return @array;
  175. }
复制代码
子函数get_idx_with_same_value是考虑可能有并列的情况而设计的。
perl是在windows下的cmd里运行出来的,最近才开始用windosw下的perl的,输出结果不知道怎么copy,尴尬。

论坛徽章:
15
2015年辞旧岁徽章
日期:2015-03-03 16:54:15双鱼座
日期:2015-01-15 17:29:44午马
日期:2015-01-06 17:06:51子鼠
日期:2014-11-24 10:11:13寅虎
日期:2014-08-18 07:10:55酉鸡
日期:2014-04-02 12:24:51双子座
日期:2014-04-02 12:19:44天秤座
日期:2014-03-17 11:43:36亥猪
日期:2014-03-13 08:13:51未羊
日期:2014-03-11 12:42:03白羊座
日期:2013-11-20 10:15:18CU大牛徽章
日期:2013-04-17 11:48:45
54 [报告]
发表于 2012-06-17 14:44 |只看该作者
hjason2042 发表于 2012-06-14 22:06
回复 7# rdcwayx
版大,问题1、2的代码有点小BUG哦。
int(d)返回结果是年,不包括月、日。假如有两个人的 ...


谢谢指正。
  1. awk -F"[()]" -v min=100000000 '{d=(NF==7)?$4:$2;gsub(/-/,"",d)}
  2.     NR==FNR&&/-/{min=(min>int(d))?d:min;max=(max<d)?d:max}
  3.     NR>FNR&&/-/{if (min==d) print "The oldest player is " , substr($1,10),min;
  4.                 if (max==d) print "The youngest player is " , substr($1,10),max}' name.txt name.txt
复制代码

论坛徽章:
0
55 [报告]
发表于 2012-06-17 20:03 |只看该作者
回复 8# jils2013

第三个问题,解答不准确哦..
出生日期在同一天的不止一组结果..
   

论坛徽章:
0
56 [报告]
发表于 2012-06-17 20:32 |只看该作者
回复 7# rdcwayx

第6个问题,应该是
  1. if (++a[$NF]>max)
复制代码
结果应该是
  1. 13  Bayern Munich
复制代码

论坛徽章:
15
2015年辞旧岁徽章
日期:2015-03-03 16:54:15双鱼座
日期:2015-01-15 17:29:44午马
日期:2015-01-06 17:06:51子鼠
日期:2014-11-24 10:11:13寅虎
日期:2014-08-18 07:10:55酉鸡
日期:2014-04-02 12:24:51双子座
日期:2014-04-02 12:19:44天秤座
日期:2014-03-17 11:43:36亥猪
日期:2014-03-13 08:13:51未羊
日期:2014-03-11 12:42:03白羊座
日期:2013-11-20 10:15:18CU大牛徽章
日期:2013-04-17 11:48:45
57 [报告]
发表于 2012-06-18 08:32 |只看该作者
hjason2042 发表于 2012-06-17 20:32
回复 7# rdcwayx

第6个问题,应该是结果应该是


谢谢指正, 写得快了,没注意。

论坛徽章:
0
58 [报告]
发表于 2012-06-19 15:48 |只看该作者
码农的自娱自乐啊!

论坛徽章:
0
59 [报告]
发表于 2012-06-23 00:38 |只看该作者
本帖最后由 bintre 于 2012-06-23 01:04 编辑

1.年纪最小的人
perl -nale 'print "$1\t$_" if /(\d{4}.*?)\)/;' name.txt |sort -k 1 -r  |tail -1
2.年纪最大的人
perl -nale 'print "$1\t$_" if /(\d{4}.*?)\)/;' name.txt |sort -k 1 -r  |head -1
3.哪一天出生的人最多
perl -nale '$a{$1}++ if /(\d{4}.*?)\)/; END{ print  map{"$_\t$a{$_}\n"}  keys %a}' name.txt  |sort  -k 2 -r |head
4.和你生日相同的人,如果有的话找出来
perl -nale 'print "$1\t$_" if /(\d{4}.*?)\)/;' name.txt  |grep yyyy-mm-dd
5.给定一个球员名,列出国籍与教练,处在哪个小组
这个麻烦了,跳过
6.哪个俱乐部的人最多
perl -nale '$a{$1}++  if /\s*\d+.*\s+(.*?)\r$/; END{print "$_\t $a{$_} " for keys %a  }' name.txt  |sort -k 2 | tail -2
7.队长里打什么位置的最多
什么是队长的标志啊?
perl -nale '$a{$1}++  if /^\s*\d+.*?\s+(.*?)\s+.*\r$/; END{print "$_\t $a{$_} " for keys %a  }' name.txt  |sort -k 1 | tail
8.比你年纪大的有多少人
perl -nale 'print "$1\t$_" if /(\d{4}.*?)\)/;' name.txt |sort -k 1 -r  |perl -F\\t -nale 'print if $F[0] lt "yyyy-mm-dd" ' |wc -l
9.列出365天里所有人都不过生日的日期
perl   -nale 'BEGIN{ %c;  for $a ("01".."12")  { for $b ("01".."31") {$c{"$a-$b"}=1} }}; $c{"$1-$2"}=0  if /\d{4}-(\d{2})-(\d{2})\)/; END{    for (keys %c) {print "$_"if $c{$_}==1 } }' name.txt    |grep -E -v  "02-29|02-30|02-31|04-31|06-31|09-31|11-31"|wc -l
10.打各个位置的人一共有多少
perl -nale '$a{$1}++  if /^\s*\d+.*?\s+(.*?)\s+.*\r$/; END{print "$_\t $a{$_} " for keys %a  }' name.txt  |sort -k 1 | less

如果有错请指错,谢谢

论坛徽章:
0
60 [报告]
发表于 2012-06-25 16:53 |只看该作者
本帖最后由 ryh19860922 于 2012-06-25 16:59 编辑

1.年纪最小的人
  1. [ryh@localhost ~]$ awk -F"[()]" '/aged/{date=(NF==7)?$4:$2; gsub(/-/,"", date); if(date-temp>0||temp==0) {temp=date; str=$0} }END{print str}' name.txt
  2. 15  DF  Jetro Willems        (1994-03-30)  (aged 18) PSV
复制代码
2.年纪最大的人
  1. [ryh@localhost ~]$ awk -F"[()]" '/aged/{date=(NF==7)?$4:$2; gsub(/-/,"", date); if(date-temp<0||temp==0) {temp=date; str=$0} }END{print str}' name.txt
  2.   1  GK  Kostas Chalkias           (1974-05-30)  (aged 38) P.A.O.K.
复制代码
3.哪一天出生的人最多
  1. [ryh@localhost ~]$ awk -F"[()]" '/aged/{date=(NF==7)?$4:$2;num[date]++} END{for(date in num) {print num[date],"\t", date|"sort -rn"}}' name.txt
  2. 2        1989-05-31
  3. 2        1987-07-28
  4. 2        1987-01-27
  5. 2        1987-01-22
  6. 2        1986-09-08
  7. 2        1985-08-20
  8. 2        1984-12-13
  9. 2        1984-06-28
  10. 2        1983-07-07
  11. 2        1982-05-01
  12. 2        1981-10-29
  13. 2        1981-10-03
复制代码
  1. [ryh@localhost ~]$ awk -F"[()]" '/aged/{date=(NF==7)?$4:$2; date=substr(date,6); num[date]++} END{for(date in num) print (num[date], "\t", date) |"sort -rn"}' name.txt
  2. 4        07-07
  3. 4        06-09
  4. 4        03-30
复制代码
4.和你生日相同的人,如果有的话找出来
  1. [ryh@localhost ~]$  grep '1986-09-22' name.txt
复制代码
5.给定一个球员名,列出国籍与教练,处在哪个小组
  1. [ryh@localhost ~]$  tac name.txt| awk 'BEGIN{flag=0} {if($0~/Philipp Lahm/) {flag=1}; if(flag==1 && $0~/Head coach/) {print $0; num=NR; flag=2}; if(NR==num+2 && flag==2) {print $0}; if($0~/Group/&&flag==2){print $0; exit}}'
  2. Head coach:  Joachim Low (Germany)
  3. Germany
  4. Group B
复制代码
6.哪个俱乐部的人最多
  1. [ryh@localhost ~]$  awk -F")" '/aged/{num[$NF]++}END{for(i in num) {print num[i],"\t", i}}' name.txt|sort -rn
  2. 13        Bayern Munich
复制代码
7.队长里打什么位置的最多
  1. [ryh@localhost ~]$ awk '/\(c\)/{num[$2]++} END{for(i in num) {print num[i], "\t", i |"sort -rn"}}' name.txt
  2. 6        MF
复制代码
8.比你年纪大的有多少人
  1. [ryh@localhost ~]$  awk -F"[()]" 'BEGIN{mydate=19860922}  /aged/{date=(NF==7)?$4:$2; gsub(/-/,"", date); if(date-mydate<0) {num++} } END{print num}' name.txt
复制代码
9.列出365天里所有人都不过生日的日期
  1. [ryh@localhost ~]$  awk -F"[()]" '/aged/{date=(NF==7)?$4:$2; date=substr(date,6); num[date]++} END{for (date in num) print date}' name.txt |awk '{d[NR]=$0} END{ for(i=1;i<=12;i++)  for(j=1;j<=31;j++) {flag=1; date=sprintf("%.2d-%.2d",i,j); for(k in d){if(d[k]==date) {flag=0; break} } ; if(flag==1 && date!="02-30" && date!="02-31" &&date!="04-31" && date!="06-31" && date!="09-31" && date!="11-31") {print date} }}'
复制代码
10.打各个位置的人一共有多少
  1. [ryh@localhost ~]$ awk '/aged/{num[$2]++} END{for(i in num) {print num[i], "\t", i}}' name.txt
  2. 76       FW
  3. 48       GK
  4. 130      MF
  5. 114      DF
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP