matrix_path_3-ways_best.pl 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 13 August 2016
  5. # Website: https://github.com/trizen
  6. # The minimal path sum in the 5 by 5 matrix below, by starting in any cell
  7. # in the left column and finishing in any cell in the right column, and only
  8. # moving up, down, and right; the sum is equal to 994.
  9. # This algorithm finds the best possible path.
  10. # The problem was taken from: https://projecteuler.net/problem=82
  11. use 5.010;
  12. use strict;
  13. use warnings;
  14. no warnings 'recursion';
  15. use List::Util qw(min);
  16. use Memoize qw(memoize);
  17. memoize('path');
  18. my @matrix = (
  19. [131, 673, 234, 103, 18],
  20. [201, 96, 342, 965, 150],
  21. [630, 803, 746, 422, 111],
  22. [537, 699, 497, 121, 956],
  23. [805, 732, 524, 37, 331],
  24. );
  25. my $end = $#matrix;
  26. sub path {
  27. my ($i, $j, $last) = @_;
  28. $j >= $end && return $matrix[$i][$j];
  29. my @paths;
  30. if ($i > 0 and $last ne 'down') {
  31. push @paths, path($i - 1, $j, 'up');
  32. }
  33. push @paths, path($i, $j + 1, 'ok');
  34. if ($i < $end and $last ne 'up') {
  35. push @paths, path($i + 1, $j, 'down');
  36. }
  37. my $min = 'inf';
  38. foreach my $sum (@paths) {
  39. $min = $sum if $sum < $min;
  40. }
  41. $min + $matrix[$i][$j];
  42. }
  43. my @sums;
  44. foreach my $i (0 .. $end) {
  45. push @sums, path($i, 0, 'ok');
  46. }
  47. say min(@sums);