Golf bit weaving

14

Note: the first half of this challenge comes from Martin Ender's previous challenge, Visualize Bit Weaving.

The esoteric programming language evil has an interesting operation on byte values which it calls "weaving".

It is essentially a permutation of the eight bits of the byte (it doesn't matter which end we start counting from, as the pattern is symmetric):

  • Bit 0 is moved to bit 2
  • Bit 1 is moved to bit 0
  • Bit 2 is moved to bit 4
  • Bit 3 is moved to bit 1
  • Bit 4 is moved to bit 6
  • Bit 5 is moved to bit 3
  • Bit 6 is moved to bit 7
  • Bit 7 is moved to bit 5

For convenience, here are three other representations of the permutation. As a cycle:

(02467531)

As a mapping:

57361402 -> 76543210 -> 64725031

And as a list of pairs of the mapping:

[[0,2], [1,0], [2,4], [3,1], [4,6], [5,3], [6,7], [7,5]]

After 8 weavings, the byte is essentially reset.

For example, weaving the number 10011101 (which is 157 in base 10) will produce 01110110 (which is 118 in base 10).

Input

There are only 256 valid inputs, namely all the integers between 0 and 255 inclusive. That may be taken in any base, but it must be consistent and you must specify it if the base you choose is not base ten.

You may not zero-pad your inputs.

Output

You should output the result of the bit weaving, in any base, which must also be consistent and specified if not base ten.

You may zero-pad your outputs.


Related: Visualize Bit Weaving

Leaky Nun

Posted 2016-06-29T13:10:47.410

Reputation: 45 011

5Fun fact: this is the challenge I wanted to post originally. Then I drew up the ASCII art to visualise the permutation, and then Sp3000 suggested that rendering that would make a better challenge. ;) – Martin Ender – 2016-06-29T13:13:30.160

2Can output base be different from input base? When you say "consistent" I understand that as "every possible input in the same base" – Luis Mendo – 2016-06-29T14:03:19.430

I think that the representation as a cycle would be more useful than the mapping representation. – mbomb007 – 2016-06-29T14:07:04.127

I have to say the ASCII art is definitely more fun. – Insane – 2016-06-29T19:32:22.340

2This could really use some more test cases. – James – 2016-06-29T23:22:04.257

Would taking input as a singleton list (i.e. [1] in Python instead of 1) be acceptable? – Mego – 2016-06-30T04:44:49.623

@Mego I don't like trick questions but yes. – Leaky Nun – 2016-06-30T10:00:36.330

@LuisMendo Yes, and yes. – Leaky Nun – 2016-06-30T10:01:30.087

Where it says, "You may not zero-pad your inputs," that means 00000001 is invalid (should be 1), correct? – Joe – 2016-07-22T21:08:56.793

@SirBidenXVII Correct. – Leaky Nun – 2016-07-23T00:29:09.460

Answers

32

Python 2.7, 44 -> 36 bytes

lambda x:x/4&42|x*2&128|x*4&84|x/2&1

Arfie

Posted 2016-06-29T13:10:47.410

Reputation: 1 230

10Great first answer, welcome to PPCG! :) – Martin Ender – 2016-06-29T13:43:04.037

10If you use | instead of + and mask after shifting then you can shave 8 bytes by removing parentheses. – PellMell – 2016-06-29T15:52:40.780

Since you're new, I'll point out that you can take @PellMell's suggestion to improve your golf and then use <strike></strike> around your old byte score to indicate the progress :-) – Insane – 2016-06-30T00:20:11.653

