diff options
| author | Abigail <abigail@abigail.be> | 2021-02-25 14:13:21 +0100 |
|---|---|---|
| committer | Abigail <abigail@abigail.be> | 2021-02-25 14:13:21 +0100 |
| commit | da2f7e48f7f8c0ecc2653bf233f2c724f35e48f9 (patch) | |
| tree | f1a94c613020653a49f49944f557c71fb17ee8e9 | |
| parent | bb123a18ffd0376c3a306f0cbd6b5746bbf4956b (diff) | |
| download | perlweeklychallenge-club-da2f7e48f7f8c0ecc2653bf233f2c724f35e48f9.tar.gz perlweeklychallenge-club-da2f7e48f7f8c0ecc2653bf233f2c724f35e48f9.tar.bz2 perlweeklychallenge-club-da2f7e48f7f8c0ecc2653bf233f2c724f35e48f9.zip | |
Perl solution for week 101, part 1
| -rw-r--r-- | challenge-101/abigail/README.md | 1 | ||||
| -rw-r--r-- | challenge-101/abigail/perl/ch-1.pl | 108 |
2 files changed, 109 insertions, 0 deletions
diff --git a/challenge-101/abigail/README.md b/challenge-101/abigail/README.md index 7707028ada..48c4c6976e 100644 --- a/challenge-101/abigail/README.md +++ b/challenge-101/abigail/README.md @@ -62,6 +62,7 @@ or ~~~~ ### Solutions +* [Perl](perl/ch-1.pl) ### Blog diff --git a/challenge-101/abigail/perl/ch-1.pl b/challenge-101/abigail/perl/ch-1.pl new file mode 100644 index 0000000000..0b7dfa3352 --- /dev/null +++ b/challenge-101/abigail/perl/ch-1.pl @@ -0,0 +1,108 @@ +#!/opt/perl/bin/perl + +use 5.032; + +use strict; +use warnings; +no warnings 'syntax'; + +use experimental 'signatures'; +use experimental 'lexical_subs'; + +use List::Util 'max'; + +# +# See ../README.md +# + +# +# Run as: perl ch-1.pl < input-file +# + +# +# This is a really hard problem to do efficiently, as it involves +# factorizing numbers. And if we can do that efficiently, we can +# break many public key encryption schemes, including RSA. +# +# We do, however, use a simplistic method to find the optimal width +# and height for the matrix, by starting at the square root of the +# number of elements, and trying each number (while counting down) +# till we have found a divisor. +# +# This is O (sqrt (N)), where N is the number of elements. +# However, we're already spending linear time reading the input. +# + +my $RIGHT = 0; +my $UP = 1; +my $LEFT = 2; +my $DOWN = 3; + +# +# Read in the data; we're assuming the elements are separated by whitespace. +# We can easily change this without effecting the rest of the program. +# +my @elements = split ' ' => scalar <>; + +# +# Find optimal sizes: width $w and height $h +# We start at the square root, and count downwards till we +# have a divider. +# +my $h = int sqrt @elements; +for (; @elements % $h;) { + $h --; +} + +my $w = @elements / $h; + + +# +# Fill a matrix, starting from the bottom left. +# +my $matrix; +my ($min_x, $max_x, $min_y, $max_y) = (0, $h - 1, 0, $w - 1); +my $x = $max_x; +my $y = $min_y; +my $direction = $RIGHT; +foreach my $element (@elements) { + $$matrix [$x] [$y] = $element; + my $turn = 0; + if ($direction == $RIGHT) { + if ($y >= $max_y) {$turn = 1; $x --; $max_x --} + else {$y ++} + } + if ($direction == $UP) { + if ($x <= $min_x) {$turn = 1; $y --; $max_y --} + else {$x --} + } + if ($direction == $LEFT) { + if ($y <= $min_y) {$turn = 1; $x ++; $min_x ++} + else {$y --} + } + if ($direction == $DOWN) { + if ($x >= $max_x) {$turn = 1; $y ++; $min_y ++} + else {$x ++} + } + if ($turn) { + $direction ++; + $direction %= 4; + } +} + +# +# Pretty print array; we're making sure all the columns are aligned. +# + +my @widths = map {my $y = $_; + max map {length $$matrix [$_] [$y]} 0 .. $h - 1} 0 .. $w - 1; + +foreach my $row (@$matrix) { + for (my $y = 0; $y < @$row; $y ++) { + my $width = $widths [$y]; + printf "%s%${width}s" => $y ? " " : "", $$row [$y]; + } + print "\n"; +} + +__END__ |
