9
\$\begingroup\$

Task

Given an input string of one or more ASCII characters which codepoints are between 0 and 128 (exclusive), do the following:

  1. Convert each character into its 7-bit ASCII code (if the ASCII code is less than 7 bits, put leading zero bits)
  2. Concatenate all bits (this results in 7*n bits where n is the number of characters)
  3. For each bit in this bitstream, print 1 if it is different from the previous bit, and print 0 otherwise. The first output bit is always 1.

Example

Input:

Hi

Output:

11011001011101

Explanation:

The string "Hi" has the ASCII codes

72 105

which in bits are:

1001000 1101001

And the transition bits indicators:

11011001011101

This is code golf. Lowest byte count wins.

Test Cases

Test case 1:

Hello World!
110110010101110011010101101010110001110000111110000110000001011101101010101100110001

Test case 2:

%% COMMENT %%
1110111111011111100001100010010100001010110101011010011101010011111110011000001101111110111

Test case 3 (credit to Luis Mendo):

##
11100101110010

Congrats to Luis Mendo for the shortest solution with 9 bytes in MATL!

\$\endgroup\$
  • 2
    \$\begingroup\$ Suggested test case ## (leading 0 bit; some answers currently fail because of that) \$\endgroup\$ – Luis Mendo Jul 10 at 9:25
  • 4
    \$\begingroup\$ How is this a duplicate of the Manchester encoding challenge? Am I missing something? \$\endgroup\$ – gastropner Jul 10 at 10:25
  • 2
    \$\begingroup\$ The other challenge says converting an input stream of bits into a double-rate output stream, with each input '1' translated to a '01' and each input '0' translated to a '10'. So not dupe in my opinion. If a large number of people upvote @gastropner's comment above I can un-dupe (or any other user with that ability) \$\endgroup\$ – Luis Mendo Jul 10 at 11:24
  • 1
    \$\begingroup\$ @Shaggy: Both test cases include a space, which has only a single bit set, and not the 7th. So I don't think the problem statement is guaranteeing that each ascii code will be exactly 7 bits in length. \$\endgroup\$ – recursive Jul 10 at 15:05
  • 1
    \$\begingroup\$ @SmileAndNod On second thought, I think you don't need to handle empty string. \$\endgroup\$ – justhalf Jul 17 at 21:47

28 Answers 28

4
\$\begingroup\$

MATL, 9 bytes

Hj7&B!hdg

Try it online!

Explanation

H     % Push 2
j     % Read line of input, unevaluated
7&B   % Convert to binary with 7 bits. Gives a 7-column matrix
!     % Transpose
h     % Concatenate horiontally. The matrix is read in column-major order
d     % Consecutive differences
g     % Convert to logical. Implicitly display
\$\endgroup\$
  • 1
    \$\begingroup\$ This is the shortest so far. +1. It's fun to have a built-in for consecutive differences. \$\endgroup\$ – justhalf Jul 12 at 5:19
5
\$\begingroup\$

Python 2, 58 bytes

n=1
for c in input():n=n<<7|ord(c)
print'1'+bin(n^n/2)[4:]

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Japt -P, 11 bytes

Takes advantage of the fact that spaces can be coerced to 0 in JavaScript when trying to perform a mathematical or, in this case, bitwise operation on it.

c_¤ù7Ãä^ i1

Try it or run all test cases

c_¤ù7Ãä^ i1     :Implicit input of string
c_              :Map codepoints
  ¤             :  Convert to binary string
   ù7           :  Left pad with spaces to length 7
     Ã          :End map
      ä^        :XOR consecutive pairs
         i1     :Prepend 1
                :Implicitly join and output
\$\endgroup\$
  • \$\begingroup\$ The 7-bit means that if it is 32 (for space character), it would be 0100000. Also the % character (37) would be 0100101 \$\endgroup\$ – justhalf Jul 10 at 16:58
  • \$\begingroup\$ It's working now. +1 \$\endgroup\$ – justhalf Jul 10 at 17:04
2
\$\begingroup\$

CJam, 21 bytes

1q{i2b7Te[}%e__(;.^);

Try it online!

Explanation

Showing the stack with a sample input of 5:

1 q      e# Push 1 and then the whole input: 1 "5"
{
  i      e# Convert to its char code: 1 [53]
  2 b    e# Convert to binary: 1 [[1 1 0 1 0 1]]
  7 T e[ e# Left-pad with 0 to length 7: 1 [[0 1 1 0 1 0 1]]
} %      e# Map this block over every character in the string
e_       e# Flatten array: 1 [0 1 1 0 1 0 1]
_ ( ;    e# Duplicate array and remove its first element: 1 [0 1 1 0 1 0 1] [1 1 0 1 0 1]
. ^      e# Element-wise xor: 1 [1 0 1 1 1 1 1]
) ;      e# Remove and pop the last element of the array: 1 [1 0 1 1 1 1]
         e# Stack implicitly printed: 1101111

To see if a bit is different from the previous bit, we do a vector (element-wise) xor between the bit array and the bit array without the first element. We also remove the last bit of the result, because it is always the last bit of the longer array unchanged.

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Unicode), 16 bytesSBCS

Full program. Prompts for string from stdin.

1,2≠/∊1↓¨11⎕DR¨⍞

Try it online!

 prompt for input ("a quote in a console")

11⎕DR¨ change each character to bit-Boolean Data Representation

1↓¨ drop the first bit from each

ϵnlist (flatten)

2≠/ pairwise difference

1, prepend a one

\$\endgroup\$
2
\$\begingroup\$

Jelly, 12 bytes

O+Ø⁷BḊ€FIA1;

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 25 bytes

⭆θ◧⍘℅鲦⁷←Wⅈ←I﹪⍘KD²←01 ²1

Try it online! Link is to verbose version of code. Explanation:

⭆θ◧⍘℅鲦⁷←

Convert all the characters to binary and pad them to a length of 7 and then print them, but leave the cursor over the last digit.

Wⅈ

Repeat until the cursor is over the first digit.

←I﹪⍘KD²←01 ²

Calculate whether the digits are different and overwrite each digit with the difference.

1

Overwrite the first digit with a 1.

\$\endgroup\$
2
\$\begingroup\$

PowerShell, 73 56 49 bytes

$args|%{$b=+$_
6..0}|%{+($c-ne($c=($b-shr$_)%2))}

Try it online!

-17 bytes thanks to mazzy :)

\$\endgroup\$
  • 1
    \$\begingroup\$ -17 bytes :D \$\endgroup\$ – mazzy Jul 10 at 15:52
  • \$\begingroup\$ Awesome, you have to post it yourself. \$\endgroup\$ – Andrei Odegov Jul 10 at 16:50
  • \$\begingroup\$ this answer for you. my princess is in another castle :)))) \$\endgroup\$ – mazzy Jul 10 at 16:56
  • 1
    \$\begingroup\$ @mazzy, some more -7 bytes :) \$\endgroup\$ – Andrei Odegov Jul 10 at 23:08
  • \$\begingroup\$ awesome and brilliant! 【ツ】 \$\endgroup\$ – mazzy Jul 11 at 4:41
2
\$\begingroup\$

Ruby -p, 68 57 bytes

-11 bytes by shamelessly stealing the method used by xnor's Python solution.

l=1
gsub(/./){l=l<<7|$&.ord}
$_=?1+(l^l/2).to_s(2)[2..-1]

Try it online!

Original solution:

gsub(/./){'%07b'%$&.ord}
l=p
gsub(/./){b=$&.ord-48;r=l ?l^b:1;l=b;r}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Octave, 36 30 bytes

Fix thanks to Luis Mendo

-2 bytes thanks to Sanchises

@(a)[1;~~diff(de2bi(a,7)'(:))]

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You can probably shave off quite a few bytes with de2bi. \$\endgroup\$ – Sanchises Jul 13 at 12:18
  • \$\begingroup\$ Wasn't working for me before @sanchises but I'll take another look when I can \$\endgroup\$ – Expired Data Jul 13 at 12:23
  • \$\begingroup\$ Try it online! \$\endgroup\$ – Sanchises Jul 13 at 15:08
1
\$\begingroup\$

Python 2, 104 bytes

lambda w:reduce(lambda(A,P),C:(A+'10'[P==C],C),bin(reduce(lambda a,c:a*128+ord(c),w,1))[3:],('','x'))[0]

Try it online!

A quick stab at it.

\$\endgroup\$
  • \$\begingroup\$ Clever trick with a*128+ord(c)! But isn't the reduce and lambda kind of costly? \$\endgroup\$ – justhalf Jul 10 at 3:54
1
\$\begingroup\$

Dart, 213 168 bytes

f(s,{t,i}){t=s.runes.map((r)=>r.toRadixString(2).padLeft(7,'0')).join().split('').toList();for(i=t.length-1;i>0;i--)t[i]=t[i]==t[i-1]?'0':'1';t[0]='1';return t.join();}

Previous one-liner

f(String s)=>'1'+s.runes.map((r)=>r.toRadixString(2).padLeft(7,'0')).join().split('').toList().reversed.reduce((p,e)=>p.substring(0,p.length-1)+(p[p.length-1]==e?'0':'1')+e).split('').reversed.join().substring(1);

Try it online!

This verbosity and lack of easy built ins is really killing this one. Still managed to pull a one liner though.

  • -45 bytes by not using a one liner and using a for loop
\$\endgroup\$
1
\$\begingroup\$

Stax, 13 12 bytes

ìEÖâU₧(~¬8IE

Run and debug it

If it's guaranteed that all input characters have the 7th bit set, as some answers assume, it can be done in 10 bytes

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

Kotlin, 182 bytes

var l='6'
fun f(b:String)=b.fold(""){t,i->t+"".a(i.toInt())}.map{if(l==it){l=it;0} else {l=it;1}}
fun String.a(v:Int):String=if(v<=0)"${this}0".reversed() else "${this}${v%2}".a(v/2)

Try it online!

Hopefully I can improve this soon, I feel like there must be some spots for improvement but I can't think right now

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

Perl 5 -p, 60 bytes

s/./sprintf'%07b',ord$&/ge;s/.(?=(.))/0|$&^$1/ge;s/^/1/;chop

Try it online!

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

C (gcc (MinGW)), 90 bytes

Requires a compiler providing itoa().

n[9],b,c;f(char*s){for(b=*s<64;c=*s++;printf("%07s",itoa((c^c/2)&127,n,2)))c|=b<<7,b=c&1;}
\$\endgroup\$
1
\$\begingroup\$

Ruby -p, 50 bytes

gsub(/./){"%07b"%$&.ord}
gsub(/./){$`=~/#$&$/?0:1}

Try it online!

Explanation

First line, same as Value Ink's answer:

gsub(/./){       $&    }   # Replace each character $&…
                   .ord    # …with its ASCII code…
                %          # …formatted as…
          "%07b"           # …binary digits padded to 7 places.

Second line:

gsub(/./){      $&      }  # Replace each character $&…
          $`               # …if the text to its left…
            =~             # …matches…
              /#  $/       # …the Regexp /c$/ where "c" is the character…
                    ?0:1   # …with 0, or 1 otherwise.

In Ruby you can use interpolation in Regexp literals, e.g. /Hello #{name}/, and for variables that start with $ or @ you can omit the curly braces, so if e.g. $& is "0" then the grawlixy /#$&$/ becomes /0$/.

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

K (ngn/k), 9 13 bytes

Solution:

~=':,/(7#2)\'

Try it online!

Explanation:

~=':,/(7#2)\' / the solution
           \' / convert each
      (   )   / do this together
       7#2    / 2 2 2 2 2 2 2
    ,/        / flatten
 =':          / equal to each-previous?
~             / not

Notes:

  • +4 bytes to support strings consisting only of 6-bit chars
\$\endgroup\$
  • \$\begingroup\$ This seems to fail for input # for example (output only has 6 bits) \$\endgroup\$ – Luis Mendo Jul 10 at 9:19
  • \$\begingroup\$ @streetster, do you want to post the fixed version? \$\endgroup\$ – justhalf Jul 11 at 14:18
1
\$\begingroup\$

Emojicode, 263 bytes

🏁🍇🔤🔤➡️🖍🆕s🔂b📇🆕🔡👂🏼❗️❗️🍇🍪s🔪🔡🔢b❗️➕128 2❗️1 7❗️🍪➡️🖍s🍉🔤?🔤➡️🖍🆕p🔂b s🍇↪️b🙌p🍇👄🔤0🔤❗️🍉🙅🍇👄🔤1🔤❗️🍉b➡️🖍p🍉🍉

Try it online here.

Ungolfed:

🏁 🍇  💭 Main code block
    🔤🔤 ➡️ 🖍 🆕 s  💭 Start with s as the empty string
    🔂 b 📇 🆕 🔡 👂🏼  💭 For each byte b in the input ...
    ❗️ ❗️ 🍇
        🍪 s  💭 ... append ...
           🔪 🔡 🔢 b ❗️ ➕ 128  💭 ... b + 128 (this gives the leading zero(s) in case the binary representation of b is shorter than 7 digits) ...

                 2  💭 ... in binary ...
              ❗️
              1 7  💭 ... without the leading one ...
           ❗️
        🍪
        ➡️ 🖍 s  💭 ... to s
    🍉
    🔤?🔤 ➡️ 🖍 🆕 p  💭 This will be used as the previous character, by assigning it neither 0 nor 1 we assure the first bit output is always a one
    🔂 b s 🍇  💭 For each character in s:
        ↪️ b 🙌 p 🍇  💭 If it is the same as the previous character ...
            👄 🔤0🔤 ❗️  💭 ... output a zero ...
        🍉 🙅 🍇  💭  ... else ...
            👄 🔤1🔤 ❗️ 💭 ... output a one
        🍉
        b ➡️ 🖍 p  💭 And the current character becomes the new previous character.
    🍉
🍉
\$\endgroup\$
1
\$\begingroup\$

JavaScript (V8), 150 95 bytes

-55 thanks to @dana

x=>[...[...x].reduce((a,c)=>a+c.charCodeAt(0).toString(2).padStart(7,0),"")].map(c=>x!=(x=c)|0)

Try it online!

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

Python3.8, 72 bytes

Solution:

lambda a:["10"[a==(a:=x)]for x in"".join(bin(ord(i)+128)[3:]for i in a)]

Explanation:

Ever since Python 3.8 introduced assignment expressions (rather than the standard assignment statements), I have wanted to use them in a list comprehension that needs to remember the last item. This is not the best way to do this but demonstrates an interesting method of using the assignment expression.

The code creates a lambda function which takes the required argument which is the string to convert. When called, the function proceeds as follows. Every character in a is converted to its character code which 128 is added to for dealing with 6-bit characters (the binary representation will always be 8 bits and we can chop off the first bit). This number is converted to binary and the header (0x) and the initial 1 from adding 128 is chopped off. These new strings are then joined into one larger string.

For each character in this new string (which contains the concatenated 7-bit representation of the text), it is checked if the character is the same as the previous character. What happens with the first character? The first result character should always be "1" so we just have to make sure that whatever is in the last character variable is neither "1" nor "0". We do this by reusing the original parameter now that we are not using it anymore. This may be a problem if the original string was a single "0" (a single "1" just happens to work) but we will ignore that.

During the comparison, the previous character was evaluated first so when we use the assignment expression to set the previous character variable to the current character, it does not affect the comparison expressions' evaluation.

The comparison either produces True or False which can also be used as 1 or 0 respectively in Python, so they are used to look up either a "1" or "0" in a string

\$\endgroup\$
  • \$\begingroup\$ You can save some bytes by using string format literals: bin(ord(i)+128)[3:] -> f"{ord(i):07b}" \$\endgroup\$ – movatica Jul 25 at 10:02
1
\$\begingroup\$

Tcl, 215 167 140 bytes

{{s {B binary} {X ~$w/64}} {join [lmap c [split $s {}] {$B scan $c c w;$B scan [$B format i [expr 2*$w^$w^$X<<7]] B7 r;set X $w;set r}] ""}}

Try it online!

Uses shift-by-one and exclusive-or to detect transitions. Carries lsb of current character to msb of next character. Combines output for each character by joining list returned by lmap.

Uses lambdas with default arguments to save bytes on initialization and repeated commands.

Relies heavily on order of operation. Works for empty string.

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

05AB1E (legacy), 12 bytes

Çb7jð0:¥ÄJ1ì

Uses the legacy version of 05AB1E, since j implicitly joins the strings together, which requires an explicit J after the j in the new version of 05AB1E.

Try it online or verify all test cases.

Explanation:

Ç             # Convert the (implicit) input-string to a list of ASCII code-points
              #  i.e. "Hi#" → [72,105,35]
 b            # Convert each integer to a binary string
              #  → ["1001000","1101001","100011"]
  7j          # Prepend each with spaces to make them length 7,
              # and join everything together to a single string implicitly
              #  → "10010001101001 100011"
    ð0:       # Replace all those spaces with 0s
              #  → "100100011010010100011"
       ¥      # Get the deltas of each pair of 1s/0s
              #  → [-1,0,1,-1,0,0,1,0,-1,1,-1,0,1,-1,1,-1,0,0,1,0]
        Ä     # Get the absolute value of this
              #  → [1,0,1,1,0,0,1,0,1,1,1,0,1,1,1,1,0,0,1,0]
         J    # Join them all together
              #  → "10110010111011110010"
          1ì  # And prepend a 1
              #  → "110110010111011110010"
              # (after which the result is output implicitly)
\$\endgroup\$
1
\$\begingroup\$

Haskell, 137 bytes

import Data.Char
b 0=[]
b n=odd n:b(n`div`2)
d x|x='1'|1<2='0'
c=('1':).map d.(zipWith(/=)<*>tail).concatMap(reverse.take 7.b.(+128).ord)

Try it online!

The biggest problem here is converting booleans (result of the XOR) to '0'/'1'.

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

Python 3, 88 84 bytes

l=2;s=''
for c in''.join(f'{ord(c):07b}'for c in input()):s+='01'[l!=c];l=c
print(s)

Try it online!

I feel that the assignments should be avoidable, but couldn't think of any way to do that.

Update:

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

PHP, 90 bytes

for(;$c=ord($argn[$j++]);$o.=sprintf('%07b',$c));for(;($q=$o[$i++])>'';$p=$q)echo$p!=$q|0;

Try it online!

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

C# (Visual C# Interactive Compiler), 80 bytes

s=>{for(int p,c=2,i=0;i<7*s.Length;Write(p==c?0:1))(p,c)=(c,1&s[i/7]>>6-i++%7);}

Try it online!

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

JavaScript (V8), 73 bytes

s=>[...c=s.repeat(7)].map((_,i)=>(c=1&s.charCodeAt(i/7,p=c)>>6-i%7)!=p|0)

Try it online!

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