String Bit Manipulation- There and Back Again Your job is to encrypt a string using a number key.

Your program will receive 2 strings: one containing a sequence of characters to encrypt, and another one containing an even amount of digits (1-9, never 0).

The encrypting will work like this:


take the string to be encrypt and decode it to binary (ISO-8859-1)
for every pair of numbers x and y in the number string do:
for every character in the string of zeroes and ones, starting from the first one, if the bit is 0 toggle the xth bit in front of the bit you are reading right now. If the bit is 1, toggle the yth bit in front of the bit you are reading right now. If the bit to be toggled is out of bounds, do not toggle anything.


Other than that:

This is a code golf challenge, shortest code wins. Standard Loopholes apply.

Here's a more graphic explanation of what happens:

inputs: "a", "23"
"a" =BIN&gt; "01100001"
"01100001" //first bit is a 0, get the first number in the key, 2.
 - ^       //toggle the bit 2 steps in front
"01000001" //next bit is 1, get second number in the key, 3.
  -  ^     //toggle the bit 3 steps in front
"01001001" //0 bit, toggle the bit that is 2 steps in front.
   - ^
"01000001" //etc
    - ^
"01000101"
     - ^
"01000111"
      -  ^ //no change, out of bounds.
"01000111"
       -  ^
"01000111"
        -  ^
"01000111" =ASCII&gt; "G"


So: a, 23 = G. Then, running G, 23 should be a because this process is perfectly reversible. To decrypt a string encrypted using key 12438135, reverse the ordering of the pairs, 35814312 and run the encrypted string through a similar program that performs the operations in reverse order (starting at the end, approaching the beginning) using that key. (thanks to Martin Büttner for pointing that out)

Good luck and have fun! (My first challenge, tell me if i missed anything :))
Ruby, 230 191 181 178 175 173 171 159 bytes

i,n=$*
s=i.gsub(/./){|c|"%08b"%c.ord}
n.scan(/(.)(.)/){s.size.times{|i|s[j=i+(s[i]==?0?$1:$2).to_i]&amp;&amp;s[j]=s[j]==?0??1:?0}}
$&gt;&lt;&lt;s.gsub(/.{8}/){|c|c.to_i(2).chr}


It's just a very naive implementation of the spec. Input via command-line arguments, output to STDOUT.

# Read ARGV into i and n
i,n = $*
# Turn each character into a string of eight 0s and 1s using a format string.
s = i.gsub(/./){|c|"%08b"%c.ord}
# For each pair of characters in n
n.scan(/(.)(.)/){
    # For each index into s
    s.size.times{|i|
        # Determine the index that is to be toggled. $1 and $2 refer to the captures 
        # of /(.)(.)/.
        j=i+(s[i]==?0?$1:$2).to_i
        # Using short-circuiting, toggle s[j] if it isn't nil.
        s[j]&amp;&amp;s[j]=s[j]==?0??1:?0
    }
}
# Convert each group of 8 characters back to a single character and print
$&gt;&lt;&lt;s.gsub(/.{8}/){|c|c.to_i(2).chr}