【问题标题】:Words for phone number电话号码的词
【发布时间】:2013-06-17 11:48:49
【问题描述】:

我想编写一个简单的 perl 脚本来为给定的电话号码生成所有可能的单词。

我从数组的定义开始:

my @nums = (
    ['0'],
    ['1'],
    ['2', 'a', 'b', 'c'],
    ['3', 'd', 'e', 'f'],
    ['4', 'g', 'h', 'i'],
    ['5', 'j', 'k', 'l'],
    ['6', 'm', 'n', 'o'],
    ['7', 'p', 'q', 'r', 's'],
    ['8', 't', 'u', 'v'],
    ['9', 'w', 'x', 'y', 'z']
);

最终脚本应生成以下输出:

$ num2word 12
12
1a
1b
1c

$ num2word 213
213
21d
21e
21f
a13
a1d
a1e
a1f
b13
b1d
b1e
b1f
c13
c1d
c1e
c1f

我正在寻找可以完成大部分工作的任何模块(类似于 List::Permutor 似乎不符合这项任务的条件)。

有什么提示吗? 谢谢!

【问题讨论】:

标签: perl cross-product


【解决方案1】:

我们自己的@brian d foy 用他的Set::CrossProduct 模块解决了这个问题。

use Set::CrossProduct;
my $iterator = Set::CrossProduct->new(
    [ [ qw(8 t u v) ], [ qw(0) ], [ qw(7 p q r s) ] ] );
print "@$_\n" for $iterator->combinations;

输出:

8 0 7
8 0 p
8 0 q
8 0 r
8 0 s
t 0 7
t 0 p
t 0 q
t 0 r
t 0 s
u 0 7
u 0 p
u 0 q
u 0 r
u 0 s
v 0 7
v 0 p
v 0 q
v 0 r
v 0 s

【讨论】:

  • 我非常感谢所有的答案。我什至没想到会有这么多的支持。感谢大家! :) 就问题的形式而言,此答案最合适,因为它指出了解决此问题的确切 perl 模块,而这正是问题所在。
【解决方案2】:

这就是你所要求的。

use strict;
use warnings;

my @nums = (
    [ qw/ 0 / ],
    [ qw/ 1 / ],
    [ qw /2 a b c / ],
    [ qw /3 d e f / ],
    [ qw /4 g h i / ],
    [ qw /5 j k l / ],
    [ qw /6 m n o / ],
    [ qw /7 p q r s / ],
    [ qw /8 t u v / ],
    [ qw /9 w x y z / ],
);

list_matching('12');
list_matching('213');

