diff options
| author | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2021-05-27 21:36:54 +0100 |
|---|---|---|
| committer | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2021-05-27 21:36:54 +0100 |
| commit | d9c07477fa50631b547fbc38f59e7691353d5e88 (patch) | |
| tree | 6af9a7db8dc0ac48a247f4c73a4a94762906dd82 | |
| parent | 3be055bb3275324fd02a11efaac7ab79173ca92e (diff) | |
| download | perlweeklychallenge-club-d9c07477fa50631b547fbc38f59e7691353d5e88.tar.gz perlweeklychallenge-club-d9c07477fa50631b547fbc38f59e7691353d5e88.tar.bz2 perlweeklychallenge-club-d9c07477fa50631b547fbc38f59e7691353d5e88.zip | |
- Updated solution.
| -rw-r--r-- | challenge-112/colin-crain/perl/ch-1.pl | 245 |
1 files changed, 138 insertions, 107 deletions
diff --git a/challenge-112/colin-crain/perl/ch-1.pl b/challenge-112/colin-crain/perl/ch-1.pl index 3a638cea0f..ff7a309d49 100644 --- a/challenge-112/colin-crain/perl/ch-1.pl +++ b/challenge-112/colin-crain/perl/ch-1.pl @@ -1,107 +1,138 @@ -#!/Users/colincrain/perl5/perlbrew/perls/perl-5.32.0/bin/perl
-#
-# where-am-i-where-are-my-friends.pl
-#
-# Canonical Path
-# Submitted by: Mohammad S Anwar
-# You are given a string path, starting with a slash ‘/'.
-#
-# Write a script to convert the given absolute path to the simplified
-# canonical path.
-#
-# In a Unix-style file system:
-#
-# - A period '.' refers to the current directory
-# - A double period '..' refers to the directory up a level
-# - Multiple consecutive slashes ('//') are treated as a single slash '/'
-# The canonical path format:
-#
-# - The path starts with a single slash '/'.
-# - Any two directories are separated by a single slash '/'.
-# - The path does not end with a trailing '/'.
-# - The path only contains the directories on the path from the root
-# directory to the target file or directory
-#
-# Example
-# Input: "/a/"
-# Output: "/a"
-#
-# Input: "/a/b//c/"
-# Output: "/a/b/c"
-#
-# Input: "/a/b/c/../.."
-# Output: "/a"
-#
-# method
-# converting to a canonical path form is not quite as simple as
-# restructuring dot file notaion into real directories and
-# normalizing superfluous chaff such as '//', because a canonical
-# path is always an absolute path and the relative path given may
-# not be.
-#
-# Fortunately for us today we are defined as having been given an
-# absolute path, sidestepping that mess.
-#
-# However a canonical path also resolves soft links, which remains a
-# difficulty, as Perl is not a shell. There are ways involving a module
-# to address this, but I'm going to assume this edge case is outside
-# the scope of the problem.
-#
-#
-# © 2021 colin crain
-## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
-
-
-
-use warnings;
-use strict;
-use feature ":5.26";
-use feature qw(signatures);
-no warnings 'experimental::signatures';
-
-use Cwd qw( abs_path );
-
-
-
-sub canonical ($path) {
- $path =~ s{/\.?/}{/}g;
- $path =~ s{/$}{};
-
- my @parts = split '/', $path;
- my $pos = 0;
- while (++$pos < @parts) {
- if ($parts[$pos] eq '..') {
- splice @parts, $pos-1, 2;
- $pos -= 2;
- }
- }
- join '/', @parts;
-}
-
-# this will resolve relative paths, and soft links, from the cwd, which doesn't
-# really solve that problem in a general way. We need to `chdir` over to
-# the place in question, which would need to both exist and have the right permissions.
-# The whole thing is a bit of a mess, really, and I don't think that's what Mohammad is
-# asking of us.
-
-sub canonical_softlinks ($path) {
- chdir $path;
- return abs_path( $path );
-}
-
-## resolving the link from d -> e
-## yields /Users/colincrain/a/b/c/e
-
-my $path = '../../a/b/c/f/../d';
-say canonical_softlinks( $path );
-
-
-
-use Test::More;
-
-is canonical("/a/"), "/a" , 'ex-1';
-is canonical("/a/b//c/"), "/a/b/c" , 'ex-2';
-is canonical("/a/b/c/../.."), "/a" , 'ex-3';
-
-done_testing();
-
+#!/Users/colincrain/perl5/perlbrew/perls/perl-5.32.0/bin/perl +# +# PWC 112 - TASK 1 +# +# where-am-i-where-are-my-friends.pl +# +# Canonical Path +# Submitted by: Mohammad S Anwar +# You are given a string path, starting with a slash ‘/'. +# +# Write a script to convert the given absolute path to the simplified +# canonical path. +# +# In a Unix-style file system: +# +# - A period '.' refers to the current directory +# - A double period '..' refers to the directory up a level +# - Multiple consecutive slashes ('//') are treated as a single slash '/' +# The canonical path format: +# +# - The path starts with a single slash '/'. +# - Any two directories are separated by a single slash '/'. +# - The path does not end with a trailing '/'. +# - The path only contains the directories on the path from the root +# directory to the target file or directory +# +# Example +# Input: "/a/" +# Output: "/a" +# +# Input: "/a/b//c/" +# Output: "/a/b/c" +# +# Input: "/a/b/c/../.." +# Output: "/a" +# +# method +# converting to a canonical path form is not quite as simple as +# restructuring dot file notaion into real directories and +# normalizing superfluous chaff such as '//', because a canonical +# path is always an absolute path and the relative path given may +# not be. +# +# Fortunately for us today we are defined as having been given an +# absolute path, sidestepping that mess. +# +# However a canonical path also resolves soft links, which remains a +# difficulty, as Perl is not a shell. There are ways involving a module +# to address this, but I'm going to assume this edge case is outside +# the scope of the problem. +# +# +# © 2021 colin crain +## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## + + + +use warnings; +use strict; +use feature ":5.26"; +use feature qw(signatures); +no warnings 'experimental::signatures'; +use Cwd qw( abs_path ); + + +sub canonical ($path) { + $path =~ s{//+}{/}g; + $path =~ s{/\./}{/}g; + $path =~ s{/$}{}; + + my @parts = split '/', $path; + + my $pos = 0; + while ($pos < @parts) { + if ($parts[$pos] eq '..') { + if ($pos > 0) { + splice @parts, $pos-1, 2; + $pos -= 2; + } + else { + splice @parts, $pos, 1; + $pos--; + } + } + $pos++; + } + @parts = (undef, undef) unless scalar @parts; + unshift @parts, '' if $parts[0] ne ''; + join '/', @parts; +} + +## this will resolve relative paths, and soft links, with the Cwd package, which +## doesn't really solve that problem in a general way. We need to `chdir` over to +## the place in question, which would need to both exist and have the right +## permissions. The whole thing is a bit of a mess, really, and I don't think +## that's what Mohammad is asking of us. +sub canonical_softlinks ($path) { + chdir $path; + return abs_path( $path ); +} + +## a solution using realpath from the system utilities +## we still need to chdir down to root unless we want the cwd prepended to an assumed +## relative path +sub canon_sys ($path) { + my $cur = `pwd`; + chdir '/'; + my $out = `realpath -m $path` ; + chomp $out; + chdir $cur; + return $out; +} + + + +use Test::More; + +is canonical("/a/"), "/a" , 'ex-1'; +is canonical("/a/b//c/"), "/a/b/c" , 'ex-2'; +is canonical("/a/b/c/../.."), "/a" , 'ex-3'; +is canonical('a/b/c//.//../d/'), "/a/b/d" , 'hateful'; +is canonical("../../../b"), "/b" , 'rogers bane'; +is canonical(".."), "/" , 'no path'; +is canonical("/"), "/" , 'no path2'; + + +is canon_sys("/a/"), "/a" , 'sys-ex-1'; +is canon_sys("/a/b//c/"), "/a/b/c" , 'sys-ex-2'; +is canon_sys("/a/b/c/../.."), "/a" , 'sys-ex-3'; +is canon_sys('a/b/c//.//../d/'), "/a/b/d" , 'sys-hateful'; +is canon_sys("../../../b"), "/b" , 'sys-rogers bane'; +is canon_sys(".."), "/" , 'sys-no path'; +is canon_sys("/"), "/" , 'sys-no path2'; + + +done_testing(); + + |
