Ruby stop and move to next iteration of for loop - ruby

I have a for loop with an if elsif statement inside. On the first if, if the condition is met I want it to stop there and go on to the next iteration of the loop.
This is a very simplified version of what I am trying to do:
array = [1,2,3,4,"x"]
for i in 0..(array.count -1)
if array[i] == "x"
#start next for loop iteration without executing the elsif
elsif array[i] < 3
puts "YAY!"
end
end
What I am exactly trying to do is iterating through an array which all but one of the elements are integers but one of them is a string. On the string element, I need the loop (whatever kind is best) to skip the rest of the code and go to the next iteration of the loop. This is important because the second if statement uses an 'array_element < 11 condition' so if it runs that on the string element I get "comparison of String with 11 failed"
so I would want arr[x][3] this is what i tried but it gives me 8 8 8 8 instead of a single 8.
arr = [[1,2,3,"4"], [5,6,7,8], [9,10,11,12]]
arr.each{|x|
x.each {|i|
next if x[3].instance_of? String
if x[3] < 12 puts x[3]
end
}
}
Ok this works!! Thank you iAmRubuuu!!
arr = [1,2,3,"4"], [5,6,7,8], [9,10,11,12], [13,14,15,"16"], [17,18,19,20]]
arr.each_with_index{|x, i|
next if x.last.instance_of? String
if x.last < 21
puts x.last
end
}
give me the output
8
12
20

Don't use for in, use each.
(0..10).each do |i|
next if i == 5
if i == 10
puts "YAY!"
end
end

As per your edit, hope the below one you are looking for:
arr = [1, 2, 3, "11", 11]
arr.each do |x|
next if x.instance_of? String
puts "#{x} is #{x.class}"
end
Output:
1 is Fixnum
2 is Fixnum
3 is Fixnum
11 is Fixnum
EDIT
Code:
arr = [[1,2,3,"4"], [4,5,6,7], [8,9,10,11]]
arr.each{|x|
x.each{ |i|
next if i.instance_of? String
puts "#{i} is #{i.class}"
}
}
Output:
1 is Fixnum
2 is Fixnum
3 is Fixnum
4 is Fixnum
5 is Fixnum
6 is Fixnum
7 is Fixnum
8 is Fixnum
9 is Fixnum
10 is Fixnum
11 is Fixnum
V_1(from your first comment in my answer post)
arr = [[1,2,3,"4"], [4,5,6,7], [8,9,10,11]]
puts arr[1].last,arr.last.last
Output:
7
11
V_2(from your first comment in my answer post)
arr = [[1,2,3,"4"], [4,5,6,7], [8,9,10,11]]
arr.each_with_index{ |x,i|
next if i == 0
#p x,i
p "last element of inner array:#{x.last}"
}
Output:
"last element of inner array:7"
"last element of inner array:11"

Related

How to multiply integer digits between them?

I want to my n to multiply with next number for example if n=99 i want it to 9*9 and then return a result, and then i want the result (9*9 = 81 then 8*1 = 8) to multiply until it becomes 1 digit.
Here's my code:
def persistence(n)
if n <= 9
puts n
else
n.to_s.each_char do |a|
a.to_i * a.to_i unless n < 9
puts a.to_i
end
end
end
and i want it to return this:
persistence(39) # returns 3, because 3*9=27, 2*7=14, 1*4=4
# and 4 has only one digit
persistence(999) # returns 4, because 9*9*9=729, 7*2*9=126,
# 1*2*6=12, and finally 1*2=2
persistence(4) # returns 0, because 4 is already a one-digit number
def persistence(n)
i = 0
while n.to_s.length != 1
n = n.to_s.each_char.map(&:to_i).reduce(:*)
i +=1
end
i
end
persistence(39) #=> 3
persistence(999) #=> 4
Other version:
def p(n, acc)
return acc if n <= 9
p(n.to_s.each_char.map(&:to_i).reduce(:*), acc+1)
end
def persistence(n)
p(n, 0)
end
I will leave the breaking down of method and understanding what's happening and what is the difference b/w two variations to you. Will love to see your comment explaining it.
def persistence(n)
0.step.each do |i|
break i if n < 10
n = n.digits.reduce(:*)
end
end
persistence 4 #=> 0
persistence 39 #=> 3
persistence 999 #=> 4
persistence 123456789123456789 #=> 2
Regarding the last result, note that 2*5*2*5 #=> 100.

Is it better way to do that?

