การคำนวณสารบบ


19

สำหรับความท้าทายนี้คุณจะได้รับเส้นทางที่แน่นอนและเส้นทาง "ใหม่" (ซึ่งอาจเป็นแบบสัมบูรณ์หรือแบบสัมพัทธ์) และคุณต้องกลับเส้นทางสุดท้าย

ตัวอย่างเช่นหากไดเรกทอรีปัจจุบันของคุณคือ/var/tmp/test:

my_dirหรือmy_dir/ ควรกลับมา/var/tmp/test/my_dir

../../my_dir ควรกลับมา /var/my_dir

/my_dir/./ ควรกลับมา /my_dir

../../../../../ ควรกลับมา /

หากต้องการความคล่องแคล่วมากขึ้น:

  • ไดเรกทอรีเป็นสตริงที่ไม่ว่างเปล่าประกอบด้วยตัวอักษรและตัวเลขและสัญลักษณ์-, _หรือ.
  • เส้นทางนี้เป็นรายการของ 0 หรือมากกว่าไดเรกทอรี/แยกโดยใช้ พา ธ สัมบูรณ์เริ่มต้นด้วย a /, พา ธ สัมพัทธ์ไม่ /เส้นทางอาจรวมถึงตอนจบ

คุณต้อง "แก้ไข" เส้นทางที่สองให้เส้นทางแรก

กระบวนการแก้ไขคือ:

  1. ทดสอบว่าเส้นทางที่สองสัมพันธ์หรือไม่ ถ้าเป็นเช่นนั้นให้ใส่ไดเรกทอรีของเส้นทางที่แน่นอนไปยังจุดเริ่มต้นของเส้นทางที่สอง
  2. หากมีไดเรกทอรีใด ๆ ให้..ลบออกและไดเรกทอรีก่อนหน้า หากเป็นไดเรกทอรีแรกให้ลบออก
  3. หากมีไดเรกทอรีใด ๆ ให้.ลบออก
  4. เอาต์พุตพา ธ สัมบูรณ์สุดท้าย /คุณไม่ควรออกสิ้นสุด

คุณไม่จำเป็นต้องจัดการกับอินพุตที่ไม่ถูกต้อง คำสั่งควรใช้งานได้ไม่ว่าจะมีไดเรกทอรีที่ส่งผ่านอยู่จริงในเครื่องของคุณหรือไม่ คุณสามารถสันนิษฐานได้ว่าทุกอย่างเป็นไดเรกทอรีแม้ว่าจะมีนามสกุลก็ตาม

กรณีทดสอบ

Absolute      New          Output
"/a/b/c"      "d"       -> "/a/b/c/d" 
"/a/b/c/"     "d"       -> "/a/b/c/d"
"/a/b/c/"     "d/"      -> "/a/b/c/d"
"/a/b/c"      "/d"      -> "/d"
"/a/b/c"      "/d/"     -> "/d"
"/../a/b/c/"  "d"       -> "/a/b/c/d"
"/a/../b/c/"  "d"       -> "/b/c/d"
"/a/b/../c"   "d"       -> "/a/c/d"
"/a/b/c/.."   "d"       -> "/a/b/d"
"/a/b/c/"     ".."      -> "/a/b"
"/a/b/c"      "../d"    -> "/a/b/d"
"/a/b/c"      "/../d"   -> "/d"
"/a/b/c"      ""        -> "/a/b/c"
"/a/b/c"      "."       -> "/a/b/c"
"/a/b/c"      "./d"     -> "/a/b/c/d"
"/a/b/c"      "/./d"    -> "/d"
"/a/b/c"      "d.txt"   -> "/a/b/c/d.txt"
"/a/b/c"      "d."      -> "/a/b/c/d."
"/a/b/c"      ".txt"    -> "/a/b/c/.txt"
"/a/b/c"      ".txt/d"  -> "/a/b/c/.txt/d"
"/a/b/."      "./././." -> "/a/b"
"/direc"      "tory"    -> "/direc/tory"
"/a-_.b/"     "__._-."  -> "/a-_.b/__._-."
"/a/b"        "../.."   -> "/"
"/a/b"        "../../.."-> "/"
"/a"          "../../.."-> "/"
"/"           ""        -> "/"
"/"           "a"       -> "/a"
"/.."         "a"       -> "/a"
"/."          ""        -> "/"

นี่คือเพื่อให้การส่งของคุณสั้นที่สุดในภาษาที่คุณชื่นชอบ!


คำตอบบางอย่างดูเหมือนว่าไฟล์ (หรือ symlink) ที่มีชื่อเดียวกันกับส่วนใดส่วนหนึ่งของแผนผังไดเรกทอรี) ไม่มีอยู่ในเครื่อง อนุญาตหรือไม่
Dennis

เราสามารถรับอินพุตทั้งสองตามลำดับที่เราต้องการได้หรือไม่?
Downgoat

คำถามงี่เง่า ... ฉันสามารถมีผลข้างเคียงได้หรือไม่ โดยเฉพาะผลข้างเคียงเช่น um, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(หรืออะไร)?
แมว