5Crossed out 44 is still regular 44. :( – James – 2016-06-30T09:08:17.143

16

Evil, 3 characters

rew

Try it online!

Input is in base 256, (e.g. ASCII), e.g. to enter the digit 63, enter ASCII 63 which is ?.

Explanation:

r          #Read a character
 e         #Weave it
  w        #Display it

This so feels like cheating.

James

Posted 2016-06-29T13:10:47.410

Reputation: 54 537

1ASCII isn't base 256, it's base 128. What encoding is used for ordinals 128-255? Edit: It looks like it just uses the system encoding. – Mego – 2016-06-30T04:59:22.440

11

CJam, 15 12 bytes

Thanks to FryAmTheEggman for saving 3 bytes.

l8Te[m!6532=

Input in base 2. Output also in base 2, padded to 8 bits with zeros.

Test it here.

Explanation

l      e# Read the input.
8Te[   e# Left-pad it to 8 elements with zeros.
m!     e# Generate all permutations (with duplicates, i.e. treating equal elements
       e# in different positions distinctly).
6532=  e# Select the 6533rd, which happens to permute the elements like [1 3 0 5 2 7 4 6].

Martin Ender

Posted 2016-06-29T13:10:47.410

Reputation: 184 808

7

MATL, 14 bytes

&8B[2K1B3D5C])

Input is in decimal. Output is zero-padded binary.

Try it online!

Explanation

&8B         % Take input number implicitly. Convert to binary array with 8 digits
[2K1B3D5C]  % Push array [2 4 1 6 3 8 5 7]
)           % Index first array with second array. Implicitly display

Luis Mendo

Posted 2016-06-29T13:10:47.410

Reputation: 87 464

7

Jelly, 11 bytes

+⁹BḊŒ!6533ị

Translation of Martin’s CJam answer. Try it here.

+⁹BḊ          Translate (x+256) to binary and chop off the MSB.
              This essentially zero-pads the list to 8 bits.
    Œ!        Generate all permutations of this list.
      6533ị   Index the 6533rd one.

Lynn

Posted 2016-06-29T13:10:47.410

Reputation: 55 648

1I like the zero padding trick. Elegant. – trichoplax – 2016-06-30T00:26:36.170

7

JavaScript (ES6), 30 bytes

f=n=>n*4&84|n*2&128|n/2&1|n/4&42

Neil

Posted 2016-06-29T13:10:47.410

Reputation: 95 035

Nice abuse of precedence! – Leaky Nun – 2016-06-29T15:40:30.437

1Surely precedence was designed to work this way! It would even work with the bit shifts, but they're longer. – Neil – 2016-06-29T15:41:29.547

6

J, 12 bytes

6532 A._8&{.

Uses the permute builtin A. with permutation index 6532 which corresponds to the bit-weaving operation.

Usage

Input is a list of binary digits. Output is a zero-padded list of 8 binary digits.

   f =: 6532 A._8&{.
   f 1 0 0 1 1 1 0 1
0 1 1 1 0 1 1 0
   f 1 1 1 0 1 1 0
1 1 0 1 1 0 0 1

Explanation

6532 A._8&{.  Input: s
       _8&{.  Takes the list 8 values from the list, filling with zeros at the front
              if the length(s) is less than 8
6532          The permutation index for bit-weaving
     A.       permute the list of digits by that index and return

miles

Posted 2016-06-29T13:10:47.410

Reputation: 15 654

6

Retina, 39 bytes

+`^(?!.{8})
0
(.)(.)
$2$1
\B(.)(.)
$2$1

Input and output in base 2, output is left-padded.

Try it online!

Explanation

+`^(?!.{8})
0

This just left-pads the input with zeros. The + indicates that this stage is repeated until the string stops changing. It matches the beginning of the string as long as there are less than 8 characters in it, and inserts a 0 in that position.

Now for the actual permutation. The straight-forward solution is this:

(.)(.)(.)(.)(.)(.)(.)(.)
$2$4$1$6$3$8$5$7

However that's painfully long and redundant. I found a different formulation of the permutation that is much easier to implement in Retina (X represents a swap of adjacent bits):

1 2 3 4 5 6 7 8
 X   X   X   X
2 1 4 3 6 5 8 7
   X   X   X
2 4 1 6 3 8 5 7

Now that's much easier to implement:

(.)(.)
$2$1

This simply matches two characters and swaps them. Since matches don't overlap, this swaps all four pairs.

\B(.)(.)
$2$1

Now we want to do the same thing again, but we want to skip the first character. The easiest way to do so is to require that the match doesn't start at a word boundary with \B.

Martin Ender

Posted 2016-06-29T13:10:47.410

Reputation: 184 808

6

x86 machine code, 20 bytes

In hex:

89C22455C1E002D0E0D1E880E2AAC0EA0211D0C3

It's a procedure taking input and returning result via AL register

Disassembly

89 c2                   mov    edx,eax
24 55                   and    al,0x55  ;Clear odd bits
c1 e0 02                shl    eax,0x2  ;Shift left, bit 6 goes to AH...
d0 e0                   shl    al,1     ;...and doesn't affected by this shift
d1 e8                   shr    eax,1    ;Shift bits to their's target positions
80 e2 aa                and    dl,0xaa  ;Clear even bits
c0 ea 02                shr    dl,0x2   ;Shift right, bit 1 goes to CF
11 d0                   adc    eax,edx  ;EAX=EAX+EDX+CF
c3                      ret

meden

Posted 2016-06-29T13:10:47.410

Reputation: 711

5

C (unsafe macro), 39 bytes

#define w(v)v*4&84|v*2&128|v/2&1|v/4&42

C (function), 41 bytes

w(v){return v*4&84|v*2&128|v/2&1|v/4&42;}

C (full program), 59 bytes

main(v){scanf("%d",&v);return v*4&84|v*2&128|v/2&1|v/4&42;}

(returns via exit code, so invoke with echo "157" | ./weave;echo $?)

C (standards-compliant full program), 86 bytes

#include<stdio.h>
int main(){int v;scanf("%d",&v);return v*4&84|v*2&128|v/2&1|v/4&42;}

C (standards-compliant full program with no compiler warnings), 95 bytes

#include<stdio.h>
int main(){int v;scanf("%d",&v);return (v*4&84)|(v*2&128)|(v/2&1)|(v/4&42);}

C (standards-compliant full program with no compiler warnings which can read from arguments or stdin and includes error/range checking), 262 bytes

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int v,char**p){v=v<2?isatty(0)&&puts("Value?"),scanf("%d",&v)?v:-1:strtol(p[1],p,10);exit(*p==p[1]||v&255^v?fprintf(stderr,"Invalid value\n"):!printf("%d\n",(v*4&84)|(v*2&128)|(v/2&1)|(v/4&42)));}

Breakdown

Pretty much the same as a lot of existing answers: bit-shift all the bits into place by using <<2 (*4), <<1 (*2), >>1 (/2) and >>2 (/4), then | it all together.

The rest is nothing but different flavours of boiler-plate.

Dave

Posted 2016-06-29T13:10:47.410

Reputation: 7 519

4

Mathematica, 34 bytes

PadLeft[#,8][[{2,4,1,6,3,8,5,7}]]&

Anonymous function. Takes a list of binary digits, and outputs a padded list of 8 binary digits.

LegionMammal978

Posted 2016-06-29T13:10:47.410

Reputation: 15 731

3

Matlab, 49 48 44 bytes

s=sprintf('%08s',input(''));s('24163857'-48)

Takes input as string of binary values. Output padded. 4 bytes saved thanks to @Luis Mendo.

Explanation:

input('')             -- takes input
s=sprintf('%08s',...) -- pads with zeros to obtain 8 digits
s('24163857'-48)      -- takes positions [2 4 1 6 3 8 5 7] from s (48 is code for '0')

pajonk

Posted 2016-06-29T13:10:47.410

Reputation: 2 480

3

05AB1E, 14 12 bytes

žz+b¦œ6532èJ

Explanation

žz+b¦           # convert to binary padded with 0's to 8 digits
     œ6532è     # get the 6532th permutation of the binary number
           J    # join and implicitly print

Input is in base 10.
Output is in base 2.

Borrows the permutation trick from MartinEnder's CJam answer

Try it online

Emigna

Posted 2016-06-29T13:10:47.410

Reputation: 50 798

3

PowerShell v2+, 34 bytes

("{0:D8}"-f$args)[1,3,0,5,2,7,4,6]

Translation of @LegionMammal978's answer. Full program. Takes input via command-line argument as a binary number, outputs as a binary array, zero-padded.

The "{0:D8}"-f portion uses standard numeric format strings to prepend 0 to the input $args. Since the -f operator supports taking an array as input, and we've explicitly said to use the first element {0:, we don't need to do the usual $args[0]. We encapsulate that string in parens, then index into it [1,3,0,5,2,7,4,6] with the weaving. The resultant array is left on the pipeline and output is implicit.

Examples

(the default .ToString() for an array has the separator as `n, so that's why the output is newline separated here)

PS C:\Tools\Scripts\golfing> .\golf-bit-weaving.ps1 10011101
0
1
1
1
0
1
1
0

PS C:\Tools\Scripts\golfing> .\golf-bit-weaving.ps1 1111
0
0
0
1
0
1
1
1

AdmBorkBork

Posted 2016-06-29T13:10:47.410

Reputation: 41 581

3

V, 17 bytes

8é0$7hd|òxplò2|@q

Try it online!

This takes input and output in binary. Most of the byte count comes from padding it with 0's. If padding the input was allowed, we could just do:

òxplò2|@q

Thanks to Martin's solution for the method of swapping characters, e.g:

1 2 3 4 5 6 7 8
 X   X   X   X
2 1 4 3 6 5 8 7
   X   X   X
2 4 1 6 3 8 5 7

Explanation:

8é0                 "Insert 8 '0' characters
   $                "Move to the end of the current line
    7h              "Move 7 characters back
      d|            "Delete until the first character
        ò   ò       "Recursively:
         xp         "Swap 2 characters
           l        "And move to the right
             2|     "Move to the second column
               @q   "And repeat our last recursive command.

James

Posted 2016-06-29T13:10:47.410

Reputation: 54 537

2

Labyrinth, 27 26 bytes

_1@
&,)}}}=}}=}}=}!{!!{{!"

Input and output in base 2. Output is padded.

Try it online!

Martin Ender

Posted 2016-06-29T13:10:47.410

Reputation: 184 808

2

Pyth, 19 characters

s[@z1.it%2tzP%2z@z6

Input and output are base 2.

Far from a Pyth expert, but since no one else has answered with it yet I gave it a shot.

Explanation:

s[                # combine the 3 parts to a collection and then join them
  @z1             # bit 1 goes to bit 0
  .i              # interleave the next two collections
    t%2tz         # bits 3,5,7; t is used before z to offset the index by 1
    P%2z          # bits 0,2,4
  @z6             # bit 6 goes to bit 7

Drowrin

Posted 2016-06-29T13:10:47.410

Reputation: 21

This is invalid as this assumed a zero-padded input. – Leaky Nun – 2016-07-23T01:10:03.390

2

UGL, 50 bytes

cuuRir/r/r/r/r/r/r/%@@%@@%@@%@@@%@@%@@%@@@oooooooo

Try it online!

Repeatedly div-mod by 2, and then % swap and @ roll to get them in the right order.

Input in base-ten, output in base-two.

Leaky Nun

Posted 2016-06-29T13:10:47.410

Reputation: 45 011

1

vi, 27 bytes

8I0<ESC>$7hc0lxp<ESC>l"qd0xp3@q03@q

Where <ESC> represents the Escape character. I/O is in binary, output is padded. 24 bytes in vim:

8I0<ESC>$7hd0xpqqlxpq2@q03@q

Neil

Posted 2016-06-29T13:10:47.410

Reputation: 95 035

<ESC> needs backticks around it. I'd edit, but I can't figure out 4 more bytes to change... – Joe – 2016-07-22T20:45:43.523

@SirBidenXVII Thanks, fixed. – Neil – 2016-07-22T23:23:16.433

0

Actually, 27 bytes

'08*+7~@tñiWi┐W13052746k♂└Σ

Try it online!

This program does input and output as a binary string (output is zero-padded to 8 bits).

Explanation:

'08*+7~@tñiWi┐W13052746k♂└Σ
'08*+                        prepend 8 zeroes
     7~@t                    last 8 characters (a[:~7])
         ñi                  enumerate, flatten
           Wi┐W              for each (i, v) pair: push v to register i
               13052746k     push [1,3,0,5,2,7,4,6] (the permutation order, zero-indexed)
                        ♂└   for each value: push the value in that register
                          Σ  concatenate the strings

Mego

Posted 2016-06-29T13:10:47.410

Reputation: 32 998

0

JavaScript, 98 Bytes

Input is taken in base-2 as a string, output is also base-2 as a string

n=>(n.length<8?n="0".repeat(8-n.length)+n:0,a="13052746",t=n,n.split``.map((e,i)=>t[a[i]]).join``)

Davis

Posted 2016-06-29T13:10:47.410

Reputation: 131