fork download
  1. #!/usr/bin/perl
  2. use 5.016;
  3. use warnings;
  4.  
  5. sub factorial { $_[0] < 1 ? $_[1] : factorial($_[0] - 1, $_[1] * $_[0]) }
  6.  
  7. sub rest { [ @{$_[0]}[1 .. $#{$_[0]}] ] }
  8.  
  9. sub term {
  10. my ($t, $args) = @_;
  11.  
  12. given($t->[0]){
  13. when('log('){
  14. return sub {
  15. my ($t, $x) = @_;
  16. ($t->[0] eq ')') or die;
  17. return (rest($t), log($x));
  18. }->(expr(rest($t), $args));
  19. }
  20. when('sqrt('){
  21. return sub {
  22. my ($t, $x) = @_;
  23. ($t->[0] eq ')') or die;
  24. return (rest($t), sqrt($x));
  25. }->(expr(rest($t), $args));
  26. }
  27. when(/[0-9]+/){
  28. return (rest($t), $t->[0]);
  29. }
  30. when(/[a-z]+/){
  31. return (rest($t), $args->{$t->[0]});
  32. }
  33. }
  34.  
  35. die;
  36. }
  37.  
  38. sub fact {
  39. my ($t, $args) = @_;
  40.  
  41. return sub{
  42. my ($t, $x) = @_;
  43. return (($t->[0] eq '!') ? (rest($t), factorial($x, 1)) : ($t, $x));
  44. }->(term($t, $args));
  45. }
  46.  
  47. sub pow {
  48. my ($t, $args) = @_;
  49.  
  50. return sub{
  51. my ($t, $x) = @_;
  52. ($t->[0] eq '^') ?
  53. sub{ $_[0], $x ** $_[1] }->(fact(rest($t), $args)) :
  54. ($t, $x)
  55. );
  56. }->(fact($t, $args));
  57. }
  58.  
  59. sub expr {
  60. my ($t, $args) = @_;
  61.  
  62. return sub{
  63. my ($t, $x) = @_;
  64. ($t->[0] eq '*') ?
  65. sub{ $_[0], $x * $_[1] }->(pow(rest($t), $args)) :
  66. ($t, $x)
  67. );
  68. }->(pow($t, $args));
  69. }
  70.  
  71. sub interpret {
  72. my ($code, $args) = @_;
  73.  
  74. my $t = [ $code =~ m/\G\s*([0-9]+|[\!\)\^\*]|log\(|sqrt\(|[a-z]+)/g, '' ];
  75.  
  76. return (expr($t, $args))[1];
  77. }
  78.  
  79.  
  80. my @code = split(/\n/, <<'EOF');
  81. 2^n
  82. 2^log(n)
  83. 4^n
  84. n
  85. n^2
  86. n!
  87. n*log(n)
  88. log(n!)
  89. log(log(n))
  90. sqrt(log(n))
  91. EOF
  92.  
  93. my $args = {n => 10};
  94.  
  95. say map{ "$_->[0] = $_->[1]\n" }
  96. sort{ $b->[1] <=> $a->[1] }
  97. map{ [ $_ => interpret($_, $args) ] } @code;
  98.  
Success #stdin #stdout 0s 3740KB
stdin
Standard input is empty
stdout
n! = 3628800
4^n = 1048576
2^n = 1024
n^2 = 100
n*log(n) = 23.0258509299405
log(n!) = 15.1044125730755
n = 10
2^log(n) = 4.9334096679146
sqrt(log(n)) = 1.51742712938515
log(log(n)) = 0.834032445247956