3
\$\begingroup\$

Consider this file path:

C:/Users/Martin/Desktop/BackupFiles/PC1/images/cars/new.png

Your goal is to write a program that will return the file path starting from the folder after the last folder that contains a number till the filename. So, for the above file path, the program should return images/cars/new.png.

One or more of the folder names may also contain spaces:

C:/Users/User1/Documents/Books/eBooks/PM2.4/ref/Project Management.pdf

should return ref/Project Management.pdf.

Also this filepath:

C:/Users/John/Videos/YouTube/3D/Animations/52.Tricky.Maneuvers/video234.png

should return video234.png.

Your answer should work with the above given three examples and all other examples that match the criteria described here.

This is , so the answer with the lowest number of bytes yields victory.

I am new to the site, so feel free to modify my post and/or add relevant tags.

\$\endgroup\$
  • 1
    \$\begingroup\$ @Stephen "challenge proposer". \$\endgroup\$ – user202729 Sep 14 '18 at 15:52
  • 3
    \$\begingroup\$ Do we have to support some weird Unicode characters like ߈ ("NKO DIGIT EIGHT") and would it be considered a number? \$\endgroup\$ – user202729 Sep 14 '18 at 16:00
  • 1
    \$\begingroup\$ @WaisKamal are backslashes considered legitimate path separators? \$\endgroup\$ – hidefromkgb Sep 14 '18 at 16:09
  • 4
    \$\begingroup\$ I'm not clear on why the third test case is supposed to return Animations/52.Tricky.Maneuvers/video234.png as opposed to video234.png. Why does the folder 52.Tricky.Maneuvers not count as " the last folder that contains a number"? \$\endgroup\$ – mypetlion Sep 14 '18 at 16:22
  • 2
    \$\begingroup\$ I agree with @mypetlion. 52.Tricky.Maneuvers contains a digit, so shouldn't it output video234.png instead? And if you mean by "starting from the folder after the last folder that contains a number till the filename" that there should always be at least one folder (regardless if it contains digits) before the file-path, doesn't that mean that C:\a1\a.pdf should output C:\a1\a.pdf?.. \$\endgroup\$ – Kevin Cruijssen Sep 14 '18 at 16:52

14 Answers 14

1
\$\begingroup\$

Retina, 9 bytes

.*\d.*?/

Regex is ported from @Arnauld's JavaScript answer, so make sure to upvote him!

Try it online.

Explanation:

.*\d.*?/    # Main regex:
.*          #  Zero or more characters (as much as possible)
  \d        #  Followed by a digit
    .*?     #  Followed by zero or more optional characters (as few as possible)
       /    #  Followed by a slash

            # Replace the match with:
            #  Nothing (so basically remove that leading part)
\$\endgroup\$
  • \$\begingroup\$ Don't worry, I upvoted all correct answers :) \$\endgroup\$ – Wais Kamal Sep 18 '18 at 14:34
5
\$\begingroup\$

JavaScript (ES6), 29 28 bytes

Saved 1 byte thanks to @tsh

