Reputation: 107
$str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
I need a function that will print me a random variation of the str. For example:
Hi Ann
Hello Polly
....
....
Anny ideas?
Upvotes: 0
Views: 146
Reputation: 47099
I would use lists and list packages to do this, shuffle
and pairwise
come to mind, e.g.:
use 5.010;
use List::Util qw /shuffle/;
use List::MoreUtils qw/pairwise/;
$, = " ";
@greetings = shuffle qw(Hi Hello Aloha);
@names = shuffle qw(Kate Ann Polly);
pairwise { say $a, $b } @greetings, @names;
Example output:
Hello Polly
Aloha Ann
Hi Kate
If you're stuck with the string format, you can convert it into lists with something like this:
$str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
($greetings, $names) = $str =~ /\[([^]]+)\] +\[([^]]+)\]/;
@greetings = shuffle split /\|/, $greetings;
@names = shuffle split /\|/, $names;
Upvotes: 1
Reputation: 385799
$str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
$str =~ s{
\[ ( [^\]]* ) \]
}{
my @choices = split /\|/, $1;
$choices[rand(@choices)]
}xeg;
say $str;
Upvotes: 4
Reputation: 57600
Combining two random elements from two arrays is rather trivial, and answered by @OleksandrBondarenko. The more interesting question is how to get a data structure from that string.
Change your input format. You need two lists/arrays, not a string. If you can change your API or interface, doing that might be easier than using this string representation
Create Perl code from that string and eval
it. While this is easy, this is a severe security problem, so this should only be applied for one-time problems where the input is well known and trusted:
my $str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
$str =~ s/ /,/g; # '[Hi|Hello|Aloha],[Kate|Ann|Polly]'
$str =~ s/\|/","/g; # '[Hi","Hello","Aloha],[Kate","Ann","Polly]'
$str =~ s/\[/["/g; # '["Hi","Hello","Aloha],["Kate","Ann","Polly]'
$str =~ s/\]/"]/g; # '["Hi","Hello","Aloha"],["Kate","Ann","Polly"]'
my @arrayrefs = eval $str; # (["Hi","Hello","Aloha"],["Kate","Ann","Polly"])
my @greetings = @{shift @arrayrefs};
my @names = @{shift @arrayrefs};
Do not do this in production code, as the string could contain any arbitrary code, possibly resulting in severe damage to your computer, files or security.
Process and parse the data correctly. While this is sometimes difficult, it is the safest solution.
my $str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
my @strings = split /(?<=\])\s+(?=\[)/, $str;
# for each $string in @strings:
$string =~ s/^\[//; #
$string =~ s/\]$//; # or: $string = substr $str, 1, length $str -2;
my @parts = split /\|/, $string
The first @parts
is the array of greetings, the second an array of names. This solution requires some further code I omitted.
The look-arounds in the first split
regex are not really neccessary, but better than making assumptions about the data format.
Upvotes: 0
Reputation: 2018
Just generate two random numbers from the set {0,1,2}
and build your greeting respectively.
For example: if the generated numbers are 1
and 2
, then you output 'Hello Polly'
. If 2
and 0
, then 'Aloha Kate'
.
Upvotes: 2