sub list_matching {

  my ($num) = @_;
  my @num = $num =~ /\d/g;
  my @map = (0) x @num;

  do {
    print join('', map { $nums[$num[$_]][$map[$_]] } 0 .. $#num), "\n";
    my $i = $#map;
    while ($i >= 0) {
      last if ++$map[$i] < @{ $nums[$num[$i]] };
      $map[$i--] = 0;
    }
  } while grep $_, @map; 
}

输出

12
1a
1b
1c
213
21d
21e
21f
a13
a1d
a1e
a1f
b13
b1d
b1e
b1f
c13
c1d
c1e
c1f

【讨论】:

  • 这段代码很难理解——例如变量名@nums@num$num
【解决方案3】:

查看Algorithm::Combinatorics中的函数。

【讨论】:

  • 这可能是个好主意,但问题是我真的找不到任何方法来利用这些函数中的任何一个来解决这个问题。这个问题实际上既不是排列也不是变化,也不是这样的。
【解决方案4】:

实际上,确实有效,对我来说为时过早......

use autodie;
use strict;
use warnings;

my @nums = (
    ['0'],
    ['1'],
    ['2', 'a', 'b', 'c'],
    ['3', 'd', 'e', 'f'],
    ['4', 'g', 'h', 'i'],
    ['5', 'j', 'k', 'l'],
    ['6', 'm', 'n', 'o'],
    ['7', 'p', 'q', 'r', 's'],
    ['8', 't', 'u', 'v'],
    ['9', 'w', 'x', 'y', 'z']
);

my $input = shift || die "Need a number!\n";
die "Input not numeric!\n" unless $input =~ m/^\d+$/;

my @digits = split //, $input;
my @rows;
push @rows, $nums[$_] for @digits;

print_row(0,'');

exit;

sub print_row {
    my $i    = shift;
    my $word = shift;

    my $row = $rows[$i];

    for my $j (0..$#{$row}) {
        my $word2 = $word . $row->[$j];
        if ($i < $#rows) {
            print_row($i+1, $word2);
        }
        else {
            print "$word2\n";
        }
    }
}

【讨论】:

    【解决方案5】:

    不需要模块:

    my @nums = (
        ['0'],
        ['1'],
        ['2', 'a', 'b', 'c'],
        ['3', 'd', 'e', 'f'],
        ['4', 'g', 'h', 'i'],
        ['5', 'j', 'k', 'l'],
        ['6', 'm', 'n', 'o'],
        ['7', 'p', 'q', 'r', 's'],
        ['8', 't', 'u', 'v'],
        ['9', 'w', 'x', 'y', 'z']
    );
    
    print "$_\n" while glob join '', map sprintf('{%s}', join ',', @{$nums[$_]}), split //, $ARGV[0]
    

    【讨论】:

    【解决方案6】:
    use strict;
    use warnings;
    my @nums = (
        ['0'], ['1'], ['2', 'a', 'b', 'c'],
        ['3', 'd', 'e', 'f'], ['4', 'g', 'h', 'i'],
        ['5', 'j', 'k', 'l'], ['6', 'm', 'n', 'o'],
        ['7', 'p', 'q', 'r', 's'],  ['8', 't', 'u', 'v'],
        ['9', 'w', 'x', 'y', 'z']);
    
    num2word(12);
    num2word(213);
    
    sub num2word {
        my ($i, $n, $t) = ($_[0]=~/(.)(.*)/, $_[1]);
        for (@{$nums[$i]}) {
            print "$t$_\n" and next if !length($n);
            num2word($n, defined $t ? $t.$_ : $_);
        }   
    }
    

    【讨论】:

      【解决方案7】:

      一个基本的递归解决方案:

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      my $phone_number = $ARGV[0] or die "No phone number";
      
      my @nums = (
          ['0'],
          ['1'],
          [ '2', 'a', 'b', 'c' ],
          [ '3', 'd', 'e', 'f' ],
          [ '4', 'g', 'h', 'i' ],
          [ '5', 'j', 'k', 'l' ],
          [ '6', 'm', 'n', 'o' ],
          [ '7', 'p', 'q', 'r', 's' ],
          [ '8', 't', 'u', 'v' ],
          [ '9', 'w', 'x', 'y', 'z' ]
      );
      
      my %letters = map { shift @{$_} => $_ } @nums;
      
      my @permutations;
      
      sub recurse {
          my $str = shift;
          my $done = shift || '';
      
          unless ($str) {
              push @permutations, $done;
              return;
          }
      
          my $next = substr( $str, 0, 1 );
          $str = substr( $str, 1 );
      
          recurse( $str, $done . $next );
      
          if ( my @chars = @{ $letters{$next} } ) {
      
              recurse( $str, $done . $_ ) foreach @chars;
      
          }
      }
      
      recurse($phone_number);
      
      print "$_\n" foreach @permutations;
      

      和:

      perl num2word 12
      12
      1a
      1b
      1c
      
      perl num2word 213
      213
      21d
      21e
      21f
      a13
      a1d
      a1e
      a1f
      b13
      b1d
      b1e
      b1f
      c13
      c1d
      c1e
      c1f  
      

      【讨论】:

      • 是的,它有效。只是对其进行了编辑以包含原始编号和字母,但除此之外它做了所要求的 - 有什么问题?
      • ...你的意思是你已经修好了?
      • 它非常接近,我只是错过了在输出中包含原始数字(在问题的文本中并不是特别清楚)。我认为反对票有点苛刻
      猜你喜欢
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 2013-11-16
      • 2016-04-15
      • 2010-11-17
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      相关资源
      最近更新 更多