Escriba un programa que convierta cada bit 17 de un archivo de texto en 1

10

Mi compañero de trabajo y yo trabajamos en un software heredado que a veces odiamos. Cada vez que lo ejecutas, las afirmaciones de depuración vienen volando por todas partes, y nunca es una garantía de que algo funcione. La motivación para esta ronda de golf de código vino de mi compañero de trabajo diciendo lo siguiente sobre nuestro software .

"Es como si cada vez que ejecutas este programa, aceptas algunos términos de servicio que dicen que cada bit 17 en tu disco duro se convertirá en un 1".

Objetivo: escribir un programa que haga una copia exacta de un archivo y convierta cada bit 17 de un archivo de texto en un 1

  • NO puede convertir CADA bit del archivo a 1. es decir, su programa debe mostrar cierta inteligencia de que solo se dirige a cada bit 17
  • NO puede escribir en el archivo original de ninguna forma o forma
  • El ganador es la presentación de programa más pequeña a fin de mes

Diviértete con este! ¡Vamos!

C. Tewalt
fuente
77
1. Cada pregunta necesita un criterio ganador objetivo. La mayoría de las preguntas son code-golf, es decir, el código más corto en bytes gana. A code-challengenecesita un sistema de puntuación bien especificado. 2. Convertir cada 18 bits de un disco duro en 1 solo es posible escribiendo directamente en el disco. Esto no se puede lograr creando y / o modificando archivos. 3. Hacer esto hará que toda la unidad quede inutilizable, por lo que una solución compatible será destructiva. No sé qué tan bien la comunidad recibirá una solicitud para escribir malware ...
Dennis
2
Votaría para volver a abrir esta pregunta, si solo tuviera suficiente representante. :/
Sammitch
3
@steveverrill Lo cambiaré a código de golf, sin embargo, voy a cambiarlo de 18 a 17 bits, para hacer las cosas interesantes.
C. Tewalt
1
@matrixugly 17th bit ciertamente es más interesante. Tenga en cuenta que no es una buena forma de cambiar las reglas de una manera que invalide las respuestas existentes (es por eso que las preguntas se ponen en espera, para evitar que se publiquen respuestas que hacen que la pregunta sea imposible de solucionar). Sin embargo, la respuesta existente no No cumpla con otras reglas actuales de todos modos, por lo que no es un gran problema en este caso.
Level River St
1
¿Cómo se lee el archivo? stdin?
Milo

Respuestas:

9

CJam, 22 bytes

q256b2H#b1f|2H#b256b:c

Pruébalo en línea.

Toca cada bit 17, contando desde el último.

He usado STDIN y STDOUT ya que CJam no tiene E / S de archivo. Si eso no está permitido, el programa se puede incluir en un script Bash a un costo de 24 bytes adicionales:

