rubymonk "all elements in an array are Fixnum"? - ruby

http://rubymonk.com/learning/books/1/problems/148-array_of_fixnum
Ruby monk suggests:
def array_of_fixnums?(array)
array.all? { |x| x.is_a? Fixnum }
end
That is fine and all, however the following code works in irb 1.9.2 but fails when rubymonk passes an empty array:
def array_of_fixnums?(array)
result = false
array.each { |n|
if n.is_a? Fixnum
result = true
else
result = false
end }
result
end
here is the irb output:
1.9.2-p320 :001 > array_of_fixnums? []
=> false
and here is what rubymonk says about my solution:
returns 'true' for [1,2,3] ✔
returns 'false' for ['a',1,:b] ✔
returns 'true' for []
RSpec::Expectations::ExpectationNotMetError
expected false to be true
I'm wondering why this is so?
Update based on answers:
def array_of_fixnums?(array)
result = true
array.each { |n| return false unless n.is_a? Fixnum }
result
end

Your code has two problems:
The problem is phrased in a slightly vague manner. What they actually want is for you to return false if any of the elements are not Fixnums, and true otherwise — so an empty array should give true. If you look at your code, you'll see that result starts out false, so if the array is empty, it will return false even though the test thinks it should be true. You can solve this by starting out with true.
Your code actually just detects whether the last element of the array is a Fixnum. Let's take the array [1, "nope", 3]. It will first see 1 and set result to true, then it will see "nope" and set result to false, then it will see 3 and set result to true, and that's what the method will return. RubyMonks tests actually don't detect this error, but it would show up in the real world. You want to return immediately after getting a false result, as that is enough to determine that the array is not all Fixnums.

For this case you will never enter the each cycle as there are no elements in array. So you return the defualt value of result that you set to false on the line above. However if there are no elements in an array, then all of its elements are Fixnums and so you should return true.

Related

Can we overide true and false methods in Ruby?

Is it possibile to override boolean method like true and false in Ruby?
For example
def true
rand()
end
def false
rand()
end
true #=> 0.7548583661438558
false #=> 0.19239076750079454
If I try the above, I get:
true #=> true
false #=> false
I'm trying to understand where these true, false methods are defined.
I know that && and || can't be overriden, because && and || are short circut operators.
Are true and false similar? or they are written inside Ruby somewhere?
I'm just experimenting with Ruby.
true and false cannot be overridden because they are keywords, not methods. Their values are hard-coded and there's no way to re-assign a different value. (at least not from within Ruby)
Even when implementing a method with the same name, a literal true will still resolve to the built-in value.
What you can do is change the object, true is resolving to for interesting results: (this is just for fun, don't do this in actual code)
def true.inspect
rand.to_s
end
true #=> 0.8499100640573652
true #=> 0.22279583303254913
However, the above example doesn't actually change the value of true in any way. Also, don't think of true as a method invocation returning a random float every time it is called. We are looking at the very same object:
a = true
a #=> 0.5813338288658235
a #=> 0.6447125630746154
What we did is change its representation by overriding inspect, which:
Returns a string containing a human-readable representation of obj.
We see those floats because IRB calls inspect in an attempt to print the last expression's result in a readable way.
If we set IRB's output mode to :to_s, our change is bypassed and we see true again:
IRB.CurrentContext.inspect_mode = :to_s
a #=> true
true #=> true

Check whether string match or not

I have a string and an array with some strings.
as below
hostname = TETDC3DBE01
Array = ['WEB','APP','STR','DBE']
I want to find whether that hostname match with any of the array element or not?
When I'm trying with below code getting output
no
no
no
no
Here is loop repeating each and every element on array. I want check that hostname with single check on array the produce the output either yes or no only.
Array.each do |x|
if hostname.match(x)
puts "yes"
else
puts "no"
end
end
Given this fixed Ruby code:
hostname = 'TETDC3DBE01'
array = ['WEB','APP','STR','DBE']
Where if you want to find all elements in array that match as a substring of hostname your code should work. The more minimal matching system is probably:
array.select { |x| hostname.match(x) }
# => ["DBE"]
Using a tool like puts to produce output isn't always very useful because that "yes" or "no" text can't be acted upon by more code. Try and think of Ruby programs as a chain of transformations, where this selects all matches, and later you can print them, like this:
puts array.select { |x| hostname.match(x) }.join(',')
# => DBE
Check out Array#any? method.
It passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } that will cause any? to return true if at least one of the collection members is not false or nil.
If instead a pattern is supplied, the method returns whether pattern === element for any collection member.
In your case:
hostname = 'TETDC3DBE01'
['WEB','APP','STR','DBE'].any? do |x|
hostname.match(x)
end
or even if you actually mean equal by match:
hostname = 'TETDC3DBE01'
['WEB','APP','STR','DBE'].any?(hostname)
Lets take your code to fix it.
hostname = "TETDC3DBE01"
arr = ['WEB','APP','STR','DBE']
arr.each do |x|
if hostname.match?(x)
puts "yes"
else
puts "no"
end
end
match gives array of result and
match? gives you true or false value
I wouldn't use regexp in this case. A simple String#include? is probably faster. Furthermore any? will return true if any of the elements in the array leads is matching.
hostname = 'TETDC3DBE01'
array = ['WEB','APP','STR','DBE']
array.any? { |x| hostname.include?(x) }
#=> true
Regular expression made real easy:
hostname = "TETDC3DBE01"
array = ['WEB','APP','STR','DBE']
re = Regexp.union(array)
hostname.match?(re) # => true

