Code Golf: Árbol de directorios -> Árbol

11

Concurso (!): En el idioma que elija, escriba un programa que atraviese el árbol de directorios de un directorio determinado y genere un árbol (es decir, una matriz de matrices) correspondiente a él. Suponga que el directorio es una variable predefinida D. El recuento de caracteres más pequeño gana.

Reglas:

  • Debes usar la recursividad
  • Ver reglas

Nota: Suponga que no hay límites de profundidad de recursión. En otras palabras, su código solo necesita trabajar para árboles de directorio suficientemente pequeños, y en principio para los más grandes.

Por ejemplo:

El árbol de directorios es

dir1
├── dir11
│   ├── file111
│   └── file112
├── dir12
│   ├── file121
│   ├── file122
│   └── file123
├── file11
├── file12
└── file13

El árbol de salida es

[[[],[]],[[],[],[]],[],[],[]]

Primer código de golf aquí, así que déjame saber si estoy haciendo algo mal.

Que te diviertas :)

Andrew Odesky
fuente
77
"Reglas: 1. Debes usar la recursividad 2. Ver reglas" ¡Ah! ¡AYUDA A QUE ME PEGUE EN UN LAZO INFINITO!
Justin
1
Podría ir por el recuento de caracteres, o podría ir por el tamaño más pequeño en bytes (de esta manera, los programas con caracteres unicode son más grandes que si usaran ascii puro)
Justin
1
¿Qué tan profundo atravesaría?
Notalie.
Mucha gente lo agradecería si en su lugar proporcionara una entrada de un archivo (como una ruta u otra cosa) y simplemente pudiera generarlo. Además, su salida parece un poco difícil de entender. ¿Puedes proporcionar un caso de prueba? En lugar de usar una matriz de matrices, ¿podríamos simplemente imprimir cada directorio / archivo en su propia línea, pero con sangría para mostrar la subcarpeta? Básicamente, ¿debemos generar un formato determinado (en cuyo caso, dar un ejemplo), o podemos elegir un formato (siempre que no sea ambiguo)?
Justin
3
Me estoy quedando ciego, analizando su formato de salida. Esto, de alguien que disfruta de Lisp.
Darren Stone

Respuestas:

6

Mathematica 120 21 20

ingrese la descripción de la imagen aquí

Recurrencia explícita (gracias alephalpha por guardar un personaje):

f=f/@__~FileNames~#&

f["~/StackExchange/dir1"]

{{{}, {}}, {{}, {}, {}}, {}, {}, {}}

TreeForm[%]

ingrese la descripción de la imagen aquí

Solución sobrecomplicada anterior:

d="~/StackExchange/dir1"

