Re: Getting combinations from a number's digits
by Zaxo (Archbishop) on Jul 10, 2006 at 01:17 UTC
|
Generally, this is a combinatorial problem and there are modules to handle that. Here's another way which is only practical due to the small length of the entry. I run the combinations through hash keys to uniquify them. The regex match serves to both extract the digits and validate the input.
#!/usr/bin/perl -w
# filename: combo
use strict;
my $entry = shift;
my @array =
$entry =~ m/^(\d)(\d)(\d)$/ ?
($1.$2.$3, $1.$3.$2, $2.$1.$3, $2.$3.$1, $3.$1.$2, $3.$2.$1) :
();
@array or die "Bad input: ${entry}\n";
@array = do {
my %hash;
@hash{@array} = ();
keys %hash;
};
print "${entry} was entered.",
" The different combinations would be @{array}.\n";
__END__
$ perl combo 123
123 was entered. The different combinations would be 231 123 312 321 2
+13 132.
$ perl combo 122
122 was entered. The different combinations would be 221 212 122.
You will be better off with an array instead of distinct named variables. It will accomodate the smaller number of combinations that are possible with duplicated digits, and you don't have to make up meaningful names for unmeaningful distinctions. (Yes, @array and %hash are not meaningful names outside tutorial use ;-)
| [reply] [d/l] |
|
|
The line after: my @array =, could you explain the $entry line. Thank you.
| [reply] |
|
|
Sure. That uses the "trinary operator", which has the form foo ? bar : baz. It tests foo, whatever that may be, for truth. If true the expression evaluates to bar, if false, to baz.
Here, foo corresponds to a regular expression match with $entry. The regex tests that $entry consists of exactly three digits and captures the three to $1, $2 and $3 by surrounding each digit's slot with parentheses.
The bar element is an explicit list of combinations using the captured digits, whatever they may be. It will be returned to the @array assignment by the expression if the match succeeded. The "baz" element is an empty list, which goes to the assignment if the match failed.
It is important to never use the backreference variables $1,$2,... unless the regex match succeeded. The trinary op above complies with that, since the number variables only appear in the true branch.
The trinary op is documented in perlop. ++bobf for suggesting the link.
| [reply] |
Re: Getting combinations from a number's digits
by GrandFather (Saint) on Jul 10, 2006 at 00:16 UTC
|
Most programmers would differentiate between single variables and arrays. If what you want is to store those values in an array then you could do it like this:
my @array = (123,132,213,213,312,312);
However that seems a pretty trivial thing to want to do. I suspect this is an XY Problem. How about asking the real question that is bothering you rather than a question pertaining to what you think might be the solution. Showing some code that you have tried would help a lot too.
DWIM is Perl's answer to Gödel
| [reply] [d/l] |
|
|
I'll try again:
I,m accepting a 3 digit number from a form.
That number has 6 possible 3-digit combinations. I have to know what those 6 3-digit combinations are so that I can take each one and check to see if it's in a MySql data base table and, if so, tell the user what dates each of the 6 combinations appeared. It's a lottery table look-up.
Does this help? We cuurently work in a MicroFocus Cobol environment which allows us to index each digit and manipulate them.
| [reply] |
|
|
use warnings;
use strict;
use Algorithm::Loops qw(NextPermute);
my $number = '123';
my @digits = split //, $number;
my @array = ($number); # Add the first permutation
push @array, join '', @digits while NextPermute (@digits);
print "@array";
Prints:
123 132 213 231 312 321
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
|
|
If you have access to change the database, I wonder whether it would be better to store all the numbers sorted (either in the main table, or in a separate table), and then look them up that way. So if the user enters "312", you'd check for "123". Then you're only doing one lookup instead of 6.
| [reply] |
Re: Getting combinations from a number's digits
by gloryhack (Deacon) on Jul 10, 2006 at 04:54 UTC
|
You might take a look at List::Permutor. Split your string, take the permutations, go away happy. | [reply] |
Re: Getting combinations from a number's digits
by ioannis (Abbot) on Jul 10, 2006 at 00:55 UTC
|
This solution is based on the combinational powers of glob()
my $txt = '123';
local $"=',';
my @array = glob( "{@{[ split(//,$txt)]}}" x length($txt) );
print Dumper \@array ;
| [reply] [d/l] |
|
|
| [reply] |
|
|
um... I learned something. glob() is an actual module. I thought you were using it like we use blah or foo.
Thanks, but does this use of glob create the 6 combinations for him? It seems the 6 combinations are hardcoded and he just want to store them somewhere for later use.
| [reply] |