093 Arithmetic expressions.pl 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Website: https://github.com/trizen
  5. # https://projecteuler.net/problem=93
  6. # Runtime: 13.819s
  7. use 5.010;
  8. use strict;
  9. use warnings;
  10. use ntheory qw(forperm);
  11. my @op = ('+', '-', '*', '/');
  12. my @expr = (
  13. "%d %s %d %s %d %s %d",
  14. "%d %s (%d %s (%d %s %d))",
  15. "%d %s ((%d %s %d) %s %d)",
  16. "(%d %s (%d %s %d)) %s %d",
  17. "%d %s (%d %s %d %s %d)",
  18. "%d %s (%d %s %d) %s %d",
  19. "%d %s %d %s (%d %s %d)",
  20. "((%d %s %d) %s %d) %s %d",
  21. "(%d %s %d) %s (%d %s %d)",
  22. );
  23. sub evaluate {
  24. my ($nums, $ops, $table) = @_;
  25. foreach my $expr (@expr) {
  26. my $n = eval sprintf($expr,
  27. $nums->[0], $ops->[0],
  28. $nums->[1], $ops->[1],
  29. $nums->[2], $ops->[2],
  30. $nums->[3]
  31. );
  32. if (not $@
  33. and $n > 0
  34. and int($n) eq $n
  35. and not exists $table->{$n}) {
  36. undef $table->{$n};
  37. }
  38. }
  39. }
  40. sub compute {
  41. my ($set, $table) = @_;
  42. forperm {
  43. my @nums = @{$set}[@_];
  44. foreach my $i (0 .. 3) {
  45. foreach my $j (0 .. 3) {
  46. foreach my $k (0 .. 3) {
  47. my @ops = @op[$i, $j, $k];
  48. evaluate(\@nums, \@ops, $table);
  49. }
  50. }
  51. }
  52. } scalar(@$set);
  53. }
  54. my %max;
  55. foreach my $i (1 .. 9) {
  56. foreach my $j ($i + 1 .. 9) {
  57. foreach my $k ($j + 1 .. 9) {
  58. foreach my $l ($k + 1 .. 9) {
  59. compute([$i, $j, $k, $l], \my %table);
  60. my ($n, $c) = (0, 0);
  61. my @keys = sort { $a <=> $b } keys %table;
  62. while (@keys) {
  63. shift(@keys) == ++$n ? ++$c : last;
  64. }
  65. if ($c > ($max{max} || 0)) {
  66. $max{max} = $c;
  67. $max{set} = [$i, $j, $k, $l];
  68. }
  69. }
  70. }
  71. }
  72. }
  73. print "$max{max}: [@{$max{set}}]\n";