matrix_path_3-ways_greedy.pl 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 is a greedy algorithm (visual version).
  10. # The problem was taken from: https://projecteuler.net/problem=82
  11. use 5.010;
  12. use strict;
  13. use warnings;
  14. use Time::HiRes qw(sleep);
  15. use Term::ANSIColor qw(colored);
  16. my @matrix = (
  17. map {
  18. [map { int(rand(1000)) } 1 .. 6]
  19. } 1 .. 6
  20. );
  21. sub draw {
  22. my ($path) = @_;
  23. print "\e[H\e[J\e[H";
  24. my @screen = map {
  25. [map { sprintf "%3s", $_ } @{$_}]
  26. } @matrix;
  27. foreach my $p (@$path) {
  28. my ($i, $j) = @$p;
  29. $screen[$i][$j] = colored($screen[$i][$j], 'red');
  30. }
  31. foreach my $row (@screen) {
  32. say join(' ', @{$row});
  33. }
  34. sleep(0.2);
  35. }
  36. my $end = $#matrix;
  37. my $min = ['inf', []];
  38. foreach my $i (0 .. $#matrix) {
  39. my $sum = $matrix[$i][0];
  40. my $j = 0;
  41. my $last = 'ok';
  42. my @path = [$i, 0];
  43. while (1) {
  44. my @ways;
  45. if ($i > 0 and $last ne 'down') {
  46. push @ways, [-1, 0, $matrix[$i - 1][$j], 'up'];
  47. }
  48. if ($j < $end) {
  49. push @ways, [0, 1, $matrix[$i][$j + 1], 'ok'];
  50. }
  51. if ($i < $end and $last ne 'up') {
  52. push @ways, [1, 0, $matrix[$i + 1][$j], 'down'];
  53. }
  54. my $m = [0, 0, 'inf', 'ok'];
  55. foreach my $way (@ways) {
  56. $m = $way if $way->[2] < $m->[2];
  57. }
  58. $i += $m->[0];
  59. $j += $m->[1];
  60. $sum += $m->[2];
  61. $last = $m->[3];
  62. push @path, [$i, $j];
  63. draw(\@path);
  64. last if $j >= $end;
  65. }
  66. $min = [$sum, \@path] if $sum < $min->[0];
  67. }
  68. draw($min->[1]);
  69. say "Minimum path-sum: $min->[0]";