cjam <(echo q256b2H#b1f\|2H#b256b:c)<"$1">"$2"

Cómo funciona

q                      " Read from STDIN.                                                 ";
 256b                  " Convert to integer by considering the input a base 256 number.   ";
     2H#b              " Convert to array by considering the integer a base 2**17 number. ";
         1f|           " Set the LSB of every integer in the array element to 1.          ";
            2H#b       " Convert to integer by considering the array a base 2**17 number. ";
                256b   " Convert to array by considering the integer a base 256 number.   ";
                    :c " Turn character codes into characters.                            ";
Dennis
fuente
1
+1, realmente necesito investigar CJam. Impresionante la cantidad de ofuscación puede entrar en un código de 22 bytes que todavía sirve a un propósito ...
Padarom
1
Bien hecho. Convirtió "Toma el bit cada 17 y conviértelo en un 1" en "" Haz tike vhe eöery el 17º quinto y gira yt (a c 1 "
C. Tewalt
¿Por qué funciona esto? No te sigo ..
Claudiu
1
Sí, no estaba seguro de si debía publicarlo, pero dado que la respuesta de Perl hizo básicamente lo mismo ... Un contenedor Bash para cumplir con los requisitos de E / S del archivo elevaría el recuento de bytes a 46. Más del doble de tiempo, pero sigue siendo la respuesta más corta.
Dennis
1
@matrixugly lo siento! la especificación dejó su intención de IO de archivo un poco ambigua. Yo personalmente no reconocí un problema. no para seguir insistiendo en los méritos de la caja de arena de codegolf , sino que la pregunta se cerró y esta confusión de requisitos probablemente podría haberse evitado. disfrutó el desafío independientemente
ardnew
6

Perl 59

sustitución de expresiones regulares en cadenas de bits:

$/=$\;$_=unpack"B*",<>;s|(.{16}).|${1}1|g;print pack"B*",$_

uso:

perl this.pl < infile.txt > outfile.txt
ardnew
fuente
la endianidad se puede alternar cambiando entre by Ben las packplantillas
ardnew
2

C, 125

Asume enteros big-endian y de 16 bits .

Funciona aplicando un bit-OR en cada dos bytes.

El archivo de entrada es y, la salida es z.

unsigned a,b;main(c){void*f=fopen("y","r"),*g=fopen("z","w");while(b=fread(&c,1,2,f))c|=a,a?a/=2:(a=32768),fwrite(&c,1,b,g);}

Sin golf

// The commented out /* short */ may be used if int is not 16 bits, and short is. 
unsigned /* short */ a = 0,b;
main(/* short */ c){
    void *f = fopen("y", "r"), *g = fopen("z", "w");
    while(b = fread(&c, 1, 2, f)){
      // __builtin_bswap16 may be used if you are using GCC on a little-endian machine. 
      //c = __builtin_bswap16(c);
        c |= a;
        if(a) a >>= 1;
        else a = 32768;
      //c = __builtin_bswap16(c);
        fwrite(&c, 1, b, g);
    }
}
es1024
fuente
las reglas sobre esta pregunta se han actualizado ...
Level River St
@steveverrill y la respuesta ahora se ha actualizado en consecuencia
es1024
@Comintern Lo que debería suceder alrededor del tiempo cuando a se convierte en 0: 00000000 00000001 00000000 00000000 10000000 00000000por alo tanto, debería ser cero en ciertos puntos. La máquina debe usar big endian (o de lo contrario lo tendría en 00000000 10000000lugar de 10000000 00000000, lo que daría un valor incorrecto).
es1024
Hrm ... No importa. Sacar lo c = __builtin_bswap16(c);corrigió.
Comintern
2

Python 2, 112 bytes

b=open('i').read().encode('hex')
open('o','w').write(('%x'%(int('1'+b,16)|16**len(b)/131071))[1:].decode('hex'))

Esto establece cada 17 bit big-endian, comenzando 17 desde el principio. No usa bibliotecas. Funciona convirtiendo el archivo de entrada en un nentero de bits gigantesco y ORing bit a bit 2**n/(2**17 - 1) == 0b10000000000000000100000000000000001….

Anders Kaseorg
fuente
1

C - 139

Lee desde un archivo llamado "i", da salida a un archivo llamado "o".

c;main(){unsigned char b,m=1;void *i=fopen("i","r"),*o=fopen("o","w");for(;(b=fgetc(i))<129;fputc(b,o))((c+=8)%17<8)?b|=m=(m-1)?m/2:128:0;}

Con saltos de línea:

c;main()
{
    unsigned char b,m=1;
    void *i=fopen("i","r"),*o=fopen("o","w");
    for(;(b=fgetc(i))<129;fputc(b,o))
        ((c+=8)%17<8)?b|=m=(m-1)?m/2:128:0;
}

Cuenta los bits de entrada y luego usa una máscara de bits flotante para establecer cada decimoséptimo bit.

Comintern
fuente
1

Java - 247

Utiliza ay un BitSetbucle simple en lugar de manejar / enmascarar los bytes manualmente. Por supuesto, esto es java, el repetitivo es la mitad del programa, por lo que no es exactamente corto.

Aún así, no dura. :RE

import java.util.*;import java.nio.file.*;class F{public static void main(String[]a)throws Exception{BitSet b=BitSet.valueOf(Files.readAllBytes(Paths.get(a[0])));for(int j=0;j<b.size();b.set(j),j+=17);Files.write(Paths.get("o"),b.toByteArray());}}

Versión sin desplazamiento:

import java.util.*;
import java.nio.file.*;
class F{
    public static void main(String[]a)throws Exception{
        BitSet b=BitSet.valueOf(Files.readAllBytes(Paths.get(a[0])));
        for(int j=0;j<b.size();b.set(j),j+=17);
        Files.write(Paths.get("o"),b.toByteArray());
    }
}
Geobits
fuente
1

Python - 98 bytes

Leer de i, escribir a o. Utiliza la biblioteca bitarray https://pypi.python.org/pypi/bitarray

from bitarray import*;a=bitarray();a.fromfile(open('i','rb'));a[::17]=1;a.tofile(open('o','wb'))

sin golf

from bitarray import *
a=bitarray()
a.fromfile(open('i','rb'))
a[::17]=1
a.tofile(open('o','wb'))
usuario590028
fuente
¿No debería ser así a[::17]=1?
undergroundmonorail
Además, creo que puede guardar un byte con from bitarray import*y a=bitarray().
undergroundmonorail
0

Cobra - 308

use System.Text.RegularExpressions
class P
    def main
        t,b='',File.readAllBytes('x')
        for n,i in b.numbered,for l in 8,b[n]=if(l,b[n],0)+if(Regex.replace(t+='00000000'[(j=Convert.toString(i,2)).length:]+j,'.{17}',do(m as Match)='[m]'[:-1]+'1')[n*=8:n+8][7-l]<c'1',0,2**l)to uint8
        File.writeAllBytes('y',b)

Cada vez que hago uno de estos desafíos de "manipular los bits individuales de algo", deseo que Cobra o la biblioteca estándar .NET tengan un binary string => integerconvertidor.

Οurous
fuente
0

Javascript (+ HTML5), 282

Probablemente no sea el más corto, pero es fácil de usar: D

Es un navegador cruzado, pero parece que Chrome es el único que lo permite cuando el archivo html es un archivo local (= acceso con file://...). Para los otros navegadores, debe colocarlo en un servidor web.

El archivo de salida debe guardarse en el directorio de descarga predeterminado, tal vez con una solicitud de archivo (según su configuración).

<input type=file onchange="r=new FileReader();r.onloadend=function(){w=window;a=new Uint8Array(r.result);for(i=17;i<a.length*8;i+=17)a[i/8>>0]|=1<<8-i%8;w.location.replace(w.URL.createObjectURL(new Blob([a],{type:'application/octet-binary'})));};r.readAsArrayBuffer(this.files[0])">

Versión sin golf:

<input type=file onchange="
    var reader = new FileReader();
    reader.onloadend = function() {
        var arr = new Uint8Array(reader.result);
        for(var i = 17 ; i < arr.length * 8 ; i += 17) {
            arr[Math.floor(i / 8)] |= 1 << (8 - (i % 8));
        }
        window.location.replace(
            window.URL.createObjectURL(
                new Blob([arr], {type: 'application/octet-binary'})
            )
        );
    };
    reader.readAsArrayBuffer(this.files[0]);
">
sebcap26
fuente
0

Python 3 - 187 bytes


Lee iy escribe desde o.

Código:

o=open;j="".join;f=list(j(format(x,"08b")for x in o("i","rb").read()))
f[16::17]="1"*(len(f)//17)
with o("o","wb") as f2:f2.write(bytes(int(j(f[i*8:(i+1)*8]),2)for i in range(len(f)//8)))

Sin golf:

# read file and convert to binary string e.g. "101010010101010101"
f = list("".join(format(x, "08b") for x in open("in.txt", "rb").read()))
# set every 17th bit to 1
f[16::17] = "1" * (len(f)//17)
with open("out.txt","wb") as f2:
    data = []
    for i in range(len(f)//8)): # for each byte
        byte = "".join(f[i*8:(i+1)*8] # get each byte
        data.append(int(byte),2) # convert to int
    f2.write(bytes(data)) # convert to byte string and write
matsjoyce
fuente
-1

Python 3 - 103 caracteres

Cambie fa la ruta del archivo que desea leer y oa la ruta del archivo en el que desea escribir.

l=open;t=list(l(f,'r').read())
for i in range(len(t)):
 if i%18==0:t[i]='1'
l(o,'w').write(''.join(t)) 
Decaimiento Beta
fuente
66
Es cada 17 bits, no byte.
matsjoyce
1
Además, es el 17, no el 18.
Dennis