Ruby FizzBuzz And/Or - ruby

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.

Related

Conditional to compare three values

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.

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 write a conditional lambda in Ruby?

I'd like to write a conditional lambda in Ruby. The Python equivalent of what I'd like to write is:
even = (lambda x: x if x % 2 == 0 else 0)
My attempt to write this in Ruby looks like:
even = -> (x) {x if x % 2 == 0 else 0}
Unfortunately, that does not work. Is there any way to fix this?
You have several options here to express this. The long-form is this:
if (x % 2 == 0)
x
else
0
end
Note that a trailing if or unless cannot have a secondary condition like else. You need to use the full form.
If you want a short version, you use the ternary operator:
(x % 2 == 0) ? x : 0
What you could also do is this:
(x % 2 == 0) and x or 0
As others have observed there's a method called even? which does the modulo for you, so that can collapse this further:
x.even? ? x : 0
Ruby's ternary operator has this syntax
x % 2 == 0 ? x : 0
You don't even need a conditional.
p = ->(x) { x*(1-x%2) }
p.call(4) #=> 4
p.call(5) #=> 0
Note procs can be called in multiple ways:
p[4] #=> 4
p.(4) #=> 4
p.yield(4) #=> 4
p === 4 #=> 4
p(4) #=> 4
The last of these may be archaic.
Wrong syntax. You can write it like this:
even = -> (x) {if x % 2 == 0; x; else; 0; end}
However, for such one-liners, it is more common to use the ternary ?: operator, as other have suggested in this thread.
Your syntax is wrong:
The then-block comes after the condition, not before it.
The then-block is separated from the condition by the then keyword, a semicolon, or a newline.
The conditional expression is terminated with an end keyword.
So, any of the following is valid:
# idiomatic:
if x % 2 == 0 then x else 0 end
# idiomatic:
if x % 2 == 0
x
else
0
end
# non-idiomatic:
if x % 2 == 0; x else 0 end
# non-idiomatic:
if x % 2 == 0 then
x
else
0
end
# non-idiomatic:
if x % 2 == 0
x else 0 end
# … and many other non-idiomatic variations
Ruby also has a conditional operator:
x % 2 ? x : 0
But I personally find it ugly and unreadable. It also has different precedence than the conditional expression, which may be surprising to some. (Witness the myriad of variations of the same question about the conditional operator here on StackOverflow.) And it is completely unnecessary: in C, where if is a conditional statement, the conditional operator is required because it is an expression. In Ruby, everything is an expression anyway, there are no statements, so of course if is an expression, too.

Is == a special method in Ruby?

I understand that x == y in Ruby interpreted as a.==(y). I tried to check if I can achieve the same with custom method, foo, like this:
class Object
def foo(n)
self == n
end
end
class A
attr_accessor :x
end
a = A.new
a.x = 4
puts a.x.==(4) # => true
puts a.x.foo(4) # => true
puts a.x == 4 # => true
puts a.x foo 4 # => in `x': wrong number of arguments (1 for 0) (ArgumentError)
Unfortunately, this doesn't work. What am I missing ? Is == a special method in Ruby ?
No, == is not a special method in Ruby. It's a method like any other. What you are seeing is simply a parsing issue:
a.x foo 4
is the same as
a.x(foo(4))
IOW, you are passing foo(4) as an argument to x, but x doesn't take any arguments.
There is, however, special operator syntax, which allows you to write
a == b
instead of
a.== b
for a limited list of operators:
==
!=
<
>
<=
>=
<=>
===
&
|
*
/
+
-
%
**
>>
<<
!==
=~
!~
Also, there is special syntax that allows you to write
!a
and
~a
instead of
a.!
and
a.~
As well as
+a
and
-a
instead of
a.+#
and
a.-#
Then, there is
a[b]
and
a[b] = c
instead of
a.[] b
and
a.[]= b, c
and last but not least
a.(b)
instead of
a.call b
Methods that are operators are treated specially in Ruby, at least syntax-wise. The language is not as flexible as, say, in Haskell where you can turn any function into an infix operator by enclosing its name in backticks: the list on infix operators are pre-determined.
One of the problems that would arise from custom infixes is the handling of operator precedence and associativity: for eaxmple, how would the parser handle a statement like:
a foo b == c # should this be (a foo b) == c or a foo (b == c)

