Conditional to compare three values - ruby

I am trying to determine if there is a way for me to write an if statement that will result in true if three values are equal to each other.
EX:
if a == b == c
puts "true"
end
Instead of having to write:
if a == b && a == c && b == c

You don't need all 3, if a equal b and c equal b it implies a equal c.
If you need it more scalable 3+ arguments, you can do:
Set[a, b, c].size == 1
Original answer was:
Set[a, b, c].one?
But it one? does not count nil or false elements. So Set[nil, nil].one? will be false.
Thanks to Sagar Pandya for pointing it out in the comments.

What about this?
[a, b, c].uniq.size == 1

As #Bodacious mentioned a == b && b == c would work due to the transitive property.
But if you have many items, you could do something like:
values = [a, b, c]
if values.all? { |value| value == value[0] }
puts "true"
end
The all? method returns true if a block returns true for every item. So in that block, check to see if every item is equal to the first item.

Related

Basic Logic operators both AND and OR

Hi I have tree conditions
A, B and C
Now, I want to apply these conditions I such a way, that if any of these conditions is true, or a combination, the whole outcome is true.
If I do
A || B || C
then as soon as A is true, B and C are not evaluated
if I do
A && B && C
it's only true if ALL of them are true.
Is there a special notation for fulfilling my wishes?
Using the Or (||) operator will give you the correct answer because it does not need to evaluate the other conditions but if you want B and C to be evaluated even if A is True then you should nest the If statements such as:
if A == True
do something;
if B == True
do something;
if C == True
do something;
Or just do three separate If statements.
You have answered your own question.
You want a situation whereby if EITHER A OR B OR C is true, or if a combination such as A AND B are true then the whole expression will evaluate to true.
That is A || B || C. If you only care about requiring ANY of the conditions to be true, then there is no need to evaluate all the conditions because as long as ONE condition is true, then your whole expression or outcome is true.
If you care about the specific combinations being true TOGETHER then you can group them using parenthesis as such:
If I want A AND B to be true at the same time OR C: (A && B) || C
If I want A AND C to be true at the same time OR B: (A && C) || B

Evaluation of multiple conditions