@dennis ผลลัพธ์ของโปรแกรมควรเป็นอิสระจากระบบไฟล์
Nathan Merrill

@downgoat ไม่เป็นไร
Nathan Merrill

คำตอบ:


7

เรติน่า 44 ไบต์

+`.+ /| |/\.?/
/
+1`/?[^/]*/\.\.|/\.?$

^$
/

อินพุตคาดว่าเป็นสองพา ธ ที่คั่นด้วยช่องว่างเดียว

ลองออนไลน์! (บรรทัดแรกเปิดใช้งานชุดทดสอบที่แยกบรรทัดด้วยฟีด)



3

รุ่น, 282 281 279 276 ไบต์

@echo off
set a=\
set r=%~2
if "%r%"=="" set r=%~1
if not %r:~,1%==/ set r=%~1/%~2
for %%a in (%r:/= %)do call:x %%a
if not %a%==\ set a=%a:~,-1%
echo %a:\=/%
exit/b
:x
if %1==. exit/b
if not %1==.. set a=%a%%1\&exit/b
if not %a%==\ for %%a in (%a:~,-1%)do set a=%%~pa

การแสดงออกแบบกลุ่มที่น่ารำคาญโดยทั่วไปไม่ชอบตัวแปรที่ว่างเปล่า แก้ไข: บันทึก 1 ไบต์ขอบคุณ @ CᴏɴᴏʀO'Bʀɪᴇɴและ 2 ไบต์ขอบคุณ @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (และอีกหลายไบต์ในคำตอบอื่น ๆ เช่นกันแม้ว่าจะไม่ได้รับการรับรอง)


