ย่นเส้นทางที่แน่นอน


17

บางครั้งพา ธ สัมบูรณ์ที่มีความยาวเช่นในพารามิเตอร์บรรทัดคำสั่งไปยังเครื่องมือ linux สามารถทำให้สั้นลงโดยใช้ไดเรกทอรีการทำงานปัจจุบันเป็นข้อมูลอ้างอิง:

$ pwd
/home/heh

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

$ cat mydir/myfile
my stuff

ในการท้าทายนี้คุณควรสร้างฟังก์ชันหรือโปรแกรมที่รับพารามิเตอร์สองตัว:

  1. พา ธ สัมบูรณ์โดยใช้รูปแบบ linux (เริ่มต้นด้วย/)
  2. ไดเรกทอรีปัจจุบันโดยใช้รูปแบบเดียวกัน

เอาต์พุตจะสั้นกว่าดังต่อไปนี้:

  • อินพุต 1 ไม่เปลี่ยนแปลง
  • พา ธ สัมพัทธ์ที่อ้างถึงไฟล์ / ไดเร็กทอรีเดียวกันกับพา ธ สัมบูรณ์

คะแนนดี:

  • หากระบบปฏิบัติการของคุณเข้ากันได้กับ linux คุณสามารถใช้ไดเรกทอรีปัจจุบันของระบบแทนการรับมันเป็นอินพุต
  • คุณสามารถสมมติว่าอินพุตมีอักขระตัวอักษรและตัวเลขเท่านั้น (และตัวคั่นพา ธ )
  • คุณสามารถสันนิษฐานได้ว่าเส้นทางสัมบูรณ์การป้อนข้อมูลไม่มีตัวคั่นเส้นทาง/ในตอนท้าย
  • คุณสามารถสมมติว่าไดเรกทอรีปัจจุบันของการป้อนข้อมูลมีตัวคั่นเส้นทาง/ในตอนท้าย
  • คุณไม่สามารถสันนิษฐานได้ว่าพา ธ สัมบูรณ์อ้างถึงไฟล์ที่มีอยู่หรือส่วนใด ๆ ของมันเป็นไดเรกทอรีที่เข้าถึงได้ อย่างไรก็ตามไดเรกทอรีปัจจุบันสามารถสันนิษฐานได้ว่าถูกต้อง
  • คุณสามารถสันนิษฐานได้ว่าไม่มี symlink ที่ใดก็ได้ที่อยู่ใกล้เส้นทางใด - เพราะฉันไม่ต้องการวิธีพิเศษในการจัดการกับ symlink
  • ไม่จำเป็นต้องสนับสนุนเคสที่อินพุตใด ๆ เป็นไดเร็กทอรีรูท
  • "ไดเรกทอรีปัจจุบัน" ควรส่งออกเป็น.(สตริงว่างไม่ถูกต้อง)

กรณีทดสอบ (อินพุต 1, อินพุต 2, เอาต์พุต):

/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
msgstr "คุณสามารถสมมติว่าไดเรกทอรีปัจจุบันของอินพุตมีตัวคั่นพา ธ/ในตอนท้าย". อย่างไรก็ตามในตัวอย่างของคุณนี่ไม่ใช่กรณี
Shaggy

1
ฉันชอบวิธีนี้ แต่บางคนชอบวิธีอื่น
Anatolyg

เกี่ยวข้องอย่างใกล้ชิด
AdmBorkBork

จะเกิดอะไรขึ้นหากเส้นทางสัมบูรณ์และเส้นทางสัมพัทธ์มีความยาวเท่ากัน
Dennis

1
กรณีนี้ขาดการทดสอบที่สำคัญบางอย่าง /home/test /home/user/mydir/myfile /home/testและ/a/b /a/b/d/e /a/b
นาธานเมอร์ริลล์

คำตอบ:


7

Julia 0.5 , 32 ไบต์

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

