diff options
| author | E7-87-83 <fungcheokyin@gmail.com> | 2021-07-13 10:36:23 +0800 |
|---|---|---|
| committer | E7-87-83 <fungcheokyin@gmail.com> | 2021-07-13 10:36:23 +0800 |
| commit | de7890d7f27c9aa373e9c9d0e59be15df60f0c2f (patch) | |
| tree | cf670de09a9f5e3f4f70bad24b95ecf05e6fca8c | |
| parent | 660818f121fc55d3076034ee632d3181b53945d3 (diff) | |
| download | perlweeklychallenge-club-de7890d7f27c9aa373e9c9d0e59be15df60f0c2f.tar.gz perlweeklychallenge-club-de7890d7f27c9aa373e9c9d0e59be15df60f0c2f.tar.bz2 perlweeklychallenge-club-de7890d7f27c9aa373e9c9d0e59be15df60f0c2f.zip | |
Task 2 via Brute Force
| -rw-r--r-- | challenge-121/cheok-yin-fung/perl/ch-2.pl | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/challenge-121/cheok-yin-fung/perl/ch-2.pl b/challenge-121/cheok-yin-fung/perl/ch-2.pl new file mode 100644 index 0000000000..0cbea74980 --- /dev/null +++ b/challenge-121/cheok-yin-fung/perl/ch-2.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl +# The Weekly Challenge - 121 +# Task 2 The Travelling Salesman +# a brute-force solution via permutations again +# Usage: $ ch-2.pl +use strict; +use warnings; +use Algorithm::Combinatorics qw/permutations/; +use feature qw/say/; + +my $M; + +my $M04 = [ + [0, 5, 2, 7], + [5, 0, 5, 3], + [3, 1, 0, 6], + [4, 5, 4, 0] +]; + +my $M09 = [ + [0,2,3,9,4,1,8,5,2], + [8,0,6,4,6,5,2,8,8], + [8,4,0,9,4,9,6,8,9], + [3,4,5,0,5,8,6,3,1], + [1,4,2,5,0,4,7,2,9], + [5,8,8,9,1,0,7,7,1], + [4,5,8,2,5,3,0,9,2], + [6,6,1,7,9,6,9,0,8], + [3,1,4,3,9,7,3,3,0] +]; + +my $M15 = [ +[ 0 , 1 , 3 ,11 , 9 ,13 , 2 ,15 ,10 ,10 ,13 , 9 , 3 ,15 , 8], +[15 , 0 , 7 ,13 , 6 , 3 , 7 , 7 , 3 , 6 , 1 , 1 ,11 , 2 ,12], +[ 9 , 7 , 0 ,16 , 5 ,14 ,12 , 2 , 6 ,16 ,10 , 9 , 8 ,13 , 3], +[ 1 , 4 , 5 , 0 , 9 ,14 , 3 ,10 , 2 ,11 , 4 ,12 , 5 , 9 , 7], +[11 , 2 , 8 , 8 , 0 , 8 ,16 , 1 , 1 , 7 , 6 , 8 ,15 , 4 , 3], +[ 1 , 4 , 8 ,13 , 7 , 0 ,13 ,13 , 6 , 4 ,12 , 5 , 1 , 7 , 9], +[ 6 , 8 , 6 ,13 , 3 ,11 , 0 , 7 , 1 ,14 , 2 ,12 , 1 , 7 , 5], +[ 2 ,12 , 2 ,11 ,14 ,13 , 2 , 0 , 8 , 7 , 2 , 2 , 2 , 9 , 2], +[14 ,14 ,15 , 8 ,16 , 5 ,14 ,15 , 0 , 9 ,14 , 3 ,11 , 3 ,13], +[11 , 8 , 2 ,12 ,12 , 1 ,11 ,11 , 2 , 0 , 3 , 4 , 2 ,10 , 5], +[12 , 4 , 2 , 8 , 6 ,10 , 7 ,15 ,16 , 4 , 0 ,12 , 1 , 5 ,10], +[13 ,13 , 7 , 8 ,16 ,10 , 9 ,14 , 9 ,11 , 6 , 0 , 8 ,10 , 6], +[15 ,14 , 4 ,15 , 5 ,16 ,14 , 6 , 4 ,16 , 4 , 3 , 0 , 2 , 2], +[ 2 , 2 , 9 ,12 , 8 , 8 ,13 ,15 , 1 , 5 ,16 , 1 , 1 , 0 ,12], +[14 , 6 ,14 , 6 , 9 , 1 ,11 ,12 ,11 , 5 , 9 , 9 , 6 , 4 , 0] +]; + +# $M09 and $M15 are produced by: +# https://onlinemathtools.com/generate-random-matrix +# manually edit the diagonal afterwards +# (but they won't be referenced actually) + +$M = $M09; +my $N = $ARGV[0] || scalar @{$M}; + +# $M = $M04, $N = 4 (Task Example) +# (0 2 1 3 0) +# length: 10 + +# $M = $M15, $N = 11 +# Z A E I J B G F D H C Z +# length: 30 + +# $M = $M15, $N = 12 +# Z A E I J B G F D H K C Z +# length: 33 + +my $min = 10000; +my @arr_min = (); + +my $v = chr(ord("A")+$N-2); +my $iter = permutations(['A'..$v]); +while (my $c = $iter->next) { + my $d = calc_dist($c); + if (defined($d) && $d <= $min) { #related to the improvement A + if ($d < $min) { + @arr_min = (); + $min = $d; + say "new shorter circuit found: @{$c}"; #facilitate testing + } + push @arr_min, $c; + } +} + +say ""; +say "length = $min"; +say ('tour = (0 ', (join " ", map {alp2n($_)} @{$arr_min[0]}) , ' 0)' ) ; + + +sub alp2n { + return ord($_[0])-ord("A")+1; +} + + +sub calc_dist { + my @seq = @{$_[0]}; + my $dist = 0; + $dist += $M->[0][ alp2n($seq[0]) ]; + for my $i (0..$#seq-1) { + $dist += $M->[ alp2n($seq[$i]) ][ alp2n($seq[$i+1]) ]; + return undef if $dist >= $min; # a slightly improvement A + } + $dist += $M->[alp2n($seq[-1])][0]; +} + |
