Times Table - Fizzbuzz Type Question in Ruby - ruby

I'm brand new to programming and Ruby is my first language. One exercise I'm working on is to create a multiplication table that does the following:
1x1 = 1
1x2 = 2
(etc)
2x1 = 2
2x2 = 4
I figured I'd do this by creating a nested while loop:
a = 1
b = 1
while a <= 5
while b <= 5
puts "#{a} * #{b} = #{a * b}"
b += 1
end
a += 1
end
When I run the script it prints the first set of times table (1x1 - 1x5) then stops. It doesn't iterate the parent loop. What am I doing wrong?

You state that you're a novice so a while loop is ok for now. But when you improve both your programming and Ruby skills you should be able to write more idiomatic code. Something along those lines:
puts [*1..5].product([*1..5]).map { |x, y| "#{x} * #{y} = #{x*y}" }.join("\n")

You never reset your b to 1. Look at the second while loop:
while b <= 5:
...
b += 1
At the end of this loop, b = 6, and the loop exits. Then a += 1 is executed, and our outer loop begins. On all the next inner loop iterations, b = 6 however, and therefore isn't executed. Thus you need:
...
end
a += 1
b = 1

The "bookkeeping error" explained in the accepted answer is an easy one to make. It is one of the reasons the each method is generally preferred to a while loop:
(1..5).each do |a|
(1..5).each do |b|
puts "#{a} * #{b} = #{a * b}"
end
end
No bookkeeping!

class MultiplicationTable
i=1
j=5
while i <= j
(1..12).each do |x|
puts "#{i} * #{x} = #{i*x}"
end
i+=1
end
end

Related

How to loop over an entire method until you achieve what you want ? (ruby)

I'm learning ruby and practicing with codewars, and I've come to a challenge that I feel I mainly understand (rudimentarily) but I'm unable to figure out how to continue looping over the method until I reach the result I'm looking for.
The challenge is asking to reduce a number, by multiplying its digits, until the multiplication results in a single digit. In the end it wants you to return the number of times you had to multiply the number until you arrived at a single digit. Example -> given -> 39; 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4; answer -> 3
Here's my code :
def persistence(n)
if n < 10
return 0
end
arr = n.to_s.split("")
sum = 1
count = 0
arr.each do |num|
sum *= num.to_i
if num == arr[-1]
count += 1
end
end
if sum < 10
return count
else
persistence(sum)
end
end
Thanks for your help!
Your function is looking great with recursion but you are reseting the count variable to 0 each time the loop runs, I think if you use an auxiliar method it should run ok:
this is in base of your code with minor improvements:
def persistence(n)
return 0 if n < 10
count = 0
multiply_values(n, count)
end
def multiply_values(n, count)
arr = n.to_s.chars
sum = 1
arr.each do |num|
sum *= num.to_i
if num == arr[-1]
count += 1
end
end
if sum < 10
return count
else
multiply_values(sum, count)
end
end
a shorter solution could be to do:
def persistence(n)
return 0 if n < 10
multiply_values(n, 1)
end
def multiply_values(n, count)
sum = n.to_s.chars.map(&:to_i).reduce(&:*)
return count if sum < 10
multiply_values(sum, count + 1)
end
and without recursion:
def persistence(n)
return 0 if n < 10
count = 0
while n > 10
n = n.to_s.chars.map(&:to_i).reduce(&:*)
count += 1
end
count
end
Let's look at a nicer way to do this once:
num = 1234
product = num.to_s.split("").map(&:to_i).reduce(&:*)
Breaking it down:
num.to_s.split("")
As you know, this gets us ["1", "2", "3", "4"]. We can easily get back to [1, 2, 3, 4] by mapping the #to_i method to each string in that array.
num.to_s.split("").map(&:to_i)
We then need to multiply them together. #reduce is a handy method. We can pass it a block:
num.to_s.split("").map(&:to_i).reduce { |a, b| a * b }
Or take a shortcut:
num.to_s.split("").map(&:to_i).reduce(&:*)
As for looping, you could employ recursion, and create product_of_digits as a new method for Integer.
class Integer
def product_of_digits
if self < 10
self
else
self.to_s.split("").map(&:to_i).reduce(&:*).product_of_digits
end
end
end
We can now simply call this method on any integer.
1344.product_of_digits # => 6

very simple ruby programing, getting into infinite loop

