Реализуйте утилиту для собак

10

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

dogУтилита разделить текст на равные части над этими файлами. Если есть остаток n, первые nфайлы получают дополнительный байт

dogпротивоположность cat, как таковая, для всего x, следующее должно иметь место.

$> dog x a.txt b.txt ...
$> cat a.txt b.txt ...
x$>

Где ...указывает произвольно много файлов.

Пример (12 байт, 3 файла, можно разделить равномерно):

$> ./dog.py "Dogs vs Cats" a.txt b.txt c.txt
$> cat a.txt
Dogs$> cat b.txt
 vs $> cat c.txt
Cats$> cat a.txt b.txt c.txt
Dogs vs Cats$> 

Пример с остатком (13 байт, 5 файлов, остаток 3):

9$>./dog.py "0123456789abc" a.txt b.txt c.txt d.txt e.txt
$> cat a.txt
012$> cat b.txt
345$> cat c.txt
678$> cat d.txt
9a$> cat e.txt
bc$> cat a.txt b.txt c.txt d.txt e.txt
0123456789abc$>
Caridorc
источник
Это подразумевается, но только для двойной проверки: 1) Должны ли аргументы вводиться через командную строку? 2) Всегда ли мы должны выводить в файлы?
Sp3000
@ Sp3000 да, до 1 и 2
Caridorc
1
@DigitalTrauma ответ уже есть, я бы чувствовал себя плохо из-за того, что аннулировал его изменением правила
Caridorc
2
Недавно я узнал о некоторых утилитах UNIX со странным названием на этом сайте (tac, dog, ...).
kirbyfan64sos
1
@ kirbyfan64sos и Caridorc: tacэто реально .
DLosc

Ответы:

4

Pyth - 12 байт

.wMC,cl.zz.z

Использует встроенную функцию split, а затем использует splat-map для функции записи. Не работает онлайн.

Maltysen
источник
2

Python - 181 байт

import sys
a=sys.argv
l=len
d=a[2:]
s=a[1]
n,r=divmod(l(s),l(d))
p=0
for i in range(l(d)):
    with open(d[i],'w') as f:
        o=n+int(i<=n)
        f.write(s[p:p+o])
        p+=o
Зак Критов
источник
1

PHP, 107 байт

Гольф-код:

for($i=1;++$i<$argc;fputs(fopen($argv[$i],w),substr($s=$argv[1],($i-2)*$l=ceil(strlen($s)/($argc-2)),$l)));

Подробный код:

$len = ceil(strlen($argv[1])/($argc - 2));
for ($i = 2; $i < $argc; $i ++) {
    $fh = fopen($argv[$i], 'w');
    fputs($fh, substr($argv[1], ($i - 2) * $len, $len));
    fclose($fh);          // omitted in the golfed version
}
axiac
источник
0

Чистая Баш: 97

s=$1;shift;for((l=${#s}/$#,m=${#s}-l*$#,i=1;i<=$#;p+=q,i++)){
printf "${s:p:q=i>m?l:l+1}">${!i};}

Как функция: ( p=требуется только для второго запуска)

dog() { p=
    s=$1;shift;for((l=${#s}/$#,m=${#s}-l*$#,i=1;i<=$#;p+=q,i++)){
    printf "${s:p:q=i>m?l:l+1}">${!i};}
}

тесты

$> rm *
$> dog "Dogs vs Cats" a.txt b.txt c.txt
$> ls -l
total 12
-rw-r--r-- 1 user user 4 May 13 22:09 a.txt
-rw-r--r-- 1 user user 4 May 13 22:09 b.txt
-rw-r--r-- 1 user user 4 May 13 22:09 c.txt
$> cat {a,b,c}.txt;echo
Dogs vs Cats
$> 

Все файлы имеют длину 4 байта и объединены в правильном порядке, содержат «Dogs vs Cats» .

$> rm *
$> dog "$(printf "%s" {0..9} {a..c})" {a..e}.txt 
$> ls -l
total 20
-rw-r--r-- 1 user user 3 May 13 22:09 a.txt
-rw-r--r-- 1 user user 3 May 13 22:09 b.txt
-rw-r--r-- 1 user user 3 May 13 22:09 c.txt
-rw-r--r-- 1 user user 2 May 13 22:09 d.txt
-rw-r--r-- 1 user user 2 May 13 22:09 e.txt
$> cat *;echo
0123456789abc
$> 

Первые файлы имеют длину 3 байта и последние только 2, объединенные в алфавитном порядке, содержат «0123456789abc» .

Пояснение (разукраска):

Если вы попали: declare -f dog, ответит:

$> declare -f dog
dog () 
{ 
    p=;
    s=$1;
    shift;
    for ((l=${#s}/$#,m=${#s}-l*$#,i=1; i<=$#; p+=q,i++))
    do
        printf "${s:p:q=i>m?l:l+1}" > ${!i};
    done
}

Это может быть написано:

dog2 () 
{ 
    position=0;
    string=$1;
    shift;
    partLen=$((${#string}/$#));
    oneMore=$((${#string}-partLen*$#));
    for ((i=1; i<=$#; i++))
    do
        if ((i<=oneMore)); then
            partQuant=$((partLen+1));
        else
            partQuant=$partLen;
        fi;
        printf "${string:position:partQuant}" > ${!i};
        ((position+=partQuant));
    done
}
Ф. Хаури
источник
0

Руби, 93 87 байт

Полная программа с использованием аргументов командной строки.

Если бы я мог использовать s.slice!для изменения строки, я бы сделал это вместо того, чтобы использовать s[c..-1], но Ruby не позволяет вам изменять строки из argv, не дублируя их в первую очередь.

s,*t=$*
d,r=s.size.divmod t.size
t.map{|e|open(e,?w)<<s[0,c=(0>r-=1)?d:d+1];s=s[c..-1]}
Значение чернил
источник