10
\$\begingroup\$

My coworker and I work on a legacy piece of software that we hate sometimes. Whenever you run it, debug asserts come flying everywhere, and it's never a guarantee that anything will work. The motivation for this round of code golf came from my coworker saying the following about our software.

"It's like every time you run this program, you're agreeing to some terms of service that says every 17th bit on your hard drive will be turned into a 1"

Goal: Write a program that will make an exact copy of a file and turn every 17th bit of a text file into a 1

  • You may NOT turn EVERY bit of the file to a 1. i.e. your program must show some intelligence that it is only targeting every 17th bit
  • You may NOT write to the original file in any way shape or form
  • The Winner is the smallest program submission at the end of the month

Have fun with this one! Go!

\$\endgroup\$
  • 7
    \$\begingroup\$ 1. Every question needs an objective winning criterion. Most questions are code-golf, i.e., shortest code in bytes wins. A code-challenge needs a well specified scoring system. 2. Turning every 18th bit of a hard drive into a 1 is only possible by writing directly to the drive. This cannot be accomplished by creating and/or modifying files. 3. Doing this will render the entire drive unusable, so a compliant solution will be destructive. I don't know how well the community will receive a request to write malware... \$\endgroup\$ – Dennis Sep 3 '14 at 5:52
  • 2
    \$\begingroup\$ I'd vote to re-open this question, if only I had enough rep. :/ \$\endgroup\$ – Sammitch Sep 4 '14 at 19:14
  • 3
    \$\begingroup\$ @steveverrill I'll change it to code golf, however I'm going to change it from 18th bit to 17th bit, to make things interesting. \$\endgroup\$ – C. Tewalt Sep 4 '14 at 22:48
  • 1
    \$\begingroup\$ @matrixugly 17th bit certainly is more interesting. Bear in mind that it is not good form to change the rules in a way that invalidates existing answers (that's why questions get put on hold, in order to avoid answers being posted that make the question impossible to fix.) However the existing answer doesn't comply with other current rules anyway, so it's not a big problem in this case. \$\endgroup\$ – Level River St Sep 4 '14 at 23:50
  • 1
    \$\begingroup\$ How is the file read in? stdin? \$\endgroup\$ – Milo Sep 5 '14 at 3:55

11 Answers 11

9
\$\begingroup\$

CJam, 22 bytes

q256b2H#b1f|2H#b256b:c

Try it online.

Touches every 17th bit, counting from the last.

I've used STDIN and STDOUT since CJam has no file I/O. If that's not allowed, the program can be wrapped in a Bash script at the cost of 24 extra bytes:

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

How it works

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.                            ";
\$\endgroup\$
  • 1
    \$\begingroup\$ +1, I really need to look into CJam. Awesome how much obfuscation you can get into a 22 byte code that still serves a purpose... \$\endgroup\$ – Padarom Sep 5 '14 at 11:37
  • 1
    \$\begingroup\$ Well done. It converted "Take the every 17th bit and turn it to a 1" into ""Tike vhe eöery 17th fiv and turn yt(to c 1" \$\endgroup\$ – C. Tewalt Sep 5 '14 at 16:44
  • \$\begingroup\$ Why does this work? I don't follow.. \$\endgroup\$ – Claudiu Sep 6 '14 at 1:20
  • 1
    \$\begingroup\$ Yes, I wasn't sure if I should post it, but since the Perl answer did basically the same... A Bash wrapper to meet the file I/O requirements would elevate the byte count to 46. More than twice as long, but still the shortest answer. \$\endgroup\$ – Dennis Sep 7 '14 at 18:55
  • 1
    \$\begingroup\$ @matrixugly sorry! the spec left your file IO intent a little ambiguous. i personally didn't recognize an issue. not to keep harping on the merits of the codegolf sandbox, but the question getting closed and this requirement confusion probably could have been avoided. enjoyed the challenge regardless \$\endgroup\$ – ardnew Sep 8 '14 at 4:05
6
\$\begingroup\$

Perl 59

regex substitution on bit strings:

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

usage:

perl this.pl < infile.txt > outfile.txt
\$\endgroup\$
  • \$\begingroup\$ the endianness can be toggled by switching between b and B in the pack templates \$\endgroup\$ – ardnew Sep 5 '14 at 3:58
2
\$\begingroup\$

C, 125

Assumes big-endian and 16-bit integers.

Works by applying a bitwise-OR on every two bytes.

Input file is y, output is 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);}

