Persingkat jalur absolut


17

Terkadang jalur absolut yang panjang, misalnya parameter baris perintah ke alat linux, dapat dipersingkat, menggunakan direktori kerja saat ini sebagai referensi:

$ pwd
/home/heh

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

$ cat mydir/myfile
my stuff

Dalam tantangan ini, Anda harus membuat fungsi atau program yang menerima dua parameter:

  1. Path absolut, menggunakan format linux (dimulai dengan /)
  2. Direktori saat ini, menggunakan format yang sama

Outputnya lebih pendek dari yang berikut:

  • Masukan 1 tidak berubah
  • Path relatif yang merujuk ke file / direktori yang sama dengan path absolut

Poin bagus:

  • Jika sistem operasi Anda kompatibel dengan linux, Anda dapat menggunakan direktori sistem saat ini alih-alih menerimanya sebagai input
  • Anda dapat mengasumsikan input hanya berisi karakter alfanumerik (dan pemisah jalur)
  • Anda dapat mengasumsikan jalur absolut input tidak memiliki pemisah jalur /pada akhirnya
  • Anda dapat mengasumsikan direktori input saat ini memiliki pemisah jalur /di akhir
  • Anda tidak dapat berasumsi bahwa path absolut merujuk ke file yang ada, atau bagian mana pun dari itu adalah direktori yang dapat diakses; Namun, direktori saat ini dapat dianggap valid
  • Anda dapat berasumsi bahwa tidak ada symlink di dekat kedua jalur - karena saya tidak ingin memerlukan cara khusus untuk berurusan dengan symlink
  • Tidak perlu mendukung kasus di mana salah satu input adalah direktori root
  • "Direktori saat ini" harus berupa keluaran sebagai .(string kosong tidak valid)

Kasus uji (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
"Anda dapat mengasumsikan direktori input saat ini memiliki pemisah jalur /pada akhirnya". Namun, dalam contoh Anda, ini tidak terjadi.
Shaggy

1
Saya suka dengan cara ini, tetapi beberapa orang menyukainya dengan cara lain
anatolyg


Apa yang harus terjadi jika jalur absolut dan relatif memiliki panjang yang sama?
Dennis

1
Ini kehilangan beberapa kasus uji kritis: /home/test /home/user/mydir/myfile /home/testdan/a/b /a/b/d/e /a/b
Nathan Merrill

Jawaban:


7

Julia 0,5 , 32 byte

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

Ini menggunakan direktori kerja saat ini sebagai basis dan tidak dapat diuji pada TIO saat ini.

Contoh dijalankan

Peringatan: Ini akan mengubah sistem file Anda.

$ 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")
"."

Versi alternatif, 35 byte (diad)

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

Ini mengambil direktori dasar sebagai input, sehingga dapat diuji tanpa memodifikasi sistem file.

Cobalah online!


Mendefinisikan ulang Base.-kesalahan kecuali diimpor secara eksplisit, bukan?
Julian Wolf

Dalam 0,5, mungkin kesalahan, tetapi hanya jika Anda menggunakan -sebelum mendefinisikannya kembali. Di 0,4, ia mencetak peringatan apakah Anda menggunakannya sebelum redefinisi atau tidak.
Dennis

9

JavaScript (ES6), 107 106 byte

Mengambil jalur absolut adan jalur saat ini cdalam sintaks currying (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||'.'

Uji kasus


Trik yang sangat menyenangkan [a.length]! Bolehkah saya meminjamnya untuk meningkatkan jawaban Node.js saya?
zeppelin

@zeppelin Tentu. Lakukan itu!
Arnauld


5

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

  • Gunakan string kosong, alih-alih "." untuk menunjukkan direktori saat ini (pada input), -1 byte
  • Meminjam [f.length]trik dari jawaban @ Arnauld , -6 byte
  • Gunakan direktori saat ini daripada parameter direktori eksplisit, -2 byte
  • Menghapus tanda kurung yang berlebihan, -2 byte

Golf

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

Uji

> 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")
'.'

Apakah kita tidak mengizinkan fungsi node.js?
Downgoat

@Downgoat Javascript lambdas diterima secara luas, sebagai bentuk jawaban, jadi saya tidak melihat mengapa Node.js harus ditangani secara berbeda.
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)

Cobalah secara Online!

Agak lama, tapi saya ingin melakukan solusi tanpa fungsi path bawaan.

Sunting: 9 byte ditambahkan ke akun untuk test case yang disediakan oleh Nathan Merrill


3

Zsh + realpath, 58 byte

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

Cobalah online!

Versi bash, 62 byte

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

Cobalah online!


Mengapa tidak mempostingnya dalam dua jawaban yang berbeda? Setiap bahasa penting!
gaborsch

2

Python 3 - 53 byte

Menggunakan os.path:

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

Program lengkap (61 byte):

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

Oo, poin bagus. Python memimpin sekarang, yay!
matsjoyce

@anatolyg Ha, saya tahu saya akan kehilangan setidaknya satu test case ... 😒 Semua sudah diperbaiki sekarang.
matsjoyce

1

PHP, 204 Bytes

[,$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:".";

Testcases

Diperluas

[,$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
    :".";

jika Output ../../sebagai gantinya of ../..dibolehkan dapat dipersingkat menjadi 175 Bytes

[,$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:".";

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.