Obliczanie katalogu

19

Za to wyzwanie otrzymasz ścieżkę bezwzględną i „nową” ścieżkę (która może być absolutna lub względna) i musisz zwrócić ostatnią ścieżkę.

Na przykład jeśli bieżący katalog to /var/tmp/test:

my_dirlub my_dir/ powinien wrócić/var/tmp/test/my_dir

../../my_dir powinien wrócić /var/my_dir

/my_dir/./ powinien wrócić /my_dir

../../../../../ powinien wrócić /

Aby być bardziej pedantycznym:

  • Katalog jest niepusty łańcuch składający się ze znaków alfanumerycznych i symboli -, _lub.
  • Ścieżka to lista 0 lub więcej katalogów oddzielonych za pomocą /. Ścieżka bezwzględna zaczyna się od /, ścieżka względna nie. Ścieżki mogą zawierać zakończenie /.

Musisz „rozwiązać” drugą ścieżkę, biorąc pod uwagę pierwszą ścieżkę.

Proces rozstrzygania jest:

  1. Sprawdź, czy druga ścieżka jest względna. Jeśli tak, wstaw katalogi ścieżki bezwzględnej na początek drugiej ścieżki.
  2. Jeśli którykolwiek z katalogów jest .., usuń go i poprzedni katalog. Jeśli jest to pierwszy katalog, po prostu go usuń.
  3. Jeśli którykolwiek z katalogów jest ., usuń go.
  4. Wyjście końcowej ścieżki bezwzględnej. Nie powinieneś wypisywać zakończenia /.

Nie musisz obsługiwać nieprawidłowych danych wejściowych. Polecenia powinny działać, niezależnie od tego, czy przekazane katalogi faktycznie istnieją na twoim komputerze. Możesz założyć, że wszystko jest katalogiem, nawet jeśli ma rozszerzenie.

Przypadki testowe

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"
"/."          ""        -> "/"

To jest , dlatego , aby Twoje zgłoszenia były jak najkrótsze w swoim ulubionym języku!

Nathan Merrill
źródło
Niektóre odpowiedzi wydają się zakładać, że pliki (lub dowiązania symboliczne) o tej samej nazwie co dowolna część drzewa katalogów) nie istnieją na komputerze. Czy to jest dozwolone?
Dennis
Czy możemy przyjąć dwa dane wejściowe w dowolnej kolejności?
Downgoat
Głupie pytanie ... czy mogę mieć skutki uboczne? W szczególności efekty uboczne, takie jak, um mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(lub coś w tym rodzaju)?
kot
@dennis. Dane wyjściowe programów powinny być niezależne od systemu plików
Nathan Merrill
@ downgoat to w porządku
Nathan Merrill

Odpowiedzi:

7

Siatkówka , 44 bajty

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

^$
/

Dane wejściowe powinny być dwiema ścieżkami oddzielonymi pojedynczą spacją.

Wypróbuj online! (Pierwszy wiersz włącza pakiet testowy oddzielony od linii).

Martin Ender
źródło
3

Python, 53 bajty

from os.path import*;p=lambda a,n:normpath(join(a,n))
orlp
źródło
3

Partia, 282 281 279 276 bajtów

@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

Irytujące wyrażenia wsadowe na ogół nie lubią pustych zmiennych. Edycja: Zapisano 1 bajt dzięki @ CᴏɴᴏʀO'Bʀɪᴇɴ i 2 bajty dzięki @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (i kilka bajtów także na inne odpowiedzi, choć niestety niewymienione w czołówce).

