Implemente la utilidad dog bash


10

dog es una utilidad de línea de comandos que toma un número arbitrario de argumentos, el primero de los cuales es el texto a escribir y los otros son arbitrariamente muchos archivos.

La dogutilidad dividirá el texto en partes iguales sobre estos archivos. Si hay un resto n, los primeros narchivos obtienen un byte adicional

doges lo opuesto de cat, como tal, para todos x, lo siguiente debería ser válido.

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

Donde ...indica arbitrariamente muchos archivos.

Un ejemplo (12 bytes, 3 archivos, se pueden dividir equitativamente):

$> ./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$> 

Un ejemplo con resto (13 bytes, 5 archivos, resto 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$>

Está implícito, pero solo para verificar: 1) ¿Los argumentos tienen que venir a través de la línea de comando? 2) ¿Siempre tenemos que dar salida a los archivos?
Sp3000

@ Sp3000 sí, a 1 y 2
Caridorc

1
@DigitalTrauma ya hay una respuesta, me sentiría mal por invalidarlo por un cambio de regla
Caridorc

2
Últimamente he estado aprendiendo sobre algunas utilidades UNIX de este sitio (tac, dog, ...).
kirbyfan64sos

1
@ Kirbyfan64sos y Caridorc: taces real .
DLosc

Respuestas:


4

Pyth - 12 bytes

.wMC,cl.zz.z

Utiliza la función de división integrada y luego usa splat-map en la función de escritura. No funciona en línea.


2

Python - 181 bytes

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 bytes

El código de golf:

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

El código detallado:

$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
}

0

Golpe puro: 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};}

Como una función: ( p=solo se requiere para la segunda ejecución)

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

Pruebas

$> 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
$> 

Todos los archivos son de 4 bytes y están concatenados en el orden correcto, contienen "Perros contra gatos" .

$> 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
$> 

Los primeros archivos son 3 bytes len y los últimos solo 2, concatenados por orden alfabético, contienen "0123456789abc" .

Explicación (ungolfing):

Si se golpea: declare -f dog, responderá:

$> 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
}

Esto podría escribirse:

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

Ruby, 93 87 bytes

Programa completo utilizando argumentos de línea de comando.

Si pudiera usar s.slice!para mutar la cadena, lo haría en lugar de tener que usarla s[c..-1], pero Ruby no te permite mutar las cadenas de argv sin duplicarlas primero

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]}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.