Ruby: Flip characters bits - ruby

I am simply trying to flip the bits of a character. I can get it into a binary form, but when xoring that data with 0xff it seems to not be giving me what I want.
bin = "a".unpack("b*")[0].to_i # Will give me the binary value (10000110)
flip = bin ^ 0xff # this will give me 9999889, expecting (01111001)
Finally, I want to re-pack it as a "character"...
Any help would be appreciated.

You need to tell Ruby that the unpacked string is binary:
bin = "a".unpack("b*")[0].to_i(2) # => 134
flip = bin ^ 0xff # => 121
flip.to_s(2) # => "1111001"
[flip.to_s(2)].pack("b*") # => "O"

Couple of things:
You probably want unpack('B*'), not b* as b* gives you LSB first.
You probably don't need binary at all ("binary" is just a representation of a number, it doesn't need to be "a binary number" in order to XOR it). So you can do simply:
number = "a".unpack('C*')[0]
flip = number ^ 0xff
new_number = [flip].pack('C*')
or, even:
number = "a".ord
flip = number ^ 0xff
new_number = flip.chr
Oh, and the result should not be "O"

Related

Generating unique non-similar codes with validation

I know there are similar questions so please bear with me.
I wish to generate approximately 50K codes for people to place orders - ideally no longer than 10 chars and can include letters and digits. They are not discount codes so I am not worried about people trying to guess codes. What I am worried about is somebody accidentally entering a wrong digit (ie 1 instead of l or 0 instead of O) and then the system will fail if by chance it is also a valid code.
As the codes are constantly being generated, ideally I don't want a table look-up validation, but an formula (eg if it contains an A the number element should be divisable by 13 or some such).
Select some alphabet (made of digits and letters) of size B such that there are no easy confusions. Assign every symbol a value from 0 to B-1, preferably in random order. Now you can use sequential integers, convert them to base B and assign the symbols accordingly.
For improved safety, you can append one or two checksum symbols for error detection.
With N=34 (ten digits and twenty four letters 9ABHC0FVW3YGJKL1N2456XRTS78DMPQEUZ), 50K codes require codes of length only four.
If you don't want the generated codes to be consecutive, you can scramble the bits before the change of base.
Before you start generating random combinations of characters, there are a couple of things you need to bear in mind:
1. Profanity
If your codes include every possible combination of four letters from the alphabet, they will inevitably include every four-letter word. You need to be absolutely sure that you never ask customers to enter anything foul or offensive.
2. Human error
People often make mistakes when entering codes. Confusing similar characters like O and 0 is only part of the problem. Other common mistakes include transposing adjacent characters (e.g. the → teh) and hitting the wrong key on the keyboard (e.g., and → amd)
To avoid these issues, I would recommend that you generate codes from a restricted alphabet that has no possibility of spelling out anything unfortunate, and use the Luhn algorithm or something similar to catch accidental data entry errors.
For example, here's some Python code that generates hexadecimal codes using an alphabet of 16 characters with no vowels. It uses a linear congruential generator step to avoid outputting sequential numbers, and includes a base-16 Luhn checksum to detect input errors. The code2int() function will return −1 if the checksum is incorrect. Otherwise it will return an integer. If this integer is less than your maximum input value (e.g., 50,000), then you can assume the code is correct.
def int2code(n):
# Generates a 7-character code from an integer value (n > 0)
alph = 'BCDFGHJKMNPRTWXZ'
mod = 0xfffffd # Highest 24-bit prime
mul = 0xc36572 # Randomly selected multiplier
add = 0x5d48ca # Randomly selected addend
# Convert the input number `n` into a non-sequential 6-digit
# hexadecimal code by means of a linear congruential generator
c = "%06x" % ((n * mul + add) % mod)
# Replace each hex digit with the corresponding character from alph.
# and generate a base-16 Luhn checksum at the same time
luhn_sum = 0
code = ''
for i in range(6):
d = int(c[i], 16)
code += alph[d]
if i % 2 == 1:
t = d * 15
luhn_sum += (t & 0x0f) + (t >> 4)
else:
luhn_sum += d
# Append the checksum
checksum = (16 - (luhn_sum % 16)) % 16
code += alph[checksum]
return code
def code2int(code):
# Converts a 7-character code back into an integer value
# Returns -1 if the input is invalid
alph = 'BCDFGHJKMNPRTWXZ'
mod = 0xfffffd # Highest 24-bit prime
inv = 0x111548 # Modular multiplicative inverse of 0xc36572
sub = 0xa2b733 # = 0xfffffd - 0x5d48ca
if len(code) != 7:
return -1
# Treating each character as a hex digit, convert the code back into
# an integer value. Also make sure the Luhn checksum is correct
luhn_sum = 0
c = 0
for i in range(7):
if code[i] not in alph:
return -1
d = alph.index(code[i])
c = c * 16 + d
if i % 2 == 1:
t = d * 15
luhn_sum += (t & 0x0f) + (t >> 4)
else:
luhn_sum += d
if luhn_sum % 16 != 0:
return -1
# Discard the last digit (corresponding to the Luhn checksum), and undo
# the LCG calculation to retrieve the original input value
c = (((c >> 4) + sub) * inv) % mod
return c
# Test
>>> print('\n'.join([int2code(i) for i in range(10)]))
HWGMTPX
DBPXFZF
XGCFRCN
PKKNDJB
JPWXNRK
DXGGCBR
ZCPNMDD
RHBXZKN
KMKGJTZ
FRWNXCH
>>> print(all([code2int(int2code(i)) == i for i in range(50000)]))
True