ฉันคิดว่าคุณสามารถลบช่องว่างระหว่างcallและ: x`, no?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴห่าคุณก็ทำได้ ฉันได้รับคำตอบจำนวนมากที่จำเป็นต้องอัปเดตในกรณีนี้ ...
Neil

2

Python 2, 265 260 254 ไบต์

y=lambda:[x for x in raw_input().split("/")if x!=""and x!="."]
a=y();n=y();m=len(a)-1
while m>0:
 if a[m]==".."and m>0:del a[m];del a[m-1];m-=1
 elif a[m]=="..":del a[m]
 m-=1
for i in n:
 if i==".."and len(a)>0:del a[-1]
 else:a+=i,
print"/"+"/".join(a)

1

Python, 142 137 ไบต์

def p(a,n,r=[],S="/"):
 for s in[s for s in((n[:1]!=S)*a+S+n).split(S)if"."!=s and s]:e=s!="..";r=[s]*e+r[1-e:]
 return S+S.join(r[::-1])

1

Bash, 41 ไบต์

สคริปต์ทุบตีนี้มีผลข้างเคียงของการสร้างไดเรกทอรีหากไม่มีอยู่ แต่ควรเป็นไปตามข้อกำหนด ขอบคุณKarlและNeilสำหรับการปรับปรุงของคุณ

mkdir -p $1;cd $1;mkdir -p $2;cd "$2";pwd

การใช้งาน: ทุบตี getpath.sh "สัมบูรณ์" "ใหม่"

หากคุณไม่ชอบ stderr เมื่ออาร์กิวเมนต์ที่สองเป็นสตริงว่างคุณสามารถทดสอบได้ดังนี้ (48 ไบต์):

mkdir -p $1;cd $1;[ $2 ]&&mkdir -p $2&&cd $2;pwd

ความพยายาม 30 ไบต์ก่อนหน้า (ต้องมีไดเรกทอรีอยู่): cd $ 1; [$ 2] && cd $ 2; echopwd


คำถามบอกว่าคำสั่งควรใช้งานได้จริงหรือไม่ว่ามีไดเรกทอรีที่ส่งผ่านอยู่จริงในเครื่องของคุณหรือไม่
Dennis

อ่าฉันเข้าใจแล้ว เลวร้ายเกินไป.
Bryn

สวัสดีและยินดีต้อนรับสู่ PPCG! โดยปกติหากคำตอบของคุณไม่ได้ผลคุณจะต้องลบทิ้ง คุณสามารถคลิกที่ลิงค์ลบด้านบนความคิดเห็นนี้
NoOne อยู่ที่นี่

คุณสามารถmkdir -pตรวจสอบให้แน่ใจว่าพวกเขามีอยู่จริง
Karl Napf

ขอบคุณฉันกำลังลองรุ่นกับ mkdir ฉันจะลบคำตอบนี้และเพิ่มคำตอบใหม่ถ้าฉันเข้าใจ
Bryn

1

C #, 43 ไบต์

(x,y)=>Path.GetFullPath(Path.Combine(x,y));

บันทึกแล้ว 1 ไบต์ขอบคุณ @aloisdg

Path.Combineทำให้ข้อโต้แย้งเข้าด้วยกันและPath.GetFullPathแก้ไข..\s


สวัสดีและยินดีต้อนรับสู่ PPCG! นี่ไม่ใช่โปรแกรมที่ถูกต้อง - รวมถึงmainและคลาสหรือเปลี่ยนเป็น lanbda: a,b->...
NoOneIsHere

ฉันกำลังจะโพสต์ :) การส่งครั้งแรกที่ดี! คุณสามารถลบช่องว่างหลังจาก,: (x, y)=>(x,y)
aloisdg พูดว่า Reinstate Monica



1

Javascript, 210 ไบต์

function p(a,b){d='.';e=d+d;s='/';t='split';u='splice';r=(b[0]===s?[]:a[t](s)).concat(b[t](s));for(i=0;i<r.length;r[i]===e&&r[u](i?i-1:i,i?2:1)?(i&&i--):i++)(!r[i]||r[i]===d)&&r[u](i,1)&&i--;return s+r.join(s)}

นี่คือชุดทดสอบ

ด้วย linebreaks แทนอัฒภาค:

function p(a,b) {
    d='.'
    e=d+d
    s='/'
    t='split'
    u='splice'

    r=(b[0]===s?[]:a[t](s)).concat(b[t](s))

    for(i=0;i<r.length;r[i]===e&&r[u](i?i-1:i,i?2:1)?(i&&i--):i++)
        (!r[i]||r[i]===d)&&r[u](i,1)&&i--

    return s+r.join(s)
}

0

Java 7, 83 ไบต์

String p(String a,String b){return Paths.get(a).resolve(b).normalize().toString();}

normalizeจำเป็นต้องจัดการกับการอ้างอิงแบบสัมพัทธ์ addถูกใช้เพื่อจัดการเส้นทางที่สองที่เริ่มต้นด้วย/ซึ่งPaths.get(a, b)จะไม่จัดการตามที่ระบุ


สวัสดีและยินดีต้อนรับสู่ PPCG! นี่เป็นโพสต์แรกที่ดี!
NoOne อยู่ที่นี่

0

Bash, 38 ไบต์

[[ $2 = /* ]]||p=$1
realpath -sm $p/$2

ไม่จำเป็นต้องมีสิทธิ์ใช้งานรูทและไม่มีข้อสันนิษฐานเกี่ยวกับไฟล์ไดเรกทอรีหรือลิงก์สัญลักษณ์ที่มีอยู่หรือไม่มีอยู่

ทดสอบบนIdeone Ideone

มันทำงานอย่างไร

[[ $2 = /* ]] ทดสอบว่าอาร์กิวเมนต์บรรทัดคำสั่งที่สองเริ่มต้นด้วย /ทดสอบถ้าอาร์กิวเมนต์ที่สองบรรทัดคำสั่งเริ่มต้นด้วย

หากไม่เป็นเช่นนั้นพา ธ จะสัมพันธ์กันและp=$1ตั้งค่าตัวแปรpเป็นอาร์กิวเมนต์บรรทัดคำสั่งแรก

วิธีนี้$p/$2คือ/$2ถ้า$2เป็นเส้นทางที่แน่นอนและ$1/$2ถ้ามันเป็นเส้นทางที่แท้จริง

สุดท้ายพิมพ์เส้นทางแน่นอนเป็นที่ยอมรับของrealpath -sm $p/$2 สวิทช์ทำให้realpathละเว้นการเชื่อมโยงสัญลักษณ์และชิ้นส่วนสวิทช์ที่ขาดหายไป$p/$2-s-m


0

ทับทิมขนาด 16 ไบต์

เนื่องจากเห็นได้ชัดว่าใช้วิธีการจากไลบรารีมาตรฐานที่ได้รับอนุญาต:

File.expand_path

ดูชุดทดสอบบน repl.it


ไม่อนุญาตให้ป้อนข้อมูลผ่านตัวแปร แต่การส่งฟังก์ชันเป็นซึ่งหมายความว่าคุณควรย่อให้เหลือFile.expand_path:)
Nathan Merrill

ฉันขอแนะนำให้ทดสอบกับชุดทดสอบเพื่อให้แน่ใจว่าทำงานได้อย่างถูกต้องในทุกกรณีทดสอบ
Nathan Merrill

@NathanMerrill ฉันทำ แต่ฉันจะไปต่อ
Jordan

แก้ไขเพื่อรวมลิงก์ชุดการทดสอบ
Jordan

0

รุ่น GNU , 81 59 + 1 = 60 ไบต์

+1 ไบต์สำหรับการ-rตั้งค่าสถานะ คาดว่าอินพุตของ STDIN จะถูกคั่นด้วยช่องว่างเดียว

s:.+ /::
s:/? :/:
:
s:/$|[^/]+/+\.\.|\.(/|$):\1:
t
s:^/*:/:

ลองออนไลน์!

คำอธิบาย

s:.+ /::  # If the second argument starts with a slash, drop the first argument
s:/? :/:  # Join the first and second arguments with a slash, dropping duplicate slashes
:
  s:/$|[^/]+/+\.\.|\.(/|$):\1:  # Drop trailing slashes, resolve double and single dots
  t                             # If the above substitution was made, branch to :
s:^/*:/:  # Ensure output begins with a single slash

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