I'm asked to write the ruby program that generate the output based the given command,
The full description
I'm really new in ruby (maybe few hours that I have started ruby)
When I run the program I get into infinite loop, I don't understand why.
Thank you.
What I have done so far:
# MyVector Class
class MyVector
def initialize (a)
if !(a.instance_of? Array)
raise "ARGUMENT OF INITIALIZER MUST BE AN ARRAY"
else
#array = a
end
end
def array
#array
end
def to_s
#array.to_s
end
def length
#array.length
end
def [](i)
#array[i]
end
def each2(a)
raise Error, "INTEGER IS NOT LIKE VECTOR" if a.kind_of?(Integer)
Vector.Raise Error if length != a.length
return to_enum(:each2, a) unless block_given?
length.times do |i|
yield #array[i], a[i]
end
self
end
def * (a)
Vector.Raise Error if length != a.length
p = 0
each2(a) {|a1, a2|p += a1 * a2}
p
end
end
# MyMatrix Class
class MyMatrix
def initialize a
#array=Array.new(a.length)
i=0
while(i<a.length)
#array[i]=MyVector.new(a[i])
end
end
def to_s
#array.to_s
end
def transpose
size=vectors[0].length
arr= Array.new(size)
i=0
while i<size
a=Array.new(vector.length)
j=0
while j<a.length
a[j]=vectors[j].arr[i]
j+=1
end
arr[i]=a
i+=1
end
arr[i]=a
i+=1
end
def *m
if !(m instance_of? MyMatrix)
raise Error
a=Array.new(#array.length)
i=0
while (i<#array.length)
a[i]=#array[i]*m
i=i+1
end
end
end
end
Input:
Test code
v = MyVector.new([1,2,3])
puts "v = " + v.to_s
v1 = MyVector.new([2,3,4])
puts "v1 = " + v1.to_s
puts "v * v1 = " + (v * v1).to_s
m = MyMatrix.new([[1,2], [1, 2], [1, 2]])
puts "m = " + m.to_s + "\n"
puts "v * m = " + (v * m).to_s
m1 = MyMatrix.new([[1, 2, 3], [2, 3, 4]])
puts "m1 = " + m1.to_s + "\n"
puts "m * m1 = " + (m * m1).to_s
puts "m1 * m = " + (m1 * m).to_s
Desired Output:
v = 1 2 3
v1 = 2 3 4
v * v1 = 20
m =
1 2
1 2
1 2
v * m = 6 12
m1 =
1 2 3
2 3 4
m * m1 =
5 8 11
5 8 11
5 8 11
m1 * m =
6 12
9 18
To answer the infinite loop issue, it looks like you forgot to add a i += 1 in the #initialize method of Matrix class.
However, you will encounter more errors further in the code since, for example, you're checking length of the Matrix object which is undefined, and iterating over the Matrix object in each2 defined inside of the Vector class which needs the object to be an Enumerable (Array/Hash etc). These will throw an error as the Matrix class is not an Enumerator. These are some good resources to help you learn how the powerful Enumerator module works.
Once you get familiar with the syntax and structure, be sure to use the Pry tool. It will be your best friend for debugging Ruby code.

Brainteaser Locker Open or Closed? in Ruby

Trying to code the classic brainteaser locker problem (the one where you open/close 100 lockers). When I run the code I wrote it does not give me the correct answer of 10 open lockers, but instead says all lockers are closed. I think I'm missing something in my loops...any suggestions? Thanks.
def lockerproblem
j = 0
lockers = []
while j < 100
lockers << "open"
j += 1
end
a = 1
i = 0
while a <= 100
while i < 100
if ( i + 1 ) % a == 0
if lockers[i] == "open"
lockers[i] = "closed"
else
lockers[i] = "open"
end
end
i += 1
end
a += 1
end
lockers[3] = "open"
lockers.each do |text|
puts text
end
end
lockerproblem
Consider this for array initialization:
lockers = ["open"] * 100
Think about your i variable: when is it set to 0? What will that mean to the inner loop? E.g.,
a, b = 0, 0
while a < 2
while b < 2
puts "a=#{a}, b=#{b}"
b += 1
end
a += 1
end
Outputs:
a=0, b=0
a=0, b=1
In other words, you don't see:
a=0, b=0
a=0, b=1
a=1, b=0
a=1, b=1
Why? Because b is incremented to 2, is never reset, and the inner loop only executes once. Perhaps you are setting the initial value of i in the wrong place, where "wrong" means "outside the outer loop".
Lastly, opening the fourth locker (locker[3]) will throw off the results.
There are a number of small tweaks that could make the code a bit easier to understand (heck I might even define an open? method on String for the purposes of this small example), but this should be enough to get you the answer you expect.
Such monkey-patching isn't always a good idea, particularly on Ruby internals. But it allows some easy and nice-looking stuff like this:
> lockers.find_all(&:closed?).size
=> 10
You can get the right answer by making three changes:
i needs to be reset to 0 at the start of each iteration of a
The lockers should start as closed
Remove the extra lockers[3] = "open" line
The updated code:
def lockerproblem
j = 0
lockers = []
while j < 100
lockers << "closed"
j += 1
end
a = 1
i = 0
while a <= 100
i = 0
while i < 100
if ( i + 1 ) % a == 0
if lockers[i] == "open"
lockers[i] = "closed"
else
lockers[i] = "open"
end
end
i += 1
end
a += 1
end
lockers.each do |text|
puts text
end
end
lockerproblem

Ruby Each Statement gets stuck on while loop

New to StackOverflow here. I'm working on the first Euler problem and have run into an issue where I can get the statement to iterate through the array. It seems like it has something to do with the way I have the while loop setup but I can't figure it out.
Here's my code:
#euler problem 1
numbers = [3,5]
sum = 0
i=1
total=0
numbers.each do |number|
while i * number < 10
adder = i * number
total += adder
i += 1
puts total
end
end
puts total
The output is 3
9
18
18
Any idea why it isn't processing the 5 in the array numbers?
Your problem is that i is declared outside the block so when number is five, i is already four and the while loop's condition fails immediately because 20 < 10 is false. Try it like this:
numbers = [3,5]
sum = 0
total=0
numbers.each do |number|
i = 1
while i * number < 10
#...
end
end
puts total
If you put a little puts in your code you'll see what's going on:
i = 1
numbers.each do |number|
puts "#{number}\ti = #{i}"
while i * number < 10
puts "\ti = #{i}"
adder = i * number
total += adder
i += 1
end
end
That will give you this output:
3 i = 1
i = 1
i = 2
i = 3
5 i = 4
and you'll see the problem with i.

more ruby way of doing project euler #2

I'm trying to learn Ruby, and am going through some of the Project Euler problems. I solved problem number two as such:
def fib(n)
return n if n < 2
vals = [0, 1]
n.times do
vals.push(vals[-1]+vals[-2])
end
return vals.last
end
i = 1
s = 0
while((v = fib(i)) < 4_000_000)
s+=v if v%2==0
i+=1
end
puts s
While that works, it seems not very ruby-ish—I couldn't come up with any good purely Ruby answer like I could with the first one ( puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).
For a nice solution, why don't you create a Fibonacci number generator, like Prime or the Triangular example I gave here.
From this, you can use the nice Enumerable methods to handle the problem. You might want to wonder if there is any pattern to the even Fibonacci numbers too.
Edit your question to post your solution...
Note: there are more efficient ways than enumerating them, but they require more math, won't be as clear as this and would only shine if the 4 million was much higher.
As demas' has posted a solution, here's a cleaned up version:
class Fibo
class << self
include Enumerable
def each
return to_enum unless block_given?
a = 0; b = 1
loop do
a, b = b, a + b
yield a
end
end
end
end
puts Fibo.take_while { |i| i < 4000000 }.
select(&:even?).
inject(:+)
My version based on Marc-André Lafortune's answer:
class Some
#a = 1
#b = 2
class << self
include Enumerable
def each
1.upto(Float::INFINITY) do |i|
#a, #b = #b, #a + #b
yield #b
end
end
end
end
puts Some.take_while { |i| i < 4000000 }.select { |n| n%2 ==0 }
.inject(0) { |sum, item| sum + item } + 2
def fib
first, second, sum = 1,2,0
while second < 4000000
sum += second if second.even?
first, second = second, first + second
end
puts sum
end
You don't need return vals.last. You can just do vals.last, because Ruby will return the last expression (I think that's the correct term) by default.
fibs = [0,1]
begin
fibs.push(fibs[-1]+fibs[-2])
end while not fibs[-1]+fibs[-2]>4000000
puts fibs.inject{ |sum, n| n%2==0 ? sum+n : sum }
Here's what I got. I really don't see a need to wrap this in a class. You could in a larger program surely, but in a single small script I find that to just create additional instructions for the interpreter. You could select even, instead of rejecting odd but its pretty much the same thing.
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
puts fib.take_while{|i| i < 4000000}
.reject{|x| x.odd?}
.inject(:+)
That's my approach. I know it can be less lines of code, but maybe you can take something from it.
class Fib
def first
#p0 = 0
#p1 = 1
1
end
def next
r =
if #p1 == 1
2
else
#p0 + #p1
end
#p0 = #p1
#p1 = r
r
end
end
c = Fib.new
f = c.first
r = 0
while (f=c.next) < 4_000_000
r += f if f%2==0
end
puts r
I am new to Ruby, but here is the answer I came up with.
x=1
y=2
array = [1,2]
dar = []
begin
z = x + y
if z % 2 == 0
a = z
dar << a
end
x = y
y = z
array << z
end while z < 4000000
dar.inject {:+}
puts "#{dar.sum}"
def fib_nums(num)
array = [1, 2]
sum = 0
until array[-2] > num
array.push(array[-1] + array[-2])
end
array.each{|x| sum += x if x.even?}
sum
end

Resources