Accorcia un percorso assoluto


17

A volte un percorso assoluto lungo, ad esempio un parametro della riga di comando per uno strumento linux, può essere abbreviato, usando l'attuale directory di lavoro come riferimento:

$ pwd
/home/heh

$ cat /home/heh/mydir/myfile
my stuff

$ cat mydir/myfile
my stuff

In questa sfida, è necessario creare una funzione o un programma che riceve due parametri:

  1. Percorso assoluto, usando il formato linux (inizia con /)
  2. Directory corrente, utilizzando lo stesso formato

L'output è il più breve dei seguenti:

  • Ingresso 1 invariato
  • Percorso relativo che fa riferimento allo stesso file / directory del percorso assoluto

Punti positivi:

  • Se il tuo sistema operativo è compatibile con Linux, puoi utilizzare la directory corrente del sistema invece di riceverla come input
  • Puoi assumere che gli input contengano solo caratteri alfanumerici (e separatori di percorso)
  • Puoi supporre che il percorso assoluto di input non abbia un separatore di percorso /alla fine
  • Si può presumere che la directory corrente di input abbia un separatore di percorso /alla fine
  • Non si può presumere che il percorso assoluto si riferisca a un file esistente o che qualsiasi parte di esso sia una directory accessibile; tuttavia, la directory corrente può essere considerata valida
  • Puoi presumere che non ci siano link simbolici da nessuna parte vicino a nessuno dei due percorsi, perché non voglio richiedere alcun modo speciale per gestire i link simbolici
  • Non è necessario supportare il caso in cui uno degli input sia la directory principale
  • "La directory corrente" deve essere emessa come .(una stringa vuota non è valida)

Casi di test (input1, input2, output):

/home/user/mydir/myfile
/home/user
mydir/myfile

/var/users/admin/secret/passwd
/var/users/joe/hack
../../admin/secret/passwd

/home/user/myfile
/tmp/someplace
/home/user/myfile

/dir1/dir2
/dir1/dir2/dir3/dir4
../..

/dir1/dir2
/dir1/dir2
.

1
"Puoi presumere che la directory corrente di input abbia un separatore di percorso /alla fine". Tuttavia, nei tuoi esempi, non è così.
Shaggy,

1
Mi piace in questo modo, ma ad alcune persone piace l'altro
anatolyg


Cosa dovrebbe accadere se il percorso assoluto e relativo hanno la stessa lunghezza?
Dennis,

1
Mancano alcuni casi di test critici: /home/test /home/user/mydir/myfile /home/teste/a/b /a/b/d/e /a/b
Nathan Merrill il

Risposte:


7

Julia 0,5 , 32 byte

!,~=relpath,endof
t->~t<~!t?t:!t

Questo utilizza l'attuale directory di lavoro come base e al momento non può essere testato su TIO.

Esempio di esecuzione

Avviso: questo modificherà il tuo file system.

$ sudo julia --quiet
julia> function test(target,base)
       mkpath(base)
       cd(base)
       shorten(target)
       end
test (generic function with 1 method)
julia> !,~=relpath,endof
(relpath,endof)

