How about something different...
Rather than checking rand for different values, i construct a heuristic and run through it for each character. It's only vaguely correct since it's difficult to extract integer values appropriately in only a few keystrokes. The first entry weighs in at 120 characters and doesn't assume that $f and $h are set for me. The second weighs in at 103 characters and assumes that they are set (but doesn't run under warnings). Thanks for the interesting golf Masem :)
#1
sub f{
($a,$b,@_)=(@_,split//,'0@*+'.'='x(4/(pop)-4);
$b=2*$_-1,print$"x((2*$a-1-$b)/2),$_>1?map$_[rand@_],1..$b:'*',$/for 1
+..$a
}
#2
sub g{
+split//,'0@*+'.'='x(4/$f-4);
$b=2*$_-1,print$"x((2*$h-1-$b)/2),$_>1?map$_[rand@_],1..$b:'*',$/for 1
+..$h
}
jynx
update: i didn't notice the --$h trick, so i've shortened those still further:
update2:oops, my heuiristic was hard-coded for 0.3. i've corrected all versions.
#1 (at 97 characters)
sub f{
($a)=@_;+split//,'0@*+'.'='x(4/(pop)-4);
print$"x--$a,$_>1?map$_[rand@_],1..2*$_-1:'*',$/for 1..$a
}
#2 (at 86 characters)
sub g{
+split//,'0@*+'.'='x(4/$f-4);
print$"x--$h,$_>1?map$_[rand@_],1..2*$_-1:'*',$/for 1..$h
}