สิ่งนี้ใช้ไดเรกทอรีการทำงานปัจจุบันเป็นฐานและไม่สามารถทดสอบบน TIO ได้ในขณะนี้

ตัวอย่างการวิ่ง

คำเตือน:นี่จะเปลี่ยนระบบไฟล์ของคุณ

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

รุ่นสำรอง 35 ไบต์ (dyadic)

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

นี่ใช้ไดเรกทอรีฐานเป็นอินพุตดังนั้นจึงสามารถทดสอบได้โดยไม่ต้องแก้ไขระบบไฟล์

ลองออนไลน์!


การกำหนดBase.-ข้อผิดพลาดซ้ำหากไม่ได้นำเข้าอย่างชัดเจนไม่ใช่หรือ
Julian Wolf

ใน 0.5 มันอาจผิดพลาด แต่ถ้าคุณใช้-ก่อนที่จะนิยามใหม่ ใน 0.4 มันจะพิมพ์คำเตือนว่าคุณใช้ก่อนที่จะกำหนดใหม่หรือไม่
เดนนิส

9

JavaScript (ES6), 107 106 ไบต์

ใช้เส้นทางที่แน่นอนaและเส้นทางปัจจุบันในไวยากรณ์c 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||'.'

กรณีทดสอบ


เคล็ดลับที่ดีมาก ๆ[a.length]! ฉันขอยืมเพื่อปรับปรุงคำตอบของ Node.js ได้ไหม
zeppelin

@zeppelin แน่นอน ไปเลย!
Arnauld


5

ES6 (Node.js REPL), 56, 54, 46, 45 ไบต์

  • ใช้สตริงที่ว่างเปล่าแทน "." เพื่อแสดงถึงไดเรกทอรีปัจจุบัน (ในอินพุต), -1 ไบต์
  • ยืม[f.length]เคล็ดลับจากคำตอบของ @ Arnauld ขนาด -6 ไบต์
  • ใช้ไดเรกทอรีปัจจุบันแทนพารามิเตอร์ไดเรกทอรีชัดเจน -2 ไบต์
  • ลบวงเล็บฟุ่มเฟือย -2 ไบต์

แข็งแรงเล่นกอล์ฟ

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

ทดสอบ

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

เราไม่อนุญาตให้ใช้ฟังก์ชั่น node.js หรือไม่
Downgoat

@Downgoat Javascript lambdas ได้รับการยอมรับอย่างกว้างขวางว่าเป็นรูปแบบของคำตอบดังนั้นฉันไม่เห็นว่าทำไม Node.js จึงควรจัดการแตกต่างกัน
Zeppelin

4

Python 2, 135 144 ไบต์

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)

ลองออนไลน์!

ค่อนข้างยาว แต่ฉันต้องการแก้ปัญหาโดยไม่มีฟังก์ชั่นพา ธ ในตัว

แก้ไข:เพิ่ม 9 ไบต์ในบัญชีสำหรับกรณีทดสอบที่จัดทำโดย Nathan Merrill


3

Zsh + realpath 58 ไบต์

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

ลองออนไลน์!

รุ่น Bash ขนาด 62 ไบต์

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

ลองออนไลน์!


ทำไมไม่โพสต์มันในสองคำตอบที่แตกต่างกันอย่างไร ทุกภาษามีความสำคัญ!
gaborsch

2

Python 3 - 53 ไบต์

การใช้os.path:

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

โปรแกรมเต็มรูปแบบ (61 ไบต์):

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

โอ้ดีมาก ไพ ธ อนเป็นผู้นำในตอนนี้ใช่!
matsjoyce

@anatolyg ฮ่าฉันรู้ว่าฉันพลาดการทดสอบอย่างน้อยหนึ่งกรณี ... 😒แก้ไขเรียบร้อยแล้ว
matsjoyce

1

PHP, 204 ไบต์

[,$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

ขยาย

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

ถ้าอนุญาตให้ส่งออก../../แทนof ../..มันจะสั้นลงถึง 175 ไบต์

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.