Generating random number of length 6 with SecureRandom in Ruby

I tried SecureRandom.random_number(9**6) but it sometimes returns 5 and sometimes 6 numbers. I'd want it to be a length of 6 consistently. I would also prefer it in the format like SecureRandom.random_number(9**6) without using syntax like 6.times.map so that it's easier to be stubbed in my controller test.
You can do it with math:
(SecureRandom.random_number(9e5) + 1e5).to_i
Then verify:
100000.times.map do
(SecureRandom.random_number(9e5) + 1e5).to_i
end.map { |v| v.to_s.length }.uniq
# => [6]
This produces values in the range 100000..999999:
10000000.times.map do
(SecureRandom.random_number(9e5) + 1e5).to_i
end.minmax
# => [100000, 999999]
If you need this in a more concise format, just roll it into a method:
def six_digit_rand
(SecureRandom.random_number(9e5) + 1e5).to_i
end
To generate a random, 6-digit string:
# This generates a 6-digit string, where the
# minimum possible value is "000000", and the
# maximum possible value is "999999"
SecureRandom.random_number(10**6).to_s.rjust(6, '0')
Here's more detail of what's happening, shown by breaking the single line into multiple lines with explaining variables:
# Calculate the upper bound for the random number generator
# upper_bound = 1,000,000
upper_bound = 10**6
# n will be an integer with a minimum possible value of 0,
# and a maximum possible value of 999,999
n = SecureRandom.random_number(upper_bound)
# Convert the integer n to a string
# unpadded_str will be "0" if n == 0
# unpadded_str will be "999999" if n == 999999
unpadded_str = n.to_s
# Pad the string with leading zeroes if it is less than
# 6 digits long.
# "0" would be padded to "000000"
# "123" would be padded to "000123"
# "999999" would not be padded, and remains unchanged as "999999"
padded_str = unpadded_str.rjust(6, '0')
Docs to Ruby SecureRand, lot of cool tricks here.
Specific to this question I would say: (SecureRandom.random_number * 1000000).to_i
Docs: random_number(n=0)
If 0 is given or an argument is not given, ::random_number returns a float: 0.0 <= ::random_number < 1.0.
Then multiply by 6 decimal places (* 1000000) and truncate the decimals (.to_i)
If letters are okay, I prefer .hex:
SecureRandom.hex(3) #=> "e15b05"
Docs:
hex(n=nil)
::hex generates a random hexadecimal string.
The argument n specifies the length, in bytes, of the random number to
be generated. The length of the resulting hexadecimal string is twice
n.
If n is not specified or is nil, 16 is assumed. It may be larger in
future.
The result may contain 0-9 and a-f.
Other options:
SecureRandom.uuid #=> "3f780c86-6897-457e-9d0b-ef3963fbc0a8"
SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
For Rails apps creating a barcode or uid with an object you can do something like this in the object model file:
before_create :generate_barcode
def generate_barcode
begin
return if self.barcode.present?
self.barcode = SecureRandom.hex.upcase
end while self.class.exists?(barcode: barcode)
end
SecureRandom.random_number(n) gives a random value between 0 to n. You can achieve it using rand function.
2.3.1 :025 > rand(10**5..10**6-1)
=> 742840
rand(a..b) gives a random number between a and b. Here, you always get a 6 digit random number between 10^5 and 10^6-1.

Ruby bitwise xor 2 same length ascii string

I am trying to do bitwise xor 2 ASCII strings of the same length in ruby. I have come to the following:
'A'.unpack('B*').zip('B'.unpack('B*')).map{|a, b| (a.to_i ^ b.to_i).to_s}.pack('b*')
=> "\003"
It works. However, when performing string of 2 or more chars, it behaves wierdly, i think because of the value is too big for Fixnum, see below:
'AA'.unpack('B*').zip('BB'.unpack('B*')).map{|a, b| (a.to_i ^ b.to_i).to_s}.pack('b*')
=> "_\003"
If I stop right after the xor, without the to_s part, I see that it is not doing the bitwise XOR correctly:
'AA'.unpack('B*').zip('BB'.unpack('B*')).map{|a, b| (a.to_i ^ b.to_i)}
=> [1515925259]
Can someone help? Or can someone suggest another way of doing this?
Many thanks
I think you want to unpack with C (8-bit unsigned) rather than B (bit string) since the xor operator ^ operates on numbers rather than strings:
'AA'.unpack('C*').zip('BB'.unpack('C*')).map { |a,b| a^b }.pack('C*')
# => "\x03\x03"
3 is what one would expect from xoring 65 ('A') with 66 ('B').

How to store a 64 bit integer in two 32 bit integers in Ruby