iterate array combination method with .any method

Is there anyway to iterate through different combinations of arrays?
I'm writing a program that returns true if the largest number in an array can be the sum of any of the members of the array.
This is my code: (forgive me, i learned how to program 2 weeks ago for the first time)
def ArrayAdditionI(arr)
arr=arr.sort
largest=arr.pop
n=arr.length
for i in 1..n
if arr.combination(i).to_a.any? {|array| array.inject(:+)==largest}
return true
else
return false
end
end
end
i tested it for
a = [1,2,3,4]
and it returned false even though clearly, 3+1 = 4.
When I change the above code from arr.combination(i) to arr.combination(2) its returns true. So I'm guessing it has something to do with the combination method not being able to be looped. Any suggestions?
You have return false in the wrong place. As it is, false is returned is there is no combination of one element (i.e., one element other than the one you've removed after sorting) that sums (i.e., is equal to) largest. Rather you want to return false only if no combination of any size sums to largest. This is what you need:
def max_match?(arr)
arr=arr.sort
largest=arr.pop
n=arr.length
for i in 1..n
return true if arr.combination(i).any? {|array|
array.inject(:+)==largest}
end
false
end
arr = [1,4,7,3,5,2,13]
max_match?(arr) #=> true
arr = [1,3,4,7,59]
max_match?(arr) #=> false
A few notes:
lower case letters and optional underscores are used for names of methods. You can also put a question (?) or explanation (!) mark at the end. Here a question mark seems appropriate.
to_a is not needed. Enumerable methods (e.g., any?) can have Enumerators as receivers.
sorting is expensive and unnecessary. Instead, just get the max value and remove it from the array. (Aside: you didn't say what happens if the maximum value appears more than once. See the code below and the last sentence.)
you don't need n=arr.length. for i in 1..arr.length is enough, except...
for ... is rarely used. Rubyists tend to use each instead, or one of the many methods from the Enumerable (mix-in) module (all of which invoke each).
you don't need return false because Ruby returns the value of the last statement evaluated, which is false if the method does not return true earlier.
Here's a more Ruby-like way to do that:
def max_match?(arr)
mx = arr.max
whats_left = arr - [mx]
(1..whats_left.size).any? {|n| whats_left.combination(n).any? {|c|
c.reduce(:+) == mx }}
end
arr = [1,4,7,3,5,2,13]
max_match?(arr) #=> true
arr = [1,3,4,7,59]
max_match?(arr) #=> false
If you wish this to return true when arr contains more than one value equal to mx, insert the following after mx = arr.max:
return true if arr.count(mx) > 1

Why do method declarations evaluate to nil in ruby?

Defining a method doesn't seem to evaluate to a truthy value as can be checked by putting one inside an if condition:
if(def some_method; puts "random text"; end) then
puts "declaration evaluates to true"
else
puts "declaration evaluates to false"
end
# => declaration evaluates to false
Why/How does a method declaration evaluate to nil?
It actually evaluates to nil. This makes sense; why would a method creation return anything?
irb(main):001:0> def test; print 'test'; end
=> nil
However, it has to return something, so to return "nothing" would be to return nil.
Every statement in Ruby evaluates to something. The def statement's value is not supposed to be checked and is therefore nil.
You will find the behavior you are looking for in the reflective "meta-programming" method define_method.
class EmptyClass
m = define_method(:newmethod) {p "I am the new method"}
p m # => <Proc:0x50b3f359#E:\NetBeansProjects\RubyApplication1\lib\main.rb:6>
end
From Ruby gotchas:
Boolean evaluation of non-boolean data is strict: 0, "" and [] are all evaluated to true. In C, the expression 0 ? 1 : 0 evaluates to 0 (i.e. false). In Ruby, however, it yields 1, as all numbers evaluate to true; only nil and false evaluate to false. A corollary to this rule is that Ruby methods by convention — for example, regular-expression searches — return numbers, strings, lists, or other non-false values on success, but nil on failure. This convention is also used in Smalltalk, where only the special objects true and false can be used in a boolean expression.
Method definions such as def some_method; puts "random text"; end always return nil.
Now, that means the method is evaluated to nil. According to the Ruby Documentation:
Returns false if obj is nil or false; true otherwise.
Since your method return nil, if will evaluate it as false therefore execute the else statement.

ruby method wont return false

i have method, which returns either an array (if it contains any elements) or false if it is nil:
def check_for_four
#four = []
check_values.each do |key, value| ###check_values return hash with key and values as numbers
#four << key if value == 4
end
if #four == nil
return false
else
return #four
end
end
but later on, if i call a method
if some_object.check_for_four
puts "true"
else
puts "false"
end
it always return true, even if #four array is empty. Why is that?
You are checking for whether the array is nil (i.e. is the singleton instance of NilClass) which is very different to checking whether the array is empty.
To check where the array is empty you can either call empty? or if you actually want to check whether it is not empty, you can also use any?.
You can of course also do things like check that the length/size is zero, but it feels more rubyish to me to ask for the specific thing you are interested in.
An empty array is 'truthy' in Ruby. For example:
puts "foo" if []
will output "foo" but
puts "foo" if nil
won't output anything.

Resources