Peter’s blog ✴ Week 399 ✴ 9 November 2026

THE WEEKLY CHALLENGE
Longest and longest

The Perl Camel

Task 2

Longest absolute path

You are given a filesystem as a string. Write a script to return the length of the longest absolute path to a file in the abstracted file system. If there is no file in the system, return 0.

dir
- subdir1
  - file1.ext
  - subsubdir1
- subdir2
  - subsubdir2
    - file2.ext

This file system can be represented as: "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2 \n\t\tsubsubdir2\n\t\t\tfile2.ext"

Examples


Example 1
Input: $fs = 'dir\n\tsubdir1\n\t\tsubsubdir1\n\tsubdir2'
Output: 0
There are no files in the system (a file must contain a . character
   separating a name and extension).
Since there are no files, the answer is 0.

Example 2
Input: $fs = 'file1.txt\nfile2.ext\na.png'
Output: 9
All entries are located at root depth (0 tabs).
Found File Paths:
    'file1.txt' (length = 9)
    'file2.ext' (length = 9)
    'a.png'     (length = 5)
The longest absolute file path length is 9.

Example 3
Input: $fs = 'my documents\n\tproject v1.0\n\t\tnotes
   v1.txt\n\timage.png'
Output: 38
Notice project v1.0 is a directory (it has children beneath 
   it), while notes v1.txt and image.png are files.
Found File Paths:
    'my documents/project v1.0/notes v1.txt' (length = 38)
    'my documents/image.png' (length = 22)
The maximum absolute length is 38.

Example 4
Input: $fs = 'root\n\ta\n\t\tb\n\t\t\tc.txt\n\td\n\t\te.txt'
Output: 14
Found File Paths:
    'root/a/b/c.txt' => 4 + 1 + 1 + 1 + 1 + 1 + 5 = 14
    'root/d/e.txt'   => 4 + 1 + 1 + 1 + 5 = 12
The longest file path is 'root/a/b/c.txt' with length 14.

Example 5
Input: $fs =
   'a\n\tb\n\t\tc\n\t\t\td\n\t\t\t\te.txt\n\tvery_long_directory_name\
   n\t\tf.txt'
Output: 32
Found File Paths:
    'a/b/c/d/e.txt' => 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 5 = 13
    'a/very_long_directory_name/f.txt' => 1 + 1 + 24 + 1 + 5 = 32
The long directory name compensates for depth, giving a max length of
   32.

Analysis

This is not difficult but rather messy. I have assumed that a file can be distinguished from a directory in that a filename contains a '.' and a directory name doesn’t.

So it’s then just a case of analysing the input string using something like

$string = m|¦(\n*)([^\t]*)|g

except that it's easier to replace \t and \n with single printable characters, for which I used ¦ and §.

The node depth is then length($1) - derived from the number of tabs - and the node name is $2. If the node is a file - ie its name includes a '.' - I caculate its full path length, and I keep track of the longest path.

Try it 

Your input:



eg: root\n\ta\n\t\tb\n\t\t\tc.txt\n\td\n\t\te.txt

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge/399/2

use v5.26;    # The Weekly Challenge - 2026-11-09
use utf8;     # Week 399 - task 2 - Longest absolute path
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

longest_absolute_path('dir\n\tsubdir1\n\t\tsubsubdir1\n\tsubdir2');
longest_absolute_path('file1.txt\nfile2.ext\na.png');
longest_absolute_path('my documents\n\tproject v1.0\n\t\t' .
    'notes v1.txt\n\timage.png');
longest_absolute_path('root\n\ta\n\t\tb\n\t\t\tc.txt\n\td\n\t\t' .
    'e.txt');
longest_absolute_path('a\n\tb\n\t\tc\n\t\t\td\n\t\t\t\te.txt\n\t' .
    'very_long_directory_name\n\t\tf.txt');

sub longest_absolute_path {
    
    my ($string, $depth, @node, $path, $length, $max_length, 
        $longest, $string2, $line);
    
    # initialise
    $string = '¦' . $_[0];
    $max_length = 0;
    $longest = '';
    
    # loop over lines
    $string =~ s|\\n|¦|g;
    $string =~ s|\\t|§|g;
    while ($string =~ m|¦(§*)([^¦]*)|g) {
        $depth = length($1);
        $node[$depth] = $depth == 0 ? $2 : qq[/$2];
        
        # make pretty dir structure
        $line = (' ¬ ' x $depth) . $node[$depth];
        $line =~ s|§| ¬ |g;
        $string2 .= '   ' . $line . qq[\n];
        
        # get file path and path length
        $path = '';
        $path .= qq[$node[$_]] for 0 .. $depth;
        if ($node[$depth] =~ m|\.|) {
            $length = length($path);
            if ($length > $max_length) {
                $max_length = $length;
                $longest = $path;
            } elsif ($length == $max_length) {
                $longest .= qq[, $path];
            }
        }
    }
    
    # report
    $string = $_[0];
    $string =~ s|\\|/|g;
    say qq[\nInput:  '$_[0]' - which is:\n$string2];
    if ($max_length) {
        say qq[Output: longest file path = $longest];
        say qq[                   length = $max_length];
    } else {
        say qq[Output: no files found];
    }
}

30 lines of code

Output from script


Input:  'dir\n\tsubdir1\n\t\tsubsubdir1\n\tsubdir2' - which is:
   dir
    ¬ /subdir1
    ¬  ¬ /subsubdir1
    ¬ /subdir2

Output: no files found

Input:  'file1.txt\nfile2.ext\na.png' - which is:
   file1.txt
   file2.ext
   a.png

Output: longest file path = file1.txt, file2.ext
                   length = 9

Input:  'my documents\n\tproject v1.0\n\t\tnotes v1.txt\n\timage.png' 
	- which is:
   my documents
    ¬ /project v1.0
    ¬  ¬ /notes v1.txt
    ¬ /image.png

Output: longest file path = my documents/project v1.0/notes v1.txt
                   length = 38

Input:  'root\n\ta\n\t\tb\n\t\t\tc.txt\n\td\n\t\te.txt' - which is:
   root
    ¬ /a
    ¬  ¬ /b
    ¬  ¬  ¬ /c.txt
    ¬ /d
    ¬  ¬ /e.txt

Output: longest file path = root/a/b/c.txt
                   length = 14

Input:  'a\n\tb\n\t\tc\n\t\t\td\n\t\t\t\te.txt\n\tvery_long_
	directory_name\n\t\tf.txt' - which is:
   a
    ¬ /b
    ¬  ¬ /c
    ¬  ¬  ¬ /d
    ¬  ¬  ¬  ¬ /e.txt
    ¬ /very_long_directory_name
    ¬  ¬ /f.txt

Output: longest file path = a/very_long_directory_name/f.txt
                   length = 32

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain