I initially treated ‘10000’ as an array of 1s and 0s and wrote a function to recursively come up with the above combinations before it was pointed out to me that it’d be much easier to use bit wise logic instead.

I don’t remember every having to write any code using bit wise operations since university so I thought I’d document what I learnt.

The first thing to do is convert those binary values into a decimal equivalent which is pretty easy in Ruby:

Binary XOR Operator copies the bit if it is set in one operand but not both.

'10000' XOR '10000'

In Ruby it would read like this:

>16 ^ 16=>0

If we do the same XOR operation but changing the other bits instead we end up with all the neighbours of distance 1:

>[0,1,2,4,16].map{|x|16 ^ x }=>[16, 17, 18, 20, 0]

We can generalise the function that creates that array of values like so:

> bits = 5> offsets = (0..(bits -1)).map{|x|2** x }=>[1, 2, 4, 8, 16]

or if we want to use bit shifting:

> offsets = (0..(bits -1)).map{|x|1<< x }=>[1, 2, 4, 8, 16]

With that approach we’re moving the “left operands value is moved left by the number of bits specified by the right operand.” i.e. we move ‘1’ left by 0 bits (from ‘1’to ‘1’), then by 1 bit (from ‘1’ to ’10’), then by 2 bits (from ‘1’ to ‘100’) and so on.

We still need to get all the neighbours which differ by 2 bits which we can do by getting all the ways that we can combine those offsets together. The combination function and Bitwise or do the trick here:

I asked on the #haskell.au IRC group and got another approach to converting binary to int (from m3ga). Need to import Numeric, Data.Char, and Data.Maybe (if you want to handle errors with Maybe, otherwise can use non-total list functions like `head`).

The `2` is the base we want, and the next arg is whether we want to parse a character. That gives us [(Int, String)], where the String is any unparsed characters. We can convert this to a Maybe Int with: