Bit Manipulator/Reader

4

1

Introduction

There are often times that we have challenges which require communication of some sort (such as in team KOTH), where density of information may be more important than density of code. There are a number of compression techniques that can allow us to convey more information in less space, but for simple data flags, sometimes flipping bits themselves can be a great way to achieve desired data density.

Challenge

Write a program or function in the language of your choice that can take an integer to be manipulated (must handle at least 32 bit), a start bit position (integer), a number of bits to manipulate (integer), and a manipulation mode (integer), and returns the original integer manipulated in the way specified below. In addition, write a second program or function that serves as a bit reader, taking in an integer, a start bit position (integer), and a number of bits to read (integer), and returns an integer consisting of just that group of bits shifted down, and every other bit as 0.

Some further details and rules are as follows:

  • The first argument will be an integer, signed or unsigned.
  • The second argument will be the bit position to start from (counting from least significant bit, zero-indexed).
  • The third argument will be the number of bits to be read/manipulated, moving up in bit significance from the start bit. If not given as an argument, the value should default to 1.
  • The fourth argument (manipulator only) will be the manipulation mode:
    • When passed a 0 or null value, the behavior will be to flip (xor) all of the specified bits (default if no value given).
    • When passed a positive value, the behavior will be to set all of the specified bits to 1.
    • When passed a negative value, the behavior will be to set all of the specified bits to 0.
  • The return value of the manipulator function should be the initial integer with the above bit manipulations applied.
  • The return value of the reader function should be the start bit shifted to the least significant bit, and every bit beyond the length of bits set to 0.
  • Assume that only valid input will be used. Don't worry about error handling.

The winner will be determined by the shortest sum of the length of both programs/functions. They will be selected in at least 7 days, or if/when there have been enough submissions. In the event of a tie, the answer that came earlier wins.

Examples

Here's a few examples of input and output that your code should be able to handle. I've golfed both functions in JavaScript that I can release if people want to test their results, but otherwise I'll probably wait a few days before I post it up.

Manipulator

F(0, 2) => 4 (0 => 100)

F(4, 2) => 0 (100 => 0)

F(0, 2, 4) => 60 (0 => 111100)

F(170, 2, 4, 0) => 150 (10101010 => 10010110)

F(170, 2, 4, 1) => 190 (10101010 => 10111110)

F(170, 2, 4, -1) => 130 (10101010 => 10000010)

F(0, 31) => (+/-)2147483648 (0 => 10000000000000000000000000000000)

Reader

F(0, 2) => 0 (0 => 0)

F(4, 2) => 1 (100 => 1)

F(60, 2, 4) => 15 (111100 => 1111)

F(170, 2, 4) => 10 (10101010 => 1010)

F((+/-)2147483648, 0, 32) => (+/-)2147483648 (10000000000000000000000000000000 => 10000000000000000000000000000000)

Mwr247

Posted 2016-03-01T16:43:50.413

Reputation: 3 494

What if a language doesn't support optional function arguments? – Zgarb – 2016-03-01T16:46:07.220

@Zgarg Then you can pass in the default values 1 and 0, respectively. – Mwr247 – 2016-03-01T16:47:56.053

Ok, thanks. Also, can we have shared code between the two functions, and can one of them use the other in its definition? – Zgarb – 2016-03-01T16:48:52.770

@Zgarb I'll allow that, so long as they are still called as specified. Your function can reference another function, and your program can reference another program, but all of the code used must be summed up in the end. – Mwr247 – 2016-03-01T16:54:11.953

1You should add some test cases that use 32-bit integers, since that it the requirement. – mbomb007 – 2016-03-01T21:19:38.573

@mbomb007 Good point. Added some simple cases to just ensure they work at that level. Thanks! – Mwr247 – 2016-03-04T17:48:44.227

Answers

4

JavaScript (ES6), 75 bytes

Saved 4 bytes thanks to @Mwr247

Manipulator: (47 bytes)

(a,b,c=1,d=0,z=(1<<c)-1<<b)=>d?d<0?a&~z:a|z:a^z

Reader: (28 bytes)

(a,b,c=1)=>a>>b&(1<<c-1)*2-1

How it works

Manipulator

The first thing we need to do is figure out the number that has c bits set, starting at the bth bit. Possibly the best way to do this is z=(1<<c)-1<<b, which works like so:

b  c    1<<c     -1     <<b    z
2  1      10     01    0100    4
2  2     100    011   01100   12
2  3    1000   0111  011100   28
1  4   10000  01111  011110   30

Now we take into account d. For case 0, we flip the bits with a^z; for case 1, we set the bits to 1 with a|z; for case -1, we set the bits to 0 with a&~z.

ETHproductions

Posted 2016-03-01T16:43:50.413

Reputation: 47 880

Did you peek at my computer? Because that's almost exactly the code I had, down to the variable names XD Very nice! – Mwr247 – 2016-03-01T17:10:16.360

2@Mwr247 Haha! I guess this is another instance of great minds thinking alike :) – ETHproductions – 2016-03-01T17:11:12.110

You can actually save 4 bytes on the manipulator with z=(1<<c)-1<<b – Mwr247 – 2016-03-01T17:17:52.817

@Mwr247 Wow, that helps a lot, thanks! – ETHproductions – 2016-03-01T17:21:40.510

@mbomb007 Thanks, I had just messed up the decimal translations of those numbers. – ETHproductions – 2016-03-01T20:28:04.783

Just tested the 32 bit cases I just added, and your reader function doesn't work quite right. This seems to work correctly though (haven't tried shortening further): (a,b,c=1)=>a>>b&(1<<(c-1))*2-1 – Mwr247 – 2016-03-04T17:47:18.023

This would be the winning submission, but the reader is still wrong. See above. – Mwr247 – 2016-03-08T16:45:31.067

@Mwr247 Thanks, fixed. It's a bummer that JS's 32-bit type only really works with 31-bit integers (the top bit is sign, I think)... – ETHproductions – 2016-03-08T16:53:54.857

3

Python 2, 89 bytes

Done in a method similar to ETH. Python lambdas aren't as short as in JS. Also, default parameter values can't depend on other parameters.

Manipulator, 63 bytes

def f(a,b,c=1,d=0):
    z=2**c-1<<b;return[a^z,a|z,a&~z][cmp(d,0)]

Reader, 26 bytes

lambda a,b,c=1:a>>b&2**c-1

Try it online

mbomb007

Posted 2016-03-01T16:43:50.413

Reputation: 21 944

2I was in the midst of trying to figure out where my Python 2.7 was installed when you posted the online testing, thanks ;) Looks good! – Mwr247 – 2016-03-01T20:18:59.610