aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-112/colin-crain/perl/ch-1.pl245
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();
+
+