Пугливая программа

17

Задача

Вы должны написать программу, которая получает целое число в nкачестве входных данных (из командной строки) и встраивает себя (программу) nв каталоги дерева каталогов. Пример с n=5:

Пример с n = 5

Имена папок могут быть любыми. Единственными требованиями являются правильность глубины и возможность повторного запуска программы из нового места в дереве каталогов, а также в том, что новый исходный файл сохраняет то же имя файла.

Бонусы:

  • Оценка * 0,9 Если все каталоги имеют разные имена (должно быть верно, по крайней мере, до глубины 1 000 000)
  • Оценка * 0,5 Если вы не можете прямо или косвенно прочитать или переместить исходный файл или получить доступ к исходному коду программы
globby
источник
1
Что считается « чтением источника »? Вы имеете в виду файл? Или настоящий исходный код?
GiantTree
2
@unclemeat Это так, потому что для перемещения файла вы (или система) должны получить доступ к данным в файле.
globby
25
Похоже , вы просто пытаетесь скрыть свою порно притон.
Абле
3
@globby как насчет lnкоманды в * nix? Если я не ошибаюсь, это просто создание другой записи в файле inode, и никакой контент вообще не читается.
HJK
7
@globby Насколько я знаю, перемещение файла не читает содержимое, если вы не перемещаетесь между жесткими дисками или разделами. В основном это просто изменение некоторых указателей в файловой системе.
Мартин Эндер

Ответы:

36

Баш, 30 * 0,9 * 0,5 = 13,5

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

Принимает глубину в качестве первого аргумента. Создает жесткую ссылку на себя в следующую структуру каталогов:

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

Затем сценарий может быть запущен из нового места, даже если rmон запущен на старом сценарии.

Объяснение:

seq -s/ $1выводит числа от 1 до $1(первый аргумент), разделенные косой чертой.

mkdir -p `seq -s` $1создает каталог, указанный seqс -pсозданием всех промежуточных каталогов.

ln $0 $_ создать жесткую ссылку на текущий запущенный скрипт во вновь созданном каталоге.

Старый (30 * 0,9 = 27):

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

Пример выполнения (с 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

Спасибо @DigitalTrauma за предложение заменить $(..)на`..`

Спасибо @hjk за предложение использовать ln.

es1024
источник
6
Блестящее использование $_!
wchargin
2
Сохраните символ - используйте галочки вместо $( ): codegolf.stackexchange.com/a/25572/11259
Цифровая травма
2
В зависимости от ответа на мой комментарий к вопросу , возможно, замените cpна, lnчтобы получить бонус 0.5 тоже ...
hjk
2
Уэллс, теперь есть обновление от OP, и mvоно также ограничено этим 0,5 бонусом. Это все еще остается lnоткрытым, да?
ХИК
2
Да, ln(вам не нужно -s) фактически поместит программу в новый каталог, чтобы ее можно было выполнить оттуда, даже не читая, не перемещая и не обращаясь к исходному источнику. Я говорю, пойти на счет FALCON PUNCH 13,5!
Тобиа
12

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

Мое решение в 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)))

Здесь в несколько более читаемой форме:

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

Проверьте, работает ли он:

$ 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

Вероятнее всего, в исходном коде большой потенциал для игры в гольф.

MarcDefiant
источник
Отличное использование препроцессора!
LeFauve
5

Партия - 48 * 0,9 = 43,2

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

Этот скрипт просто создает новый каталог и перемещает в него исходный файл - nраз.

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
unclemeat
источник
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

Пример:

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) (Просто для записи, у меня не получается с bash4.3.11: «синтаксическая ошибка рядом с неожиданным токеном`; '». Но отлично работает с zsh5.0.2)
manatwork
Не могли бы вы сохранить персонажа, удалив dранее $i?
Канадец Люк восстановит Монику
@CanadianLuke Да, я никогда не знал, что у тебя может быть каталог с именем 1. Спасибо
дверная ручка
Я думаю, вы должны быть в состоянии использовать фигурные скобки for i in {1..$1};{mkdir $i;cd $i};echo $s>f.
Ry-
@ U2744SNOWFLAKE Спасибо, это сэкономило несколько байтов. Ред.
Ручка двери
3

Реболь - 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
]


Оригинальная версия без 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
draegtun
источник
2

Баш 167 * 0,5 * 0,9 = 75,15

Сильно заимствует из отличного ответа @ es1024 , но этот - настоящий квин, поэтому он претендует на оба бонуса.

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

Кроме того, приемы оболочки Куайн отсюда .

Цифровая травма
источник
1

AutoIt3, 106 * 0,9 = 95,4 байта


Немного длинно, но я не могу помочь с этими длинными именами функций / переменных:

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

Просто позвоните с помощью, <script/.exe name> <depth>например. script.exe 5,
Это будет работать для любого количества каталогов; может быть, даже больше, чем может справиться ваша файловая система. : D

Как это устроено:

Это простой цикл, который добавляет индекс в строку. Затем создается каталог (и все родительские каталоги), и файл копирует себя в этот каталог.

GiantTree
источник
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.linkSyncотображается на ссылку вызова POSIX , которая создает жесткую ссылку. Неверный аргумент вызовет сбой программы.

CPU1
источник
1

J 82 * 0,9 = 73,8

В основном это порт ответа с наибольшим количеством голосов.

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

Сохраните как skittish.ijsили как хотите, и вызовите его из командной строки, используя вашу версию jconsole. Моя связана с 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
HoosierEE
источник
0

Zsh , 55 * 0,9 * 0,5 = 24,75 байт

Я долго смотрел на этот вызов, но хотел завершить его на Zsh, не вызывая никаких внешних программ, таких как mkdirи ln(в противном случае он был бы идентичен решению bash). Оказывается, Zsh может предоставить свои версии этих программ!

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

Попробуйте онлайн!

GammaFunction
источник