As the title says, I'm a little lost on how to accomplish this in Ruby...there are number of topics on how to do this in C or C++. Any ruby experts out there that can chime in on this?
The same syntax you'd use in C works in ruby, just drop the typecasts:
n = 0xFFFFFFFFEEEEEEEE
x = (n & 0xFFFFFFFF00000000) >> 32
y = n & 0xFFFFFFFF
puts x.to_s(16)
# => "ffffffff"
puts y.to_s(16)
# => "eeeeeeee"
v = x << 32 | y
puts v.to_s(16)
# => "ffffffffeeeeeeee"
If you need the values to be in chunks of exactly 32 bits (i.e. you need to speak binary to some external data file or program), then you'll want to use Array#pack and String#unpack to get the right bits.
one 64bit integer is not equal to two 32bit integers.
http://en.wikipedia.org/wiki/Integer_(computer_science)

Calculate the parity of a byte in Ruby

What's the best way to calculate if a byte has odd or even parity in Ruby? I've got a version working:
result = "AB".to_i(16).to_s(2).count('1').odd?
=> true
Converting a number to a string and counting the "1"s seems a poor way of calculating parity though. Any better methods?
I want to be able to calculate the parity of a 3DES key. Eventually, I'll want to convert even bytes to odd.
Thanks,
Dan
Unless what you have is not fast enough, keep it. It's clear and succinct, and its performance is better than you think.
We'll benchmark everything against array lookup, the fastest method I tested:
ODD_PARITY = [
false,
true,
true,
...
true,
false,
]
def odd_parity?(hex_string)
ODD_PARITY[hex_string.to_i(16)]
end
Array lookup computes the parity at a rate of 640,000 bytes per second.
Bowsersenior's C code computes parity at a rate of 640,000 bytes per second.
Your code computes parity at a rate of 284,000 bytes per second.
Bowsersenior's native code computes parity at a rate of 171,000 bytes per second.
Theo's shortened code computes parity at a rate of 128,000 bytes per second.
Have you taken a look at the RubyDES library? That may remove the need to write your own implementation.
To calculate parity, you can use something like the following:
require 'rubygems'
require 'inline' # RubyInline (install with `gem install RubyInline`)
class Fixnum
# native ruby version: simpler but slow
# algorithm from:
# http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
def parity_native
(((self * 0x0101010101010101) & 0x8040201008040201) % 0x1FF) & 1
end
class << self
# inline c version using RubyInline to create c extension
# 4-5 times faster than native version
# use as class method:
# Fixnum.parity(0xAB)
inline :C do |builder|
builder.c <<-EOC
int parity_c(int num) {
return (
((num * 0x0101010101010101ULL) & 0x8040201008040201ULL) % 0x1FF
) & 1;
}
EOC
end
end
def parity
self.class.parity_c(self)
end
def parity_odd?
1 == parity
end
def parity_even?
0 == parity
end
end
0xAB.parity # => 1
0xAB.parity_odd? # => true
0xAB.parity_even? # => false
(0xAB + 1).parity # => 0
According to simple benchmarks, the inline c version is 3-4 times faster than the native ruby version
require 'benchmark'
n = 10000
Benchmark.bm do |x|
x.report("inline c") do
n.times do
(0..255).map{|num| num.parity}
end
end
x.report("native ruby") do
n.times do
(0..255).map{|num| num.parity_native}
end
end
end
# inline c 1.982326s
# native ruby 7.044330s
Probably a lookup table of an Array with 255 entries would be fastest "In Ruby" solution.
In C I would mask and shift. Or if I have SSE4 I would use the POPCNT instruction with inline assembler. If you need this to be high performance write a native extension in C which does either of the above.
http://en.wikipedia.org/wiki/SSE4
How about using your original solution with memoization? This will only calculate once for each integer value.
class Fixnum
# Using a class variable for simplicity, and because subclasses of
# Fixnum—while very uncommon—would likely want to share it.
##parity = ::Hash.new{ |h,i| h[i] = i.to_s(2).count('1').odd? }
def odd_parity?
##parity[self]
end
def even_parity?
!##parity[self]
end
end
"AB".to_i(16).odd_parity?
#=> true
x = 'AB'.to_i(16)
p = 0
until x == 0
p += x & 1
x = x >> 1
end
puts p # => 5
which can be shortened to
x = 'AB'.to_i(16)
p = x & 1
p += x & 1 until (x >>= 1) == 0
if you want something that is unreadable ☺
I would construct a single table of 16 entries (as a 16 character table), corresponding to each nibble (half) of a bytes. Entries are 0,1,1,2,1,2,....4
To test your byte,
Mask out the left nibble and do a lookup, memorizing the number.
Do. a shift to the right by 4 and do a second lookup, adding the result number to the previous one to provide a sum.
Then test the low order bit from the sum. If it is 1, the byte is odd, if it is a 0, the byte is even. If result is even, you flip the high order bit, using the xor instruction.
THis lookup method is much faster than adding up the bits in a byte by single shifts.
email me for a simple function to do the parity for 8 bytes. 3DES uses 3 groups of 8 bytes.

Resources