f@{x___,Longest@s:{y_,___}..,z___}:=f@{x,f@Drop[{s},1,1],z}
f[FileNameSplit/@FileNames[__,SetDirectory@d;"",∞]]/.f->(#&)
ybeltukov
fuente
f=f/@__~FileNames~#&
alephalpha
2

Ruby, 38 caracteres

Si no le importa un espacio en blanco adicional en la salida:

f=->n{Dir[n+'/*'].map{|c|f[c]}}
p f[D]

Ejemplo de uso:

D='C:/work/dir1'
f=->n{Dir[n+'/*'].map{|c|f[c]}}
p f[D]

Salida:

[[[], []], [[], [], []], [], [], []]

Si no puedo tener el espacio en blanco, algo así para la segunda línea:

puts"#{f[D]}".tr' ',''
Paul Prestidge
fuente
2

Python 2.7, 111 caracteres

Toma la ruta de destino desde stdin.

import os
def R(d):return[R(f)for f in[d+'/'+e for e in os.listdir(d)]if os.path.isdir(f)]
print R(raw_input())
Beto
fuente
2

Powershell - 182 Char

function A([string]$b){write-host -NoNewline '['; ls -path $b|foreach{if($_.PSIsContainer){A($_.FullName)}ELSE{write-host -NoNewline $f'[]';$f=', '}};write-host -NoNewline ']'};A($D)

Bastante simple. Podría reducirse en 10 caracteres si las comas no fueran necesarias. Toma la entrada de $ D (como se indicó en la pregunta), devuelve la salida en STD-Out como fue el ejemplo en la pregunta.

Realmente deseando alias podrían usar opciones! ¡Estoy siendo asesinado por 'write-host -NoNewline's!

lochok
fuente
Creo que podría hacerse un poco mejor. ¿Un golfista más experimentado quiere darle una oportunidad?
lochok
No sé si realmente has alcanzado el objetivo al que apunta el desafío ... pero eso no es gran cosa ya que todos los que respondieron parecen haber elegido su propia interpretación.
HRRambler
{doh! Presiona entrar por accidente. } Dicho esto, no voy a tocar tu interpretación foreach {}, solo voy a señalar una mejora que puedes hacer. El primer truco de PowerShell que te estás perdiendo es que escribir host no es necesario, si terminas tu código con datos en la tubería que está escrito en el host. El segundo truco es la expansión y concatenación automática que ocurre entre comillas dobles. Finalmente use get-alias para identificar trucos como% = foreach. La próxima vez use una estrategia que encierre sus resultados dentro de una variable y luego termine llamando a esa variable: $ a = gi $ d | ls | % {}; "[$ a]"
HRRambler
1

C # 200 caracteres

Salida de una cadena, no una matriz real. Toma un camino como primer argumento.

using D=System.IO.DirectoryInfo;class P{static string R(D d){var r="[";foreach(D e in d.GetDirectories())r+=R(e);return r+"]";}static void Main(string[] a) {System.Console.WriteLine(R(new D(a[0])));}}

Sin golf:

using D = System.IO.DirectoryInfo;

class P
{
    static string R(D d)
    {
        var r = "[";
        foreach (D e in d.GetDirectories())
            r += R(e);
        return r + "]";
    }

    static void Main(string[] a)
    {
        System.Console.WriteLine(R(new D(a[0])));
    }
}
Beto
fuente
Mi primer intento de golf, y C # es un lenguaje bastante detallado. Cualquier consejo sería apreciado.
Bob
0

C ++, 318 bytes

#include <cstdio>
#include <dirent.h>
#include <string>
#define s std::string
#define n e->d_name
s l(s p){s r;dirent*e;DIR*d;if(d=opendir(p.c_str())){int c=0;while(e=readdir(d))if(s("..")!=n&s(".")!=n)r+=&",["[!c++]+(e->d_type==DT_DIR?l(p+'/'+n):"")+"]";closedir(d);}return r;}main(){puts((s("[")+l(D)+"]").c_str());}

Aquí hay una versión ungolfed:

#include <cstdio>
#include <dirent.h>
#include <string>

#define s std::string
#define n e->d_name

s l(s p) {
    s r;
    dirent*e;
    DIR*d;
    if (d=opendir(p.c_str())) {
        int c=0;
        while (e=readdir(d))
            if (s("..")!=n&s(".")!=n)
                r+=&",["[!c++]+(e->d_type==DT_DIR?l(p+'/'+n):"")+"]";
        closedir(d);
    }
    return r;
}

main() {
    puts((s("[")+l(D)+"]").c_str());
}

Tenga en cuenta que, dado que, según las instrucciones, se supone que D es una variable predefinida, el código no se genera sin proporcionar de alguna manera D. Aquí hay una forma de generar:

g++ -Dmain="s D=\".\";main" -o tree golfed.cpp
treamur
fuente
0

Script por lotes: 146, 157, 152, 127 bytes

set x=
:a
set x=%x%,[
cd %1
goto %errorlevel%
:0
for /f %%a in ('dir/b') do call:a %%a
cd..
:1
set x=%x:[,=[%]
cls
@echo %x:~1%

Corre con:

scriptfile.cmd folderroot
Robert Sørlie
fuente
La salida se hace más grande en cada ejecución de este script.
Unclemeat
1
Sí, no fue muy amigable para la sesión, pero debería ser mejor ahora
Robert Sørlie