s=>s.replace(/.*\d.*?\//,'')

Try it online!

How?

                                             /.*\d.*?\//
                                              \/\/\_/\/
                                              | |  | |
match the longest possible string (greedy) ---+ |  | |
match a digit ----------------------------------+  | |
match the shortest possible string (lazy) ---------+ |
match a slash ---------------------------------------+
\$\endgroup\$
  • \$\begingroup\$ So, why not s=>s.replace(/.*\d.*?\//,'')? \$\endgroup\$ – tsh Sep 16 '18 at 8:18
  • \$\begingroup\$ @tsh Because I didn't realize it would be 1 byte shorter. :p Thanks! \$\endgroup\$ – Arnauld Sep 16 '18 at 8:46
4
\$\begingroup\$

sed, 17 bytes

s:.*[0-9][^/]*/::

Try it online.

\$\endgroup\$
4
\$\begingroup\$

Gema, 8 bytes

*<D>*\/=

Sample run:

bash-4.4$ gema '*<D>*\/=' <<< 'C:/Users/Martin/Desktop/BackupFiles/PC1/images/cars/new.png'
images/cars/new.png

bash-4.4$ gema '*<D>*\/=' <<< 'C:/Users/User1/Documents/Books/eBooks/PM2.4/ref/Project Management.pdf'
ref/Project Management.pdf

bash-4.4$ gema '*<D>*\/=' <<< 'C:/Users/John/Videos/YouTube/3D/Animations/52.Tricky.Maneuvers/video234.png'
video234.png

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Can you please add a Try It Online link? I am not familiar with Gema. \$\endgroup\$ – Wais Kamal Sep 17 '18 at 14:24
  • \$\begingroup\$ Sorry, unfortunately there is no Gema or GeL interpreter on TIO. ☹ \$\endgroup\$ – manatwork Sep 17 '18 at 14:28
  • \$\begingroup\$ Requested. \$\endgroup\$ – Jonathan Allan Sep 17 '18 at 20:40
3
\$\begingroup\$

Powershell 42 39 45 30 26 bytes

Find the last decimal before a /, fetch all after the slash as the new path

($args-split'.*\d.*?/')[1]

Try it out!


- many bytes by tips from @mazzy
- 1 byte by removing non-required regex escape
- 4 bytes as the regex with -split didn't require a group
- added greedy decimal search

\$\endgroup\$
  • \$\begingroup\$ Great! I think $args is better then param($f)$f \$\endgroup\$ – mazzy Sep 14 '18 at 18:15
  • 1
    \$\begingroup\$ Completely right, although using $args within an expression always seems to return the original value, powershell might think of it as an array with ToString() or something. Works fine with indexer though. \$\endgroup\$ – Edwin Sep 14 '18 at 19:23
  • \$\begingroup\$ "$args". Welcome to Tips for golfing in PowerShell \$\endgroup\$ – mazzy Sep 14 '18 at 21:07
  • \$\begingroup\$ The script return 2 values: $true/$false from -match expression and match string. I think should return the file path means the file path only. I beleave it can be golfed more. \$\endgroup\$ – mazzy Sep 14 '18 at 21:11
  • 1
    \$\begingroup\$ split had a lot of additional perks :) \$\endgroup\$ – Edwin Sep 15 '18 at 14:10
2
\$\begingroup\$

Python 2, 74 bytes

r='';k=1
for c in input():
 r+=c;k-=c.isdigit()
 if'/'==c:r*=k;k=1
print r

Try it online!


Python 2, 42 bytes

lambda n:re.sub(".*\d.*?/","",n)
import re

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Java (JDK 10), 26 bytes

s->s.split(".*\\d.*?/")[1]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Matlab, 68 bytes

function[r]=f(s),[~,b]=regexp(s,'/[^/;]+\d[^/;]+/');r=s(b+1:end);end

Try it Online!

\$\endgroup\$
1
\$\begingroup\$

Jelly, 16 bytes

”/ɓṣṖf€ØDTṀ‘ṫ@ṣj

A monadic Link accepting a list of characters which returns a list of characters.

Try it online!

How?

”/ɓṣṖf€ØDTṀ‘ṫ@ṣj - Link: list of characters X
”/               - literal '/' character
  ɓ              - start a new dyadic chain with swapped arguments - i.e. f(X,'/')
   ṣ             - split (X) at ('/')
    Ṗ            - pop (removes the rightmost)
       ØD        - yield digit characters
      €          - for each: (of the parts of X after the split & pop)
     f           -   filter keep (digit characters)
         T       - truthy indices (1-indexed indices of parts containing any digit(s))
          Ṁ      - maximum (rightmost, zero if not found)
           ‘     - increment
              ṣ  - split (X) at ('/') (...again)
             @   - with swapped arguments:
            ṫ    -   tail (the split X) from index (the incremented maximum...)
               j - join with ('/')
\$\endgroup\$
1
\$\begingroup\$

Red, 79 bytes

func[s][d: charset"0123456789"parse s[any[to d thru"/"]copy t to end(print t)]]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Pyth, 14 bytes

The same regex solution that everybody else is using:

:z"^.*\d.*?/""

:                     regex replace
 z                    in the input() string
  "^.*\d.*?/"         the file path up until the last path with a number
             "        with an empty string (Pyth terminates this string at end of program)
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 23 bytes

'/©¡RćUηí®ýʒþd_}®«õš¤X«

Try it online or verify all test cases.

05AB1E has no regexes, so this is not the kind of challenge it will do very good, in comparison to non-verbose languages that have a strength in regexes like Retina or Pyth.
Can probably still be golfed by at least a few bytes, though.

Explanation:

'/              # Push a "/"
  ©             # Store it in the register (without popping)
   ¡            # Split the (implicit) input on slashes
                #  i.e. "C:/Desktop3/Stuff/F0/images/new1.png"
                #   → ["C:","Desktop3","Stuff","F0","images","new1.png"]
    R           # Reverse this list
                #  i.e. ["C:","Desktop3","Stuff","F0","images","new1.png"]
                #   → ["new1.png","images","F0","Stuff","Desktop3","C:"]
     ć          # Head extracted
                #  i.e. ["new1.png","images","F0","Stuff","Desktop3","C:"]
                #   → ["images","F0","Stuff","Desktop3","C:"] and "new1.png"
      U         # Pop the extracted head, and store it in variable `X`
       η        # Take the prefixes of the list
                #  i.e. ["images","F0","Stuff","Desktop3","C:"]
                #   → [["images"],["images","F0"],["images","F0","Stuff"],["images","F0","Stuff","Desktop3"],["images","F0","Stuff","Desktop3","C:"]]
        í       # Reverse each inner list again
                #  i.e. [["images"],["images","F0"],["images","F0","Stuff"],["images","F0","Stuff","Desktop3"],["images","F0","Stuff","Desktop3","C:"]]
                #   → [["images"],["F0","images"],["Stuff","F0","images"],["Desktop3","Stuff","F0","images"],["C:","Desktop3","Stuff","F0","images"]]
         ®ý     # And join them by slashes
                #  i.e. [["images"],["F0","images"],["Stuff","F0","images"],["Desktop3","Stuff","F0","images"],["C:","Desktop3","Stuff","F0","images"]]
                #   → ["images","F0/images","Stuff/F0/images","Desktop3/Stuff/F0/images","C:/Desktop3/Stuff/F0/images"]
ʒ   }           # Now filter this list by:
 þ              #  Leave only the digits of this suffix
                #   i.e. "images" → ""
                #   i.e. "Stuff/F0/images" → 0
  d             #  Check if its >= 0
                #   i.e. "" → 0 (falsey)
                #   i.e. 0 → 1 (truthy)
   _            #  Inverse the boolean (0→1; 1→0)
     ®«         # Append a slash to each remaining suffix
                #  i.e. ["images"] → ["images/"]
       õš       # Prepend an empty string as list
                # (work-around when there are no valid suffices left)
                #  i.e. [] → [""]
                #  i.e. ["images/"] → ["","images/"]
         ¤      # Take the last suffix
                #  i.e. ["","images/"] → "images/"
          X«    # Append variable `X` (and implicitly output the result)
                #  i.e. "images/" and "new1.png" → "images/new1.png"
\$\endgroup\$
1
\$\begingroup\$

Ruby, 22 bytes

->s{s=~/.*\d.*?\//;$'}

Try it online!

Same trick as Arnauld and everybody else after him.

\$\endgroup\$
0
\$\begingroup\$

Pip, 12 bytes

a@`\d.*?/`$'

Takes input as a command-line argument. Verify all test cases: Try it online!

Explanation

Does not use the same regex as everyone else! (Well, okay, it's pretty similar.)

a             1st command-line argument
  `\d.*?/`    Regex matching a digit, as few characters as possible, and then a slash
 @            Find all matches
          $'  Special variable: the portion of the string after the last match
              Autoprint

The shortest solutions using the standard regex were all 13 bytes:

aRM`.*\d.*?/`   Remove
a|>`.*\d.*?/`   Left-strip
aR`.*\d.*?/`x   Replace with empty string
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.