3
\$\begingroup\$

Write some code that takes a single string as input and outputs MSB-set aligned ASCII.

Only ASCII characters less than 128 (0x80) will be in the input. The output format is generated as follows:

  • For each character convert it to its binary representation, remove the MSB (always 0 in the input) and then add a delimiter-bit (X) to both ends. The value will now be 9 bits long and both begin and end in X
  • Output each character in order, MSB to LSB, making sure that the MSB of each output byte is either 1 or X
  • If the MSB of the next byte would normally be 0, output the fewest .s needed between two consecutive Xs to align the MSB with a 1 or X
  • Output the data as binary digits, with X for each delimiter and . for each padding bit
  • At the end of the data, write a . after the last X, then as many .s as necessary to complete the last byte
  • Separate each byte (group of 8 digits) with a single whitespace character (space, tab, newline, etc.)
  • A whitespace character at the end of the last output line is optional
  • Empty input must produce ........ as the output
  • Your code must work on any length strings that your language can handle and at least 255 characters

Input: Hello, World!

Bytes    -> Delimited -> * Output    Start and End of each character
01001000    X1001000X    X1001000    'H'
01100101    X1100101X    XX110010    'e'       'H'
01101100    X1101100X    1X.X1101    'l'       'e'
01101100    X1101100X    100XX110    'l'       'l'
01101111    X1101111X    1100X.X1    'o'       'l'
00101100    X0101100X    101111X.              'o'
00100000    X0100000X    X0101100    ','
01010111    X1010111X    X.....X0    ' '       ','
01101111    X1101111X    100000XX    'W'       ' '
01110010    X1110010X    1010111X              'W'
01101100    X1101100X    X1101111    'o'
01100100    X1100100X    X.X11100    'r'       'o'
00100001    X0100001X    10XX1101    'l'       'r'
                         100X..X1    'd'       'l'
                         100100X.              'd'
                         X0100001    '!'
                         X.......              '!'

The * marks the Most Significant Bit in the output. Each bit in this column is either 1 or X. Removing any number of .s would cause either a 0 or . in the MSB column. If the input was Hello, W the last byte output would be .........

As usual, lowest score wins!

\$\endgroup\$
  • \$\begingroup\$ Sorry, I'm not following these steps. You say the MSB is always 0, but then later you say it's either 1 or X. Also I don't see how your output suddenly grew 4 entries. \$\endgroup\$ – Neil Feb 17 '16 at 11:06
  • \$\begingroup\$ @Neil Added "in the input" to answer your first question. Each byte grows from 8 bits to 9 bits and there are padding bits in the output as well. It is aligned by the MSB (8-bit) to show how that's supposed to work. \$\endgroup\$ – CJ Dennis Feb 17 '16 at 11:12
  • \$\begingroup\$ Oh, I see now, you have to wrap the delimited bytes to 8 columns but without outputting a 0 in the left column. \$\endgroup\$ – Neil Feb 17 '16 at 11:23
  • \$\begingroup\$ @Neil Yes, neither 0 or . is allowed in the leftmost column (MSB). \$\endgroup\$ – CJ Dennis Feb 17 '16 at 11:24
1
\$\begingroup\$

Python 3, 144 140 131 130 137 bytes

Damn bugs :(

O=""
for Q in input():
 C="X%07dX"%int(bin(ord(Q))[2:])
 while"1">C[8-len(O)%8]:C="."+C
 O+=C
O+="."
while O:print((O+"."*8)[:8]);O=O[8:]

This is really straight forward.

Ungolfed with explanation

# initialize output buffer
output = ""
# loop through input
for char in input():
    # get charcode, binary, remove 0b, parse as int, format
    code = "X%07dX" % int(bin(ord(char))[2:])
    # pad code while the line starting character would be 0
    while "1" > code[8 - len(output) % 8]:
        code = "." + code
    # append result to output buffer
    output += code
# add dot to ensure padding in end
output += "."
# loop while any output is left
while output:
    # print line of output, with padding
    print((output + "." * 8)[:8])
    # remove printed output
    output = output[8:]
\$\endgroup\$
  • \$\begingroup\$ I'm having fun playing with your answer! I take it there's no golfier way to say import sys and then use sys.argv which is why you're using input()? Oh, never mind! I just found out I can scroll through my previous input after calling the code! \$\endgroup\$ – CJ Dennis Feb 17 '16 at 11:39
0
\$\begingroup\$

JavaScript (ES6), 187 bytes

f=(s,t=[...s].map(c=>(c.charCodeAt()*2+257).toString(2).replace(/^1|1$/g,'X')).join``)=>t.match(r=/^(.{8})*?0/)?f(s,t.replace(r,s=>s.replace(/X[01]*?$/,".$&"))):t+'.'.repeat(8-t.length%8)

Works by recursively finding 0s at illegal positions and inserting a . before the preceding X. Ungolfed:

function f(s) {
    t = '';
    for (i = 0; i < s.length; i++) {
        c = s.charCodeAt(i);
        c = c.toString(2);
        c = '000000' + c;
        c = 'X' + c.slice(-7) + 'X';
        t += c;
    }
    while (m = t.match(/^(.{8})*?0/)) {
        p = t.lastIndexOf('X', m[0].length);
        t = t.slice(0, p) + '.' + t.slice(p);
        // if one dot isn't enough, next loop will just add another
    }
    return t + '.'.repeat(8 - t.length % 8); // pad up to 8 characters
}
\$\endgroup\$

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.