Um Programa Skittish


17

Objetivo

Você deve escrever um programa que receba um número inteiro ncomo entrada (da linha de comando) e incorpore os próprios ndiretórios (o programa) na árvore de diretórios. Exemplo com n=5:

Exemplo com n = 5

Os nomes das pastas podem ser o que você desejar. Os únicos requisitos são que a profundidade esteja correta e que o programa possa ser executado novamente a partir de seu novo local na árvore de diretórios, e que o novo arquivo de origem mantenha o mesmo nome de arquivo.

Bônus:

  • Pontuação * 0,9 Se todos os diretórios tiverem um nome diferente (deve ser verdadeiro pelo menos até 1 000 000 de profundidade)
  • Pontuação * 0.5 Se você não ler, direta ou indiretamente, mover o arquivo fonte, ou acessar o código fonte do programa

1
O que conta como " ler a fonte "? Você quer dizer o arquivo? Ou o código fonte real?
GiantTree

2
@unclemeat Sim, porque para mover o arquivo você (ou o sistema) precisa acessar os dados no arquivo.
globby

25
Parece que você está apenas tentando esconder seu estoque de pornografia.
ablue

3
@globby e o lncomando em * nix? Se não me engano, é apenas criar outra entrada para o inode do arquivo e nenhum conteúdo é lido.
HJK

7
@globby Tanto quanto sei, mover um arquivo não lê o conteúdo, a menos que você esteja movendo entre discos rígidos ou partições. É basicamente apenas mudar alguns ponteiros no sistema de arquivos.
Martin Ender

Respostas:


36

Bash, 30 * 0,9 * 0,5 = 13,5

mkdir -p `seq -s/ $1`;ln $0 $_

Toma profundidade como o primeiro argumento. Cria um link físico para ele mesmo na seguinte estrutura de diretórios:

1/2/3/4/5/.../n

O script pode ser executado a partir do novo local, mesmo se rmfor executado no script antigo.

Explicação:

seq -s/ $1gera os números de 1 a $1(o primeiro argumento), separados por uma barra.

mkdir -p `seq -s` $1cria o diretório especificado por seq, com a -pcriação de todos os diretórios intermediários.

ln $0 $_ crie um link físico para o script atual em execução no diretório recém-criado.

Antigo (30 * 0,9 = 27):

mkdir -p `seq -s/ $1`;cp $0 $_

Exemplo de execução (com ln):

$ ls -lGR
.:
total 1
-rwx------+ 1 ducks 41 Jan  5 15:00 test.sh

$ ./test.sh 4

$ ls -lgR
.:
total 1
drwxr-xr-x+ 1 ducks  0 Jan  5 15:01 1
-rwx------+ 2 ducks 41 Jan  5 15:00 test.sh

./1:
total 0
drwxr-xr-x+ 1 ducks 0 Jan  5 15:01 2

./1/2:
total 0
drwxr-xr-x+ 1 ducks 0 Jan  5 15:01 3

./1/2/3:
total 0
drwxr-xr-x+ 1 ducks 0 Jan  5 15:01 4

./1/2/3/4:
total 1
-rwx------+ 2 ducks 41 Jan  5 15:00 test.sh

$ rm ./test.sh

$ ls -lg
total 0
drwxr-xr-x+ 1 ducks 0 Jan  5 15:01 1

$ ls -lg 1/2/3/4
total 1
-rwx------+ 1 ducks 41 Jan  5 15:00 test.sh

Obrigado a @DigitalTrauma pela sugestão de substituição $(..)por`..`

Obrigado a @hjk pela sugestão de uso ln.


6
Uso brilhante de $_!
wchargin

2
Salve um caractere - use backticks em vez de $( ): codegolf.stackexchange.com/a/25572/11259
Digital Trauma

2
Dependendo da resposta ao meu comentário sobre a questão , talvez substituir cpcom lnpara obter o bônus de 0,5 também ...
HJK

2
Wells, agora há a atualização do OP e mvtambém está restrito a esse bônus de 0,5. Isso ainda deixa lnclaro, sim?
HJK

2
Sim, ln(você não precisa -s) colocaria o programa no novo diretório, para que ele possa ser executado a partir daí, sem nunca ler, mover ou acessar sua fonte original. Eu digo que vá para a pontuação FALCON PUNCH de 13,5!
Tobia

12

C, 225 * 0,9 * 0,5 = 101,25

Minha solução em C:

$ cat d.c
#define R(x)#x
#define T(x)R(x)
#define S(p)b[9];main(i,v)char**v;{for(i=atoi(v[1]);i--;sprintf(b,"%i",i),mkdir(b),chdir(b));fputs("#define R(x)#x\n#define T(x)R(x)\n#define S(p)"p"\nS(T(S(p)))",fopen("d.c","w"));}
S(T(S(p)))

Aqui de uma forma um pouco mais legível:

#define R(x) #x
#define T(x) R(x)
#define S(p) char b[9];\
             main(int i,char**v) { \
                for(i=atoi(v[1]); i--; sprintf(b,"%i",i), \
                                       mkdir(b), \
                                       chdir(b)); \
                fputs("#define R(x) #x\n" \
                      "#define T(x) R(x)\n" \
                      "#define S(p) " p "\n" \
                      "S(T(S(p)))", \
                      fopen("d.c", "w")); \
             }
S(T(S(p)))

A verificação se funciona:

$ gcc -o d d.c
# a lot of warning and notes from gcc ... 
$ ./d 10
$ diff -s d.c 9/8/7/6/5/4/3/2/1/0/d.c
Files d.c and 9/8/7/6/5/4/3/2/1/0/d.c are identical

Provavelmente existe muito potencial de golfe no código fonte.