Neil
źródło
Myślę, że możesz usunąć spację między calli: x`, nie?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, więc możesz. Mam mnóstwo odpowiedzi, które wymagają aktualizacji w tym przypadku ...
Neil
2

Python 2, 265 260 254 bajtów

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)
acrolith
źródło
1

Python, 142 137 bajtów

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])
orlp
źródło
1

Bash, 41 bajtów

Ten skrypt bash ma efekt uboczny tworzenia katalogów, jeśli nie istnieją, ale powinien spełniać wymagania. Dzięki Karl i Neil za twoje ulepszenia.

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

Zastosowanie: bash getpath.sh „absolutny” „nowy”

Jeśli nie podoba ci się stderr, gdy drugi argument jest pustym łańcuchem, możesz go przetestować w następujący sposób (48 bajtów):

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

Poprzednia 30-bajtowa próba (wymaga istnienia katalogów): cd $ 1; [$ 2] && cd $ 2; echopwd

Bryn
źródło
Pytanie brzmi : Polecenia powinny działać, niezależnie od tego, czy przekazane katalogi faktycznie istnieją na twoim komputerze.
Dennis
O, rozumiem. Szkoda
Bryn
Witaj i witaj w PPCG! Zwykle, jeśli twoja odpowiedź nie działa, usuwasz ją. Możesz kliknąć link usuwania powyżej tego komentarza.
NoOneIsHere
Możesz mkdir -pupewnić się, że one istnieją.
Karl Napf,
Dzięki, próbuję wersji z mkdir. Usunę tę odpowiedź i dodam nową, jeśli się zorientuję.
Bryn
1

C #, 43 bajty

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

Zapisano 1 bajt dzięki @aloisdg

Path.Combinełączy argumenty i Path.GetFullPathrozwiązuje ..\s

jlynch630
źródło
Witaj i witaj w PPCG! To nie jest poprawny program - albo maindołącz i klasę, albo zmień go na lanbda: a,b->...
NoOneIsHere 16.07.16
Zamierzałem to opublikować :) Ładne pierwsze zgłoszenie! możesz usunąć spację po ,: (x, y)=>(x,y)
aloisdg mówi Przywróć Monikę
Interesują Cię również wskazówki C # do gry w golfa .
aloisdg mówi Przywróć Monikę
1

Węzeł REPL, 8 12 bajtów

path.resolve

Na szczęście nie musisz require()standardowych modułów w REPL.

Pakiet testowy

https://repl.it/Cclo/1

(Jeśli wyjście jest na końcu true, to pasuje)

Patrick Roberts
źródło
1

JavaScript, 210 bajtów

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)}

Oto pakiet testowy

Z podziałami linii zamiast średników:

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)
}
CShark
źródło
0

Java 7, 83 bajty

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

normalizejest potrzebny do radzenia sobie z referencjami względnymi. addsłuży do obsługi drugiej ścieżki zaczynającej się od /, która Paths.get(a, b)nie będzie obsługiwać zgodnie z opisem.

jaxad0127
źródło
Witaj i witaj w PPCG! To dobry pierwszy post!
NoOneIsHere
0

Bash, 38 bajtów

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

Nie wymaga uprawnień administratora i nie przyjmuje żadnych założeń dotyczących istniejących lub nieistniejących plików, katalogów lub dowiązań symbolicznych.

Przetestuj na Ideone .

Jak to działa

[[ $2 = /* ]]sprawdza, czy zaczyna się drugi argument wiersza polecenia /.

Jeśli nie, ścieżka jest względna i p=$1ustawia zmienną p na pierwszy argument wiersza poleceń.

Tak $p/$2jest, /$2jeśli $2jest to ścieżka bezwzględna i $1/$2jeśli jest to ścieżka realna.

Na koniec realpath -sm $p/$2drukuje kanoniczną ścieżkę bezwzględną $p/$2. Do -sprzełącznika marki realpath ignorować łączy symbolicznych, i -melementy przełączające brakuje.

Dennis
źródło
0

Rubinowy, 16 bajtów

Ponieważ najwyraźniej stosowanie metody ze standardowej biblioteki jest dozwolone:

File.expand_path

Patrz zestaw testowy na repl.it .

Jordania
źródło
Wprowadzanie za pomocą zmiennych jest niedozwolone, ale przesyłanie funkcji jest, co oznacza, że ​​należy je skrócić do File.expand_path:)
Nathan Merrill
Poleciłbym również przetestowanie go na zestawie testów, aby upewnić się, że działa poprawnie na wszystkich testach.
Nathan Merrill,
@NathanMerrill Zrobiłem, ale pójdę naprzód i nakleję coś na repl.it.
Jordan
Edytowane, aby zawierało link do zestawu testów.
Jordan
0

GNU sed , 81 59 + 1 = 60 bajtów

+1 bajt dla -rflagi. Oczekuje, że dane wejściowe na STDIN są oddzielone pojedynczą spacją.

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

Wypróbuj online!

Wyjaśnienie

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
Jordania
źródło
0

Zsh , 15 bajtów

a=$1/$2
<<<$a:a

:aModyfikator robi dokładnie to.

Wypróbuj online!

Funkcja Gamma
źródło