Generates a random fully-parenthesized infix notation expression with variables. It also generates random names and values for those variables. It creates a certain number of them with a certain depth given on the command line. The first argument is the number of expressions you want, and the second is the maximum depth it can grow to.
#!/usr/bin/perl -w
use strict;
#variables
my $times = $ARGV[0] || 5;
my $depth = $ARGV[1] || 5;
my $value_limit = 10;
my @letters = ('a' .. 'z');
my @operators = qw(+ - * /);
my @variables = ();
my %variables = ();
#main
for my $i (1 .. $times){
generate_variables($depth); #this may go outside the for loop
my ($expression,$value) = expression($depth);
print "Expression: $expression\n";
print "Value: $value\n";
}
#subs
sub randelm { return $_[int rand @_]; }
sub generate_variables {
my $depth = shift;
for my $i (0 .. $depth - 1){
my $name = $letters[$i % 26] x (int $i / 26 + 1); # such as "aaa"
+;
my $value = (rand $value_limit) + 1; # such as 3.2;
$variables[$i][0] = $name; # @varibles = ([$name,$value],
$variables[$i][1] = $value; # [$name,$value]...)
$variables{$name} = $value; # A hash of names and values.
}
}
sub expression {
my $depth = shift;
if($depth == 0){ #base case
return @{randelm(@variables)};
} else {
my @left = expression(int rand($depth - 1));
my @right = expression(int rand($depth - 1));
my $operator = randelm(@operators);
my $name = "($left[0] $operator $right[0])";
my $value = "($left[1] $operator $right[1])";
return ($name, eval $value);
}
}