Grande uso do pré-processador!
precisa saber é o seguinte

5

Lote - 48 * 0,9 = 43,2

for /l %%a in (1,1,%1)do md %%a&cd %%a&move..\%0

Este script simplesmente cria um novo diretório e move o arquivo de origem para ele - nvezes.

H:\MyDocuments\uprof\top>embed.bat 5

     ...

H:\MyDocuments\uprof\top>tree /f
Folder PATH listing for volume DATA009_HOMES
Volume serial number is B88B-384C
H:.
└───1
    └───2
        └───3
            └───4
                └───5
                        embed.bat

5

Zsh, 63 60 58 52 * 0,9 = 56,7 54 52,2 46,8

s=$(<$0);for i in {1..$1};{mkdir $i;cd $i};echo $s>f

Exemplo:

llama@llama:...Code/misc/foo$ zsh f 5
llama@llama:...Code/misc/foo$ ls -R
.:
d1  f

./d1:
d2

./d1/d2:
d3

./d1/d2/d3:
d4

./d1/d2/d3/d4:
d5

./d1/d2/d3/d4/d5:
f
llama@llama:...Code/misc/foo$ cat d1/d2/d3/d4/d5/f 
s=$(cat $0);for i in {1..$1};do;mkdir d$i;cd d$i;done;echo $s>f
llama@llama:...Code/misc/foo$ cat f
s=$(cat $0);for i in {1..$1};do;mkdir d$i;cd d$i;done;echo $s>f
llama@llama:...Code/misc/foo$ diff f d1/d2/d3/d4/d5/f
llama@llama:...Code/misc/foo$

UUOC s=$(<$0) (Apenas para constar, ele falha para mim com o bash4.3.11: “erro de sintaxe próximo ao token inesperado`; '”. Mas funciona bem com o zsh5.0.2)
manatwork

Você poderia salvar um personagem removendo o dantes $i?
Canadian Luke REINSTATE MONICA

@ CanadianLuke Huh, eu nunca soube que você poderia ter um diretório chamado 1. Obrigado
Doorknob

Eu acho que você deve ser capaz de usar chaves: for i in {1..$1};{mkdir $i;cd $i};echo $s>f.
Ry-

@ U2744SNOWFLAKE Obrigado, isso salvou alguns bytes. Editado.
Maçaneta

3

Rebol - 114 * 0,9 * 0,5 = 51,3

do b:[d: copy %./ repeat n do input[mkdir repend d[n"/"]]write join d s: system/options/script join"do b: "mold b]

Ungolfed:

do b: [
    d: copy %./
    repeat n do input [
        mkdir repend d [n "/"]
    ]
    write join d s: system/options/script join "do b: " mold b
]


Versão original não quine - 90 * 0.9 = 81

d: %./ repeat n do input[mkdir repend d[n"/"]write join d s: system/options/script read s]

Ungolfed:

d: %./
repeat n do input [
    mkdir repend d [n "/"]
]
write join d s: system/options/script read s

2

Bash 167 * 0,5 * 0,9 = 75,15

Tomando emprestado da ótima resposta de @ es1024 , mas essa é uma verdadeira solução, por isso se qualifica para os dois bônus.

b=\' c=\\ a='d=`seq -s/ $1`;mkdir -p $d;echo b=$c$b c=$c$c a=$b$a$b>>$d/$0;echo $a>>$d/$0'
d=`seq -s/ $1`;mkdir -p $d;echo b=$c$b c=$c$c a=$b$a$b>>$d/$0;echo $a>>$d/$0

Além disso, técnicas de shell quine a partir daqui .


1

AutoIt3, 106 * 0,9 = 95,4 bytes


Um pouco longo, mas não posso ajudar com esses nomes longos de função / variável:

$f = @WorkingDir
For $i = 1 To $CmdLine[1]
    $f &= "\" & $i
Next
DirCreate($f)
FileCopy(@ScriptFullPath, $f)

Basta chamá-lo com, <script/.exe name> <depth>por exemplo.script.exe 5.
Funcionará para qualquer quantidade de diretórios; talvez até mais do que seu sistema de arquivos possa suportar. : D

Como funciona:

É apenas um loop simples que adiciona o índice a uma string. Em seguida, o diretório (e todos os diretórios pai também) são criados e o arquivo se copia para esse diretório.


1

Node.js, 136 133 * 0,9 * 0,5 = 61,2 59,85

r=require,f=r('fs'),p=__dirname;while(i=process.argv[2]--)f.mkdirSync(p+='/'+i);f.linkSync(a=__filename,p+'/'+r('path').basename(a))

fs.linkSyncmapeia para o link de chamada POSIX , que cria um link físico. Um argumento inválido fará com que o programa falhe.


1

J, 82 * 0,9 = 73,8

Esta é principalmente uma porta da resposta mais votada.

exit (1!:1[1{A) 1!:2 <] (s,'/',>1{A)[fpathcreate s=:' /'charsub":1+i.".>{:A=:ARGV

Salvar como skittish.ijsou o que quiser, e chamá-lo a partir da linha de comando usando a sua versão do jconsole. O meu está vinculado a jc:

$ jc skittish.ijs 20
$ ls 1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/skittish.ijs 
1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/skittish.ijs

0

Zsh , 55 * 0,9 * 0,5 = 24,75 bytes

Eu estava de olho nesse desafio por um longo tempo, mas queria concluí-lo no Zsh sem chamar nenhum programa externo como mkdir e ln(caso contrário, seria idêntico à solução do bash). Acontece que o Zsh pode fornecer suas próprias versões desses programas!

zmodload zsh/files
mkdir -p ${(j:/:):-{1..$1}}
ln $0 $_

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.