Calcolo della directory


19

Per questa sfida, ti verrà assegnato un percorso assoluto e un "nuovo" percorso (che può essere assoluto o relativo) e dovrai restituire il percorso finale.

Ad esempio, se la directory corrente era /var/tmp/test:

my_diro my_dir/ dovrebbe tornare/var/tmp/test/my_dir

../../my_dir dovrebbe tornare /var/my_dir

/my_dir/./ dovrebbe tornare /my_dir

../../../../../ dovrebbe tornare /

Per essere più pedanti:

  • Una directory è una stringa non vuota costituite da caratteri alfanumerici e simboli -, _o.
  • Un percorso è un elenco di 0 o più directory , separate usando /. Un percorso assoluto inizia con a /, un percorso relativo no. I percorsi possono includere un finale /.

Devi "risolvere" il secondo percorso, dato il primo percorso.

Il processo di risoluzione è:

  1. Verifica se il secondo percorso è relativo. In tal caso, inserire le directory del percorso assoluto all'inizio del secondo percorso.
  2. Se è presente una delle directory .., rimuoverla e la directory precedente. Se è la prima directory, rimuovila semplicemente.
  3. Se è presente una delle directory ., rimuoverla.
  4. Emette il percorso assoluto finale. Non dovresti generare un finale /.

Non è necessario gestire input errati. I comandi dovrebbero funzionare, indipendentemente dal fatto che le directory passate esistano o meno sul tuo computer. Puoi presumere che tutto sia una directory, anche se ha un'estensione.

Casi test

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

Questo è un , quindi rendi i tuoi invii il più brevi possibile nella tua lingua preferita!


Alcune risposte sembrano supporre che file (o collegamenti simbolici) con lo stesso nome di qualsiasi parte dell'albero della directory) non esistano sulla macchina. È permesso?
Dennis,

Possiamo prendere i due ingressi nell'ordine che desideriamo?
Downgoat,

Domanda stupida ... posso avere effetti collaterali? In particolare, effetti collaterali come, um, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(o qualcosa del genere)?
gatto,

@dennis. L'output dei programmi dovrebbe essere indipendente dal file system
Nathan Merrill il

@downgoat va bene
Nathan Merrill il

Risposte:


7

Retina , 44 byte

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

^$
/

Si prevede che l'input sia i due percorsi separati da un singolo spazio.

Provalo online! (La prima riga abilita una suite di test separata da avanzamento riga.)


3

Python, 53 byte

from os.path import*;p=lambda a,n:normpath(join(a,n))

3

Lotto, 282 281 279 276 byte

@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

Le espressioni batch in modo fastidioso generalmente non amano le variabili vuote. Modifica: salvato 1 byte grazie a @ CᴏɴᴏʀO'Bʀɪᴇɴ e 2 byte grazie a @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (e anche un sacco di byte su altre risposte, anche se purtroppo non accreditato).


Penso che puoi rimuovere uno spazio tra calle: x`, no?
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, così puoi. Ho un sacco di risposte che devono essere aggiornate in quel caso ...
Neil,

2

Python 2, 265 260 254 byte

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 byte

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 byte

Questo script bash ha l'effetto collaterale di creare directory se non esistono, ma dovrebbe soddisfare i requisiti. Grazie Karl e Neil per i tuoi miglioramenti.

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

Utilizzo: bash getpath.sh "assoluto" "nuovo"

Se non ti piace lo stderr quando il secondo argomento è una stringa vuota, puoi provarlo come segue (48 byte):

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

Tentativo precedente di 30 byte (richiede l'esistenza di directory): cd $ 1; [$ 2] && cd $ 2; echopwd


La domanda dice che i comandi dovrebbero funzionare, indipendentemente dal fatto che le directory passate esistano o meno sul tuo computer.
Dennis,

Ah, capisco. Peccato.
Bryn,

Ciao e benvenuto in PPCG! Normalmente, se la tua risposta non funziona, la elimini. È possibile fare clic sul collegamento Elimina sopra questo commento.
NoOneIsHere

Potresti mkdir -passicurarti che esistano.
Karl Napf,

Grazie, sto provando una versione con mkdir. Eliminerò questa risposta e ne aggiungerò una nuova se lo capisco.
Bryn,

1

C #, 43 byte

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

Salvato 1 byte grazie a @aloisdg

Path.Combinemette insieme gli argomenti e Path.GetFullPathrisolve la ..\s


Ciao e benvenuto in PPCG! Questo non è un programma valido - includi maine una classe, o cambialo in una lanbda: a,b->...
NoOneIsHere

Stavo per pubblicarlo :) Bella prima presentazione! puoi rimuovere lo spazio dopo ,: (x, y)=>(x,y)
aloisdg dice Reinstate Monica il



1

Javascript, 210 byte

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

Ecco la suite di test

Con interruzioni di riga anziché punti e virgola:

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 byte

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

normalizeè necessario per trattare i riferimenti relativi. addviene utilizzato per gestire il secondo percorso che inizia con /, che Paths.get(a, b)non gestirà come specificato.


Ciao e benvenuto in PPCG! Questo è un buon primo post!
NoOneIsHere

0

Bash, 38 byte

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

Non richiede i privilegi di root e non fa ipotesi su file, directory o collegamenti simbolici esistenti o non esistenti.

Provalo su Ideone .

Come funziona

[[ $2 = /* ]]verifica se il secondo argomento della riga di comando inizia con /.

In caso contrario, il percorso è relativo e p=$1imposta la variabile p sul primo argomento della riga di comando.

In questo modo $p/$2è /$2se $2è un percorso assoluto e $1/$2se è un percorso realistico.

Infine, realpath -sm $p/$2stampa il percorso assoluto canonico di $p/$2. Lo -sswitch fa in modo che realpath ignori i collegamenti simbolici e lo -mswitch manchi i componenti.


0

Rubino, 16 byte

Dal momento che apparentemente è consentito l' uso di un metodo dalla libreria standard :

File.expand_path

Vedere la suite di test su repl.it .


L'input tramite variabili non è consentito, ma l'invio di funzioni lo è, il che significa che è necessario accorciarlo a File.expand_path:)
Nathan Merrill,

Raccomando anche di testarlo effettivamente sulla suite di test per assicurarsi che funzioni correttamente su tutti i casi di test.
Nathan Merrill,

@NathanMerrill l'ho fatto, ma andrò avanti e attaccerò qualcosa su repl.it.
Giordania,

Modificato per includere il collegamento della suite di test.
Giordania,

0

GNU sed , 81 59 + 1 = 60 byte

+1 byte per -rflag. Prevede input su STDIN separati da un singolo spazio.

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

Provalo online!

Spiegazione

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

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.