I wrote a simple script to sum all digits of positive integer input until 1 digit is left ( for example for input 12345 result is 6 because 1+2+3+4+5 = 15 and 1+5 = 6). It works but is it better way to do that? ( more correct?)
here is a code:
def sum(n)
string=n.to_s
while string.length > 1 do
result=string.chars.inject { |sum,n| sum = sum.to_i + n.to_i}
string=result.to_s
end
puts "Sum of digits is " + string
end
begin
p "please enter a positive integer number:"
number = Integer(gets.chomp)
while number<0
p "Number must be positive!Enter again:"
number = Integer(gets.chomp)
end
rescue
p "You didnt enter integer!:"
retry
end
sum(number)
According to Wikipedia, the formula is:
dr(n) = 1 + ((n − 1) mod 9)
So it boils down to:
def sum(n)
1 + (n - 1) % 9
end
To account for 0, you can add return 0 if n.zero?
You could use divmod (quotient and modulus) to calculate the digit sum without converting to / from string. Something like this should work:
def sum(number)
result = 0
while number > 0 do
number, digit = number.divmod(10)
result += digit
if number == 0 && result >= 10
number = result
result = 0
end
end
result
end
sum(12345) #=> 6
The line
number, digit = number.divmod(10)
basically strips off the last digit:
12345.divmod(10) #=> [1234, 5]
1234 becomes the new number and 5 is being added to result. If number eventually becomes zero and result is equal or greater than 10 (i.e. more than one digit), result becomes the new number (e.g. 15) and the loops starts over. If result is below 10 (i.e. one digit), the loop exits and result is returned.
Short recursive version:
def sum_of_digits(digits)
sum = digits.chars.map(&:to_i).reduce(&:+).to_s
sum.size > 1 ? sum_of_digits(sum) : sum
end
p sum_of_digits('12345') #=> "6"
Single call version:
def sum_of_digits(digits)
digits = digits.chars.map(&:to_i).reduce(&:+).to_s until digits.size == 1
return digits
end
It's looking good to me. You might do things a little more conscise like use map to turn every char into an integer.
def sum(n)
string=n.to_s
while string.length > 1 do
result = string.chars.map(&:to_i).inject(&:+)
string = result.to_s
end
puts "Sum of digits is " + string
end
You could also use .digits, so you don't have to convert the input into a string.
def digital_root(n)
while n.digits.count > 1
array = n.digits
n = array.sum
end
return n
end

Optimize nested loops in Ruby

In Ruby I have three nested loops:
array.each do |a|
array.each do |b|
array.each do |c|
puts a * b * c
end
end
end
How can I optimize this code, if the number of nested loops can be increased to 5-10 and more iterations?
Example:
array.each do |a|
array.each do |b|
array.each do |c|
array.each do |d|
array.each do |e|
array.each do |f|
puts a * b * c * d * e * f
end
end
end
end
end
end
You can do something like this:
array.repeated_combination(array.size).each do |combination|
puts combination.reduce(:*)
end
Array#repeated_combination returns an enumerator that yields all possible combinations.
Because this method generates all combinations before printing any output is might take a while depending on the size of the array. Keep in mind that the number of possible combinations increases quite fast: O(nⁿ) with n being the number of elements in the array.
Here are two other ways (though I prefer #spickermann's answer)
#1
array = [1,2,3]
n = 4
arr = array.product(*[array]*(n-1)).map { |arr| arr.reduce(:*) }
arr.size #=> 81 = arr.size**n
arr.each { |e| puts e }
1
2
3
2
4
6
3
6
9
...
54
27
54
81
If you just want to print the products, replace map with each and arr.reduce(:*) with puts arr.reduce(:*).
#2
sz = array.size
(0...sz**n).map { |i| i.to_s(sz)
.rjust(n,'_')
.chars
.reduce(1) { |t,e| t * (e=='_' ? 1 : array[e.to_i]) }
}

How does yield work with a block in Ruby? [duplicate]

This question already has answers here:
Blocks and yields in Ruby
(10 answers)
Closed 8 years ago.
I'm trying to understand how yield works in Ruby?
def ablock
i = 1
j = 2
yield(i, j, 3, 4)
end
ablock do |x| puts x
end
This gives me an output of -
1
2
3
4
But,
def ablock
i = 1
j = 2
yield(i, j, 3, 4)
end
ablock do |x,y| puts x, y
end
Gives me only
1
2
as the output. Why don't 3 & 4 print?
The answer is pretty simple. You have defined your block method correctly but when you go to give it a code block you only give it one variable to hold 4 objects. Instead, try giving it a variable for each object you are yielding!
def ablock
i=1
j=2
yield(i,j,3,4)
end
ablock do |i,j,k,l|
puts i
puts j
puts k
puts l
end
If you would only like to use one variable in your code block you have to do multiple yield statements(one for each object).
def ablock
i=1
j=2
yield(i)
yield(j)
yield(3)
yield(4)
end
ablock do |i|
puts i
end
Happy coding!

Start a loop from 1

I recently came upon the scary idea that Integer.count loops in Ruby start from 0 and go to n-1 while playing with the Facebook Engineering puzzlers. I did the dirty fix of adding one to the block variable in the beginning so that it would start at one instead.
Is there a prettier way?
Example:
10.times do |n|
n += 1
puts n
end #=> 012345789
Ruby supports a number of ways of counting and looping:
1.upto(10) do |i|
puts i
end
>> 1.upto(10) do |i|
> puts i
| end #=> 1
1
2
3
4
5
6
7
8
9
10
There's also step instead of upto which allows you to increment by a step value:
>> 1.step(10,2) { |i| puts i } #=> 1
1
3
5
7
9
You could use a range:
(1..10).each { |i| puts i }
Ranges give you full control over the starting and ending indexes (as long as you want to go from a lower value to a higher value).
Try
(1..10).each do |i|
# ... i goes from 1 to 10
end
instead. It is also easier to read when the value of i matters.
Old, but this might be something somebody's lookin for..
5.times.with_index(100){|i, idx| p i, idx};nil
#=>
0
100
1
101
2
102
3
103
4
104
There is of course the while-loop:
i = 1
while i<=10 do
print "#{i} "
i += 1
end
# Outputs: 1 2 3 4 5 6 7 8 9 10

Resources