I have a quick question :
In ruby, If I write
def test
foo && a == b && c == "bar"
end
if foo is null or false, will it keep evaluating the rest of the expression ?
Does it change anything if I do this instead
def test
a == b && c == "bar" if foo
end
thanks a lot
Theory
&& is a lazy operator, just like ||.
It means that in a && b, if a is false or nil, Ruby won't bother to check b because a && b will be false/nil anyway.
This behaviour is actually desired, because it saves time and could avoid NoMethodErrors.
if a && method_which_requires_a_non_nil_parameter(a)
# ...
end
method_which_requires_a_non_nil_parameter wouldn't be called at all if a is nil.
or :
x = x || long_method_to_calculate_x
is often used for caching, more often written as :
#x ||= long_method_to_calculate_x
Answer
def test
foo && a == b && c == "bar"
end
The rest of the expression won't be evaluated if foo is nil or false :
a, b, c could even be undefined without raising a NameError.
def test
a == b & c == "bar" if foo
end
If foo is truthy, the results will be exactly the same.
If foo is nil or false, the 2 equalities won't be evaluated, just like with the first example. But :
If foo is nil, both test will return nil.
If foo is false, first example will return false, second example will return nil.
"If foo is null or false, will it keep evaluating the rest of the expression?"
No, it will not
This table should help you in such questions:
The following table is ordered according to descending precedence (highest precedence at the top)
N A M Operator(s) Description
- - - ----------- -----------
1 R Y ! ~ + boolean NOT, bitwise complement, unary plus
(unary plus may be redefined from Ruby 1.9 with +#)
2 R Y ** exponentiation
1 R Y - unary minus (redefine with -#)
2 L Y * / % multiplication, division, modulo (remainder)
2 L Y + - addition (or concatenation), subtraction
2 L Y << >> bitwise shift-left (or append), bitwise shift-right
2 L Y & bitwise AND
2 L Y | ^ bitwise OR, bitwise XOR (exclusive OR)
2 L Y < <= >= > ordering
2 N Y == === != =~ !~ <=> equality, pattern matching, comparison
(!= and !~ may not be redefined prior to Ruby 1.9)
2 L N && boolean AND
2 L N || boolean OR
2 N N .. ... range creation (inclusive and exclusive)
and boolean flip-flops
3 R N ? : ternary if-then-else (conditional)
2 L N rescue exception-handling modifier
2 R N = assignment
2 R N **= *= /= %= += -= assignment
2 R N <<= >>= assignment
2 R N &&= &= ||= |= ^= assignment
1 N N defined? test variable definition and type
1 R N not boolean NOT (low precedence)
2 L N and or boolean AND, boolean OR (low precedence)
2 N N if unless while until conditional and loop modifiers

How to reverse a singly linked list recursively without modifying the pointers?

Recently I had an interview and the interviewer asked me to reverse a singly linked list without modifying the pointers(change the values only).
At the beginning I came up with a solution using a stack. He said that was OK and wanted me to do it recursively. Then I gave him a O(n^2) solution. But he said he needs a O(n) solution.
Anyone can help me?
Pseudocode
reverse (list):
reverse2 (list, list)
reverse2 (a, b):
if b != nil:
a = reverse2 (a, b.next)
if a != nil:
swap (a.data, b.data)
if a == b || a.next == b:
# we've reached the middle of the list, tell the caller to stop
return nil
else:
return a.next
else:
# the recursive step has returned nil, they don't want us to do anything
return nil
else:
# we've reached the end of the list, start working!
return a
One way I can think of doing it is recursing to the end accumulating the values in another list as you resurse to the end, then on the way out of the recursion writing the values back starting with the 1st value in the list. It would be O(2n). It's not much different from using a stack...
list = { a => b => c => d }
def recursive(acc, x)
if !x
return acc
end
acc.preprend(x)
return recursive(acc, x.next)
end
result = recursive([], list.first)
So first call is recursive([], a). result is now [a].
Second call is recursive([a], b). result turns into [b, a].
Third call is recursive([b, a], c). result is [c, b, a].
Fourth call is recursive([c, b, a], d), and result [d, c, b, a].
Fifth call gets caught by the if !x.
Tell your interviewer you need an additional structure, like someone else said above.

Ruby FizzBuzz And/Or

Here's the problem: "Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”."
My code below works, but I don't understand why, on the last line, it is f || b and not f & b?
Shouldn't both f AND b have to be truth in order to return FizzBuzz, not f OR b?
puts (1..100).map {|i|
f = i % 3 == 0 ? 'Fizz' : nil
b = i % 5 == 0 ? 'Buzz' : nil
f || b ? "#{ f }#{ b }" : i
}
f || b is true if f is not null or b is not null, or both, because that's part of the definition of OR.
If that expression is true, then we print "#{ f }#{ b }", which will print either Fizz, Buzz, or FizzBuzz depending on whether f or b (or neither) are null, since a null variable will be replaced with a blank string.

A more elegant solution to Ruby Koans' triangle.rb

I have been working through Ruby Koans and made it to about_triangle_project.rb in which you are required to write the code for a method, triangle.
Code for these items are found here:
https://github.com/edgecase/ruby_koans/blob/master/koans/about_triangle_project.rb
https://github.com/edgecase/ruby_koans/blob/master/koans/triangle.rb
In triangle.rb, I created the following method:
def triangle(a, b, c)
if ((a == b) && (a == c) && (b == c))
return :equilateral
elsif ((a == b) || (a == c) || (b == c))
return :isosceles
else
return :scalene
end
end
I know from reading Chris Pine's "Learn to Program" there is always more than one way to do things. Although the above code works, I can't help but think there is a more elegant way of doing this. Would anyone out there be willing to offer their thoughts on how they might make such a method more efficient and compact?
Another thing I am curious about is why, for determining an equilateral triangle, I was unable to create the condition of (a == b == c). It is the proof for an equilateral triangle but Ruby hates the syntax. Is there an easy explanation as to why this is?
There is an easy explanation for why that is:
== in Ruby is an operator, which performs a specific function. Operators have rules for determining what order they're applied in — so, for example, a + 2 == 3 evaluates the addition before the equality check. But only one operator at a time is evaluated. It doesn't make sense to have two equality checks next to each other, because an equality check evaluates to true or false. Some languages allow this, but it still doesn't work right, because then you'd be evaluating true == c if a and b were equal, which is obviously not true even if a == b == c in mathematical terms.
As for a more elegant solution:
case [a,b,c].uniq.size
when 1 then :equilateral
when 2 then :isosceles
else :scalene
end
Or, even briefer (but less readable):
[:equilateral, :isosceles, :scalene].fetch([a,b,c].uniq.size - 1)
Another approach:
def triangle(a, b, c)
a, b, c = [a, b, c].sort
raise TriangleError if a <= 0 or a + b <= c
return :equilateral if a == c
return :isosceles if a == b or b == c
return :scalene
end
I borrowed Chuck's cool uniq.size technique and worked it into an oo solution. Originally I just wanted to extract the argument validation as a guard clause to maintain single responsibility principle, but since both methods were operating on the same data, I thought they belonged together in an object.
# for compatibility with the tests
def triangle(a, b, c)
t = Triangle.new(a, b, c)
return t.type
end
class Triangle
def initialize(a, b, c)
#sides = [a, b, c].sort
guard_against_invalid_lengths
end
def type
case #sides.uniq.size
when 1 then :equilateral
when 2 then :isosceles
else :scalene
end
end
private
def guard_against_invalid_lengths
if #sides.any? { |x| x <= 0 }
raise TriangleError, "Sides must be greater than 0"
end
if #sides[0] + #sides[1] <= #sides[2]
raise TriangleError, "Not valid triangle lengths"
end
end
end
def triangle(a, b, c)
if a == b && a == c # transitivity => only 2 checks are necessary
:equilateral
elsif a == b || a == c || b == c # == operator has the highest priority
:isosceles
else
:scalene # no need for return keyword
end
end
class TriangleError < StandardError
end
def triangle(a, b, c)
sides = [a,b,c].sort
raise TriangleError if sides.first <= 0 || sides[2] >= sides[1] + sides[0]
return :equilateral if sides.uniq.length == 1
return :isosceles if sides.uniq.length == 2
:scalene
end
Here is my solution:
def triangle(a, b, c)
sides = [a, b, c].sort
raise TriangleError, "Invalid side #{sides[0]}" unless sides[0] > 0
raise TriangleError, "Impossible triangle" if sides[0] + sides[1] <= sides[2]
return [:scalene, :isosceles, :equilateral][ 3 - sides.uniq.size ]
end
Hmm.. I didn't know about uniq - so coming from smalltalk (ages ago) I used:
require 'set'
def triangle(a, b, c)
case [a, b, c].to_set.count
when 1 then :equilateral
when 2 then :isosceles
else :scalene
end
end
Coming from the matlab world, I am used to array functions 'any' and 'all', and was happy enough to find them in Ruby. So:
def triangle(a, b, c)
eqs = [a==b, a==c, b==c]
eqs.all?? :equilateral : eqs.any?? :isosceles : :scalene
end
No idea whether that's optimal though, in terms of readability, computation time... (ruby noob).
Here is my solution:
def triangle(a, b, c)
return :equilateral if a == b and b == c
return :isosceles if ( a == b or b == c or a == c )
return :scalene
end

Resources