Mathematica Reduce/Solve: Best way to ask for non-repeating values

A few times I found I had a system and I need to specify that all variables get different values (ie non-repeating).
I usually do things like this:
k = {a, b, c, d, e, f, g};
Reduce[
a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And ### {0 < # < 8 & /# k}] &&
Times#(Sequence ## (Subsets[k, {2}] /. {x_, y_} -> (x - y))) != 0,
k, Integers]
Where the last part of the Reduce equation
Times#(Sequence ## (Subsets[k, {2}] /. {x_, y_} -> (x - y))) != 0
asks for different values.
Are there better ways to do this? (I mean, not the product equal zero, but to specify I need all variables different)
From the speed viewpoint, you are inducing a large overhead with that product condition. If your solutions are always numbers, you can produce all solutions with Reduce and then filter them - it may be faster in some cases. For example, in the case at hand:
k = {a, b, c, d, e, f, g};
sl = Reduce[ a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And ### {0 < # < 8 & /# k}], k, Integers]
You can do the post-processing, for example like this (perhaps not the best way):
In[21]:= Select[{#, First[k /. Solve[#, k]]} & /# List ## sl,
MatchQ[Tally[#[[2]], Equal][[All, 2]], {1 ..}] &][[All, 1]]
Out[21]= {a == 3 && b == 2 && c == 7 && d == 6 && e == 4 && f == 5 && g == 1}
At least for this particular case, it was much faster.
For smallish problems, post=processing to remove unwanted solutions might be best. For larger problems there are at least two useful approaches.
(1) If the allowed values are say contiguous, or nearly so, could create 0-1 variables for the grid of each original variable and possible value. For example, if your variables are intended to fill out a standard Sudoku array, then x[i,j,k]=1 could be used to indicate that the value in row i, col j, is k. The constraints that e.g. no value in row 1 is repeated would be
Sum[x[1,j,1]==1, {j,9}]
...
Sum[x[1,j,9]==1, {j,9}]
If not all values need to be used in all places (e.g. rows) then these could be made into inequalities instead.
(2) Another approach is to use 0-1 variables for each pair if values that needs to be distinct. We assume there is at least a known upper and lower bound on value ranges. Call it m. So for any pair of variables x and y we know that the difference is between -m and m (could add/subtract ones there, but not essential).
For the pair x[i] and x[j] that need to be distinct, add a new variable 0-1 k[i,j]. The idea is it will need to be 1 if x[i]>x[j] and 0 if x[j]>x[i].*
For this pair we add two equations. I will show them in non-expanded form as that might be slightly easier to understand.
x[i]-x[j] >= k[i,j] + m*(k[i,j]-1)
x[j]-x[i] >= (1-k[i,j]) + m*(-k[i,j])
If x[i]>x[j] then both are satisfied only for k[i,j]==1. Vice versa for x[j]>x[i] and k[i.j]==0.
This might be the preferred method when variables can span a range of values substantially larger than the number of variables, or when far fewer that all pairs are constrained to be distinct values.
Daniel Lichtblau
*It's late Saturday night, so reverse anything I got backwards. Also please fix all typos while you are at it.
Why not supply a uniqueness constraint directly?
k = {a, b, c, d, e, f, g};
uniqueness = {a != b != e};
sl = Reduce[
a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And ### {0 < # < 8 & /# k}] && First#uniqueness , k,
Integers]//Timing
Out[1]= {0.046791, a == 3 && b == 2 && c == 7 && d == 6 && e == 4 && f == 5 && g == 1}
From a cursory glance at your constraints above, most of the uniqueness requirements are self satisfied by the other constraints and setting a≠b≠e fixes all the remaining. There is no need to test for everything. For e.g.,
f = a + b ⇒ f ≠ a & f ≠ b
f = e + g ⇒ f ≠ e & f ≠ g
2f = d + e ⇒ f ≠ d ∵ f ≠ e ⇒ g ≠ d
c = g + d ⇒ c ≠ g & c ≠ d
and so on... You can probably work that out in detail.
I understand this is probably just a test example, and I don't have a smart and fast one stop answer that you can use without thinking about the problem.

Resources