Code Golf: Arbre de répertoire -> Arbre

11

Concours (!): Dans la langue de votre choix, écrivez un programme qui traversera l'arborescence d'un répertoire donné et produira une arborescence (c'est-à-dire un tableau de tableaux) qui lui correspond. Supposons que le répertoire soit une variable prédéfinie D. Le plus petit nombre de caractères gagne.

Règles:

  • Vous devez utiliser la récursivité
  • Voir les règles

Remarque: Supposons qu'il n'y a pas de limites de profondeur de récursivité. En d'autres termes, votre code doit simplement fonctionner pour des arborescences de répertoires suffisamment petites, et en principe pour les plus grandes.

Par exemple:

L'arborescence des répertoires est

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

L'arbre de sortie est

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

Commencez par jouer au golf ici afin que je sache si je fais quelque chose de mal.

S'amuser :)

Andrew Odesky
la source
7
"Règles: 1. Vous devez utiliser la récursivité 2. Voir les règles" Ah !! AIDEZ-MOI À JOUER DANS UNE BOUCLE INFINIE!
Justin
1
Vous pouvez utiliser le nombre de caractères ou la plus petite taille en octets (de cette façon, les programmes avec des caractères Unicode sont plus grands que s'ils utilisaient de l'ascii pur)
Justin
1
Quelle profondeur traverserait-il?
It'sNotALie.
Beaucoup de gens apprécieraient que vous donniez à la place une entrée de fichier (comme chemin d'accès ou autre) et qu'ils puissent simplement le sortir. De plus, votre sortie semble un peu difficile à comprendre. Pouvez-vous fournir un cas de test? Plutôt que d'utiliser un tableau de tableaux, pourrions-nous simplement imprimer chaque répertoire / fichier sur sa propre ligne, mais en retrait pour montrer le sous-dossier? Fondamentalement, devons-nous produire dans un certain format (auquel cas, donner un exemple), ou pouvons-nous choisir un format (tant qu'il n'est pas ambigu)?
Justin
3
Je deviens aveugle, analysant votre format de sortie. Ceci, de la part de quelqu'un qui aime Lisp.
Darren Stone

Réponses:

6

Mathematica 120 21 20

entrez la description de l'image ici

Récursivité explicite (merci alephalpha d'avoir enregistré un caractère):

f=f/@__~FileNames~#&

f["~/StackExchange/dir1"]

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

TreeForm[%]

entrez la description de l'image ici

Solution précédente trop compliquée:

d="~/StackExchange/dir1"

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

Rubis, 38 caractères

Si cela ne vous dérange pas certains espaces supplémentaires dans la sortie:

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

Exemple d'utilisation:

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

Production:

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

Si je ne peux pas avoir d'espace, quelque chose comme ça pour la deuxième ligne:

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

Python 2.7, 111 caractères

Prend le chemin cible depuis 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())
Bob
la source
2

Powershell - 182 car.

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)

Assez simple. Peut être réduit de 10 caractères si les virgules n'étaient pas nécessaires. Prend l'entrée de $ D (comme indiqué dans la question), retourne la sortie sur STD-Out comme l'exemple de la question est allé.

Souhaitant vraiment que les alias puissent utiliser des options! Je suis tué par le 'write-host -NoNewline's!

lochok
la source
Je pense que cela pourrait être fait un peu mieux. Un golfeur plus expérimenté veut lui donner une fissure?
lochok
Je ne sais pas si vous avez réellement atteint la cible que le défi vise ... mais ce n'est pas grave car tous ceux qui ont répondu semblent avoir choisi leur propre interprétation.
HRRambler
{doh! Appuyez sur Entrée par accident. } Cela étant dit, je ne vais pas toucher à votre interprétation pour chaque {}, je vais simplement signaler une amélioration que vous pouvez apporter. La première astuce PowerShell que vous manquez est que l'écriture d'hôte n'est pas nécessaire, si vous terminez votre code avec des données dans le pipeline, il est écrit sur l'hôte. La deuxième astuce est l'expansion et la concaténation automagiques qui se produisent entre guillemets doubles. Enfin, utilisez get-alias pour identifier les astuces comme% = foreach. La prochaine fois, utilisez une stratégie qui encapsule vos résultats dans une variable puis termine en appelant cette variable: $ a = gi $ d | ls | % {}; "[$ a]"
HRRambler
1

Caractères C # 200

Sortie d'une chaîne, pas d'un tableau réel. Prend un chemin comme premier argument.

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

Non 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])));
    }
}
Bob
la source
Ma première tentative de golf, et C # est un langage assez verbeux. Tout avis sera le bienvenu.
Bob
0

C ++, 318 octets

#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());}

Voici une version légèrement non golfée:

#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());
}

Veuillez noter que puisque - selon les instructions - D est supposé être une variable prédéfinie, le code ne se construit pas sans fournir en quelque sorte D. Voici une façon de construire:

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

Script batch - 146, 157, 152 127 octets

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%

Courir avec:

scriptfile.cmd folderroot
Robert Sørlie
la source
La sortie augmente à chaque exécution de ce script.
unclemeat
1
Oui, ce n'était pas très convivial pour la session, mais ça devrait être mieux maintenant
Robert Sørlie