julia> shorten = t->~t<~!t?t:!t
(::#1) (generic function with 1 method)

julia> test("/home/user/mydir/myfile","/home/user")
"mydir/myfile"

julia> test("/var/users/admin/secret/passwd","/var/users/joe/hack")
"../../admin/secret/passwd"

julia> test("/home/user/myfile","/tmp/someplace")
"/home/user/myfile"

julia> test("/dir1/dir2","/dir1/dir2/dir3/dir4")
"../.."

julia> test("/dir1/dir2","/dir1/dir2")
"."

Versione alternativa, 35 byte (diadica)

^,~=relpath,endof
t-b=~t<~t^b?t:t^b

Questo prende la directory di base come input, quindi può essere testata senza modificare il file system.

Provalo online!


Ridefinire gli Base.-errori se non importati esplicitamente, no?
Julian Wolf,

In 0,5, potrebbe essere un errore, ma solo se lo si utilizza -prima di ridefinirlo. In 0.4, stampa un avviso se lo usi prima della ridefinizione o meno.
Dennis,

9

JavaScript (ES6), 107 106 byte

Prende il percorso assoluto ae il percorso corrente cnella sintassi del curry (a)(c).

a=>c=>(A=a.split`/`,s='',c.split`/`.map(d=>!s&A[0]==d?A.shift():s+='../'),s+=A.join`/`)[a.length]?a:s||'.'

Casi test


Un bel trucco con [a.length]! Posso prenderlo in prestito per migliorare la mia risposta Node.js?
zeppelin,

@zeppelin Certo. Fallo!
Arnauld,


5

ES6 (Node.js REPL), 56, 54, 46, 45 byte

  • Usa una stringa vuota, anziché "." per indicare la directory corrente (sull'input), -1 byte
  • Preso in prestito il [f.length]trucco dalla risposta di @ Arnauld , -6 byte
  • Utilizzare la directory corrente anziché un parametro di directory esplicito, -2 byte
  • Rimosse parentesi superflue, -2 byte

golfed

f=>(r=path.relative("",f))[f.length]?f:r||"."

Test

> F=f=>(r=path.relative("",f))[f.length]?f:r||"."
[Function: F]

> F("/home/user/mydir/myfile")
'mydir/myfile'

> F("/var/users/admin/secret/passwd")
'../../admin/secret/passwd'

> F("/home/user/myfile")
'/home/user/myfile'

> F("/dir1/dir2")
'../..'

> F("/dir1/dir2")
'.'

Non consentiamo le funzioni node.js?
Downgoat,

@Downgoat I lambda Javascript sono ampiamente accettati, come una forma di risposta, quindi non vedo perché Node.js debba essere gestito in modo diverso.
zeppelin,

4

Python 2, 135 144 byte

i=0
a,c=input()
b,d=a.split('/')*(a!=c),c.split('/')
while b[:i+1]==d[:i+1]:i+=1
print'.'[i:]or min('/'.join(['..']*len(d[i:])+b[i:]),a,key=len)

Provalo online!

Un po 'lungo, ma volevo fare una soluzione senza funzioni di percorso integrate.

Modifica: 9 byte aggiunti all'account per il test case fornito da Nathan Merrill


3

Zsh + realpath, 58 byte

r=`realpath -m --relative-to=$*`
(($#2<$#r))&&r=$2
echo $r

Provalo online!

Versione Bash, 62 byte

r=`realpath -m --relative-to=$*`
((${#2}<${#r}))&&r=$2
echo $r

Provalo online!


Perché non pubblicarlo in due risposte diverse? Ogni lingua conta!
gaborsch,

2

Python 3 - 53 byte

Utilizzando os.path:

import os
lambda x:min(x,os.path.relpath(x),key=len)

Programma completo (61 byte):

import os
x=input();print(min(x,os.path.relpath(x),key=len))

Oo, buoni punti. Python è in testa ora, yay!
matsjoyce,

@anatolyg Ah, sapevo che mi sarei perso almeno un caso di test ... 😒 Tutto risolto ora.
matsjoyce,

1

PHP, 204 byte

[,$l,$p]=$argv;$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));$m=str_pad("",3*count($z)-1,"../");$j=join("/",$r=$d($x,$y));echo$l!=$p?strlen($u=$m&&$j?"$m/$j":$m.$j)<strlen($l)?$u:$l:".";

Casi test

allargato

[,$l,$p]=$argv;
$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));
$m=str_pad("",3*count($z)-1,"../");
$j=join("/",$r=$d($x,$y));
echo$l!=$p
    ?strlen($u=$m&&$j?"$m/$j":$m.$j)<strlen($l)
      ?$u
      :$l
    :".";

se ../../invece of ../..è consentito un output , può essere ridotto a 175 byte

[,$l,$p]=$argv;$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));echo$l!=$p?strlen($m=str_pad("",3*count($z),"../").join("/",$r=$d($x,$y)))<strlen($l)?$m:$l:".";

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.