Ruby: What Does the Snippet: (Num & 1) == 0 Exactly Do

Ruby: What does the snippet: (num & 1) == 0 exactly do?

& is a bitwise AND operator. Doing (num & 1) checks if the last bit (least significant bit) of the number is set. If it is set, the number is odd, and if it is not set, it is even.

It is just a fast way to check if a number is even or odd.

You can see a list of the ruby bitwise operators here: http://www.techotopia.com/index.php/Ruby_Operators#Ruby_Bitwise_Operators

Why does my method predefine the argument `(num=nil)`?

Whenever you define a method in Ruby, you can make it have arguments. When the method is called, the arguments are replaced by objects of your choosing. When you define an argument in the method definition, it becomes the default value.

For example, if you simply call my_count in a program, it will automatically choose num to be nil, since no argument was explicitly provided. Otherwise, if you called my_count(5), then num in the method will be 5.

Here is another example, with the default value as an empty hash. I will create two Server objects:

class Server
attr_accessor :name
attr_accessor :files

def initialize(name, files={})
@name = name
@files = files
end
end

# Supply hash of files
Server.new('hostname', {'filename' => '2015-08-21 13:49 -4000'})

# New server will have no files -- empty hash
Server.new('hostname')

Let's change the initialize method and create one last server:

class Server
attr_accessor :name
attr_accessor :files

def initialize(name, files) # No default value for files
@name = name
@files = files
end
end

Server.new('hostname', 'path/to/files/')
# => ArgumentError: wrong number of arguments (1 for 2)

In the modified class, I only supplied 1 argument, the name. Because files no longer has a default value, then not including the argument raises an error. To clarify, omitting an argument is only allowed when the method definition has a default value for the argument. Without a default value, nothing will be used (not nil, 0, or ''), and the program will stop/crash -- an error has been raised/encountered.

It is possible to create a method without arguments. Here is an example using String#length. You will see that .length does not take an argument, and instead works on the string.

string = 'Hello, world!'
string.length
# => 13

Bit flags operation

The spec should list the available flags and you can then just use the individual bits to toggle them on/off.

For instance the Python ssl module has multiple constants that we can use to change some options (flags).

Let's see if TLS version 1.0 option is enabled:

>>> import ssl
>>> ctx = ssl.create_default_context()
>>> bin(ctx.options)
'0b10000010010100100000000001010100'
>>> int(ssl.PROTOCOL_TLSv1)
3
>>> bin(ssl.PROTOCOL_TLSv1)
'0b11'
>>> bool(ctx.options & ssl.PROTOCOL_TLSv1)
False

We can see that the first two bits (3 in decimal) are not set and therefore this option is not enabled so let's enable it:

>>> ctx.options |= ssl.PROTOCOL_TLSv1
>>> bin(ctx.options)
'0b10000010010100100000000001010111'
>>> bool(ctx.options & ssl.PROTOCOL_TLSv1)
True

I guess this has a similar purpose in your case.

Ruby: difference between &= and &&=

Try the following:

x = 5
x |= 2
=> 7

|= and &= are equivalent to the bitwise x = x | 2 and x = x & 2

vs

x = 5
x ||= 2
=> 5

In the second statement, x ||= 2, it means x = 2 if x is nil, otherwise it's x.
( x = (x || 2) ; the expression x || 2 returns x if x is anything but nil otherwise it returns 2.

x ||= 'foo' is actually very common in Ruby (set x to foo is x is not already set)

x = (x & 3) (which is equivalent to x &= 3), returns 3 (the second operand) unless x is 0, it returns 0)
)

The same logic applies for & but it was easier to find an example on the top of my mind for |

=)

Ruby unfamiliar string usage with Integer.chr and \001

To make the code work in Ruby 1.9, try changing that line to:

flag = @data[2].ord & 2

Prior to Ruby 1.9, str[n] would return an integer between 0 and 255, but in Ruby 1.9 with its new unicode support, str[n] returns a character (string of length 1). To get the integer instead of character, you can call .ord on the character.

The & operator is just the standard bitwise AND operator common to C, Ruby, and many other languages.

Byte number three (0x03) is not a printable ASCII character, so when you have that byte in a string and call inspect ruby denotes that byte as \003. Just make sure you understand that "\003" is a single-byte string while '\003' is a four-byte string.

In Ruby, strings are really sequences of bytes. In Ruby 1.9, there is also encoding information, but they are still really just a sequence of bytes.

Why do these two snippets produce different results?

I figured out the problem. It's an error in my ruby code.

MEMO = Array.new(10, Array.new(10, Array.new(21, 0)))

If you were to print out the object ids of MEMO[0] and MEMO[1] you would find that they are the exact same. What I assumed Array.new(10, Array.new) would do is create an Array with 10 different Array objects inside of it. Instead it creates an Array of 10 references to the same Array object.
By changing the first line to something like this:

MEMO = Array.new
10.times do
MEMO << Array.new
10.times do
MEMO[-1] << Array.new(21, 0)
end
end

or even simpler

MEMO = Array.new(10) {Array.new(10) {Array.new(21) {0}}}

It works perfectly fine.

Why does adding 1 to a recursive proc call return the count of calls made?

I just added some puts to your code, maybe it helps to follow the logic better than I can explain with my english.

So, this is the tweaked code:

def rcall(num)
if 10 == num
rec = 0
puts "rec = #{rec} ---- End of recursion"
return rec
end
rec = rcall(num - 1)
res = 1 + rec
puts "rec = #{rec} \t\t res = i + rec = #{res}"
res
end

When you call on 15 for example, you get:
rcall(15)

# rec = 0 ---- End of recursion
# rec = 0 res = i + rec = 1
# rec = 1 res = i + rec = 2
# rec = 2 res = i + rec = 3
# rec = 3 res = i + rec = 4
# rec = 4 res = i + rec = 5
# 5

If you call on a number less than 10, you never reach the end of the recursion, so no value is returned to build back the "call stack" and the error is raised: stack level too deep (SystemStackError)


Other languages supports recursion, for example Python. Here on famous Fibonacci (How to write the Fibonacci Sequence?).

I also want to share this Computerphile video about recursion on YouTube: https://youtu.be/Mv9NEXX1VHc



Related Topics



Leave a reply



Submit