Ungolfed

// 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);
    }
}
\$\endgroup\$
  • \$\begingroup\$ rules on this question have been updated... \$\endgroup\$ – Level River St Sep 4 '14 at 23:51
  • \$\begingroup\$ @steveverrill and the answer has now been updated accordingly \$\endgroup\$ – es1024 Sep 5 '14 at 2:07
  • \$\begingroup\$ @Comintern What should happen around the time when a becomes 0: 00000000 00000001 00000000 00000000 10000000 00000000, thus a should be zero at certain points. The machine must use big endian (or else you would have 00000000 10000000 instead of 10000000 00000000, which would give the wrong value). \$\endgroup\$ – es1024 Sep 5 '14 at 6:59
  • \$\begingroup\$ Hrm... Never mind. Taking out c = __builtin_bswap16(c); corrected it. \$\endgroup\$ – Comintern Sep 5 '14 at 13:07
2
\$\begingroup\$

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

This sets every 17th big-endian bit, starting 17th from the beginning. It uses no libraries. It works by converting the input file to a gigantic n-bit integer and bitwise ORing with 2**n/(2**17 - 1) == 0b10000000000000000100000000000000001….

\$\endgroup\$
1
\$\begingroup\$

C - 139

Reads from a file named "i", outputs to a file named "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;}

With line breaks:

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

Counts bits of input and then uses a floating bitmask to set every seventeenth bit.

\$\endgroup\$
1
\$\begingroup\$

Java - 247

Uses a BitSet and a simple loop instead of handling/masking the bytes manually. Of course this being java, the boilerplate is half the program, so it's not exactly short.

Still, not last! :D

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

No-scroll version:

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());
    }
}
\$\endgroup\$
1
\$\begingroup\$

Python - 98 bytes

Read from i, write to o. Uses bitarray library https://pypi.python.org/pypi/bitarray

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

ungolfed

from bitarray import *
a=bitarray()
a.fromfile(open('i','rb'))
a[::17]=1
a.tofile(open('o','wb'))
\$\endgroup\$
  • \$\begingroup\$ Wouldn't it need to be a[::17]=1? \$\endgroup\$ – undergroundmonorail Sep 8 '14 at 10:38
  • \$\begingroup\$ Also, I believe you can save a byte with from bitarray import* and a=bitarray(). \$\endgroup\$ – undergroundmonorail Sep 8 '14 at 10:39
0
\$\begingroup\$

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)

Every time I do one of these 'manipulate the individual bits of something' challenges, I wish that either Cobra or the .NET standard library had a binary string => integer converter.

\$\endgroup\$
0
\$\begingroup\$

Javascript (+HTML5), 282

Probably not the shortest, but it's user friendly :D

It's cross browser, but it seems that chrome is the only one allowing it when the html file is a local file (= access with file://...). For the other browsers, you need to put it on a web server.

The output file should be saved to the default download directory, maybe with a file prompt (depending on your configuration).

<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])">

Ungolfed version :

<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]);
">
\$\endgroup\$
0
\$\begingroup\$

Python 3 - 187 bytes


Reads in from i and writes to o.

Code:

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

Ungolfed:

# 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
\$\endgroup\$
-1
\$\begingroup\$

Python 3 - 103 chars

Change f to the path of the file you want to read and o to path of the file you want to write to.

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)) 
\$\endgroup\$
  • 6
    \$\begingroup\$ It's every 17th bit, not byte. \$\endgroup\$ – matsjoyce Sep 5 '14 at 12:34
  • 1
    \$\begingroup\$ Also, it's 17th, not 18th. \$\endgroup\$ – Dennis Sep 5 '14 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.