Printing odd numbers in an array - ruby

I am looking to print odd numbers in an array. I have this:
numbers = []
puts "Please enter 10 numbers, one at a time."
10.times do
puts "Please enter a number"
numbers << gets.chomp.to_i
if numbers % 3 == 0
p numbers
end
numbers = numbers + 1
end
puts "Here are the numbers you selected"
p numbers
When I type in a number, I get the following:
undefined method `%' for [1]:Array
(repl):6:in `block in <main>'
Any idea as to what is happening?

Checking values modulo 3 won't work to correctly identify odd numbers. However, Ruby has a built-in method Integer#odd?. Combine this with the Array#select method, and you can quickly pick off array elements that are odd once you've read them in.
a = (1..10).to_a # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p a.select(&:odd?) # [1, 3, 5, 7, 9]
If you insist on using the modulo operator, you would check for x % 2 == 1 to check integer x for oddness:
p a.select { |x| x % 2 == 1 } # [1, 3, 5, 7, 9] again, but less efficiently
The modulo method does not work with an array as the receiver, which is what you attempted to do. That's what the error message is telling you.

Odd number is a number that when divided by two, leaves a remainder.
So in Ruby it looks like number % 2 != 0. Why do you decide to use % 3?
In your code numbers is Array, but you can use % only to numbers.
And you don't need it because in Ruby Integer has built-in method odd?. It returns true if number is odd.
You can use method .find_all or .select to your Array. Read here.
Also you use numbers = numbers + 1. It's better to write numbers += 1, it's the same. But you don't need it when use method .times. Read here.
By the way, you don't need use .chomp if your variable will be Integer, just use .to_i
So it's better to use code like this:
numbers = []
10.times do
puts 'Enter a number'
number = gets.to_i
numbers << number
end
puts "Here your odd numbers: #{numbers.find_all(&:odd?)}"

Related

bad value for range (ArgumentError) in ruby

I get the desired output but the interpreter throws an ArgumentError-bad value for range ?
Q)Given an array of integers, for each integer output all integers from 1 to that integer; e.g. if the integer was 5, you would output 1, 2, 3, 4, 5.
Solution:
numbers = [7, 3, 5, 2, 1, 8, 4]
counter = 0
loop do
num = numbers[counter]
(1..num).each do |ele|
puts ele
end
counter += 1
end
I'll let someone else explain why your code is broken, except to say that unless this is a classroom exercise (in which case ask your instructor what the point is), the code is not really idiomatic Ruby. Aside from being more complicated than it needs to be, non-idiomatic Ruby is often harder to debug. One of the following examples will do the right thing when using Ruby 3.0.1, and both are much shorter and less error-prone that manually iterating:
# if you just want to print each item
numbers = [7, 3, 5, 2, 1, 8, 4]
numbers.each { puts _1 }
# if you want to print each slice of length n
numbers.each_index do
next unless _1 > 0
p numbers.slice 0, _1
end
If you need your output in a specific format, that wasn't defined in your original question. Both of these options can be modified to suit whatever output format you're looking for.

Adding the number to the according index it is positioned in

def incrementer(num)
num.map.with_index(1) do |row, index|
if row > 9
row.to_s.reverse.chop.to_i
else
index + row
end
end
end
Hi,
I have a method which adds the number to the according index it is positioned in. However I have two rules:
The index starts at (1)
If the number is a multiple, remove the first integer off the end of it. 12 would become 2 for example.
The problem is I am unsure how to include an 'if' statement inside a block and I believe I am doing it wrong. I know there is a much better way to write this statement but I am finding it hard.
Example:
incrementer([4,6,9,1,3]) => [5,8,2,5,8]
- 9 + 3 (position of 9 in array) = 12
- Only its last digit 2 should be returned
Fixing your code
Use map followed by with_index(1), the argument offsetting the initial index by +1.
def incrementer(num)
num.map.with_index(1) do |row, index|
row = index + row
if row > 9
row.digits.first
else
row
end
end
end
incrementer [3, 2, 4, 10] #=> [4, 4, 7, 4]
incrementer [4, 6, 9, 1, 3] #=> [5, 8, 2, 5, 8]
Negative numbers
Numbers can be negative and for which we can use abs.digits but it may be better to use Integer#remainder.
def incrementer(num)
num.map.with_index(1) do |row, index|
row = index + row
case row
when -9..9
row
else
row.remainder 10
end
end
end
incrementer [3, 2, 4, 10]
#=> [4, 4, 7, 4]
incrementer [4, 6, 9, 1, 3]
#=> [5, 8, 2, 5,8]
incrementer [3, 2, 4,-17]
#=> [4, 4, 7, -3]
incrementer [4, 6, -22, 1, 3]
#=> [5, 8, -9, 5, 8]
Why not use % instead of Integer#remainder?
a % b returns a modulo b which is not the same thing as the remainder. This has consequences for negative numbers:
-12 % 10 #=> 8 not the last digit
So we need to use Integer#remainder, so:
-12.remainder 10 #=> -2
Which is what we need, i.e. the last digit (parity included). It can be noted in other languages such as JavaScript, a % b returns the remainder.
As noted by #moveson the above code can be refactored to:
num.map.with_index(1) { |row, index| (index + row).remainder 10 }
The #digits method requires Rails or ActiveSupport (or Ruby 2.4+), and it's not necessary. Here is a pure Ruby solution that works with any Ruby version:
def incrementer(array)
array.map.with_index(1) { |integer, index| (integer + index) % 10 }
end
This code above says: For each element of the array, add its index (starting from 1), divide the sum by 10, and return the remainder.
The % (modulo) operator divides the number before it by the number after it and returns the remainder. For example, 22 % 7 returns 1. It's an extremely useful tool and can often help avoid the use of conditionals entirely, such as in your example. Using %, you can get the last digit of a number n (whether or not n is greater than 9) by simply taking n % 10.
Now you can do:
>> incrementer([3,2,4,10])
=> [4, 4, 7, 4]
>> incrementer([4,6,9,1,3])
=> [5, 8, 2, 5, 8]
You've got two separate problems. The first problem is your use of each_with_index. Ruby functions return the value of the last expression they execute, so if you look at your function:
def incrementer(num)
num.each_with_index do |row, index|
# do some stuff
end
end
It essentially calls each_with_index and returns the value. The issue here is that each_with_index iterates over an array and then returns the original array. What you want to do is change each item in the array and return a new array with the new values. For this, you can use map:
def incrementer(num)
num.map.with_index(1) do |row, index|
# do some stuff
end
end
In this case, you can even conveniently pass in the parameter 1 to tell the iterator to start at index 1.
Now the second problem is that your if-else-statement either iterates a number or wraps it around. But what you actually want to do is iterate a number and wrap it around if it's bigger than 9. You can do that like so:
def incrementer(num)
num.map.with_index(1) do |row, index|
row = index + row
if row > 9
row.to_s.reverse.chop.to_i
else
row
end
end
end
What we're doing here is iterating the number first, saving it into row and then checking to see if it's over 9. If it is, we return the last digit; otherwise, we just return the value row.
This code will do what you want, but let's make one more change for the sake of clarity. This code:
row.to_s.reverse.chop.to_i
Is a little bit confusing. Ruby 2.4 has a convenient method for getting at the digits of an integer:
row.digits.first
This is easy to read, but it's a bit slow since it turns an integer into an array of integers. A better way is to use modulus % to get the remainder of your number, divided by 10. This is fast and easy to read for most programmers, since it's a common trick.
row % 10
Putting it all together, you get:
def incrementer(num)
num.map.with_index(1) do |row, index|
row = index + row
if row > 9
row % 10
else
row
end
end
end
Special thanks to (#sagarpandya84) and (#moveson) for allowing me to build on their answers.

Ruby: Avoiding infinite loop in an array that doubles each number

So there is an infinte loop here, but I'm not seeing it.
# Return an array that doubles each number
numbers = [1, 2, 3, 4]
numbers.each do |number|
numbers << number * 2
end
puts numbers
I understand there are shorter ways to do this, but I am learning so it's all written out more explicitly.
You're adding elements to an array while iterating over that array. It's therefore impossible to reach the end.
What you need to do is use the map function:
numbers.map! do |n|
n * 2
end
That updates each entry in place with its value times two.
If you're looking to add on a single set of doubled numbers:
numbers += numbers.map do |n|
n * 2
end
That adds on a copy of the array that's been doubled.
Edit: Instead of using map, for academic illustration purposes, you can try using a copy with dup:
numbers.dup.each do |n|
numbers << n * 2
end
You can also iterate over it sequentially:
numbers.each_index do |i|
numbers << numbers[i] * 2
end
These are all far less efficient and are much harder to read than the map version.
You cant see the process since this infinity lasts forever and never reaches your puts numbers statement. Thats why you cant see it in the console.
Try something like:
numbers = [1, 2, 3, 4]
numbers.each do |number|
numbers << number * 2
puts numbers
end
To see your pc going mad :)
by pushing the doubled value in the array you are increasing the array size each time by 1. hence infinite loop is occurring. I think what you really want to do is
numbers.each do |num|
puts num *2
end
Return an array that doubles each number
Assuming you don't want to use map, you can use Enumerable#each_with_object:
numbers = [1, 2, 3, 4]
numbers.each_with_object([]) { |n, o| o << n + n }
#=> [2, 4, 6, 8]
Since nobody mentioned the obvious answer, here it is :
numbers = [1, 2, 3, 4]
double_numbers = []
numbers.each do |number|
double_numbers << number * 2
end
p double_numbers
# [2, 4, 6, 8]
This would be the way to do it if you didn't know about map or map!. Note that you iterate on one array and create another one in order to avoid messing with the each loop.

Arithmetic series in Ruby

I am trying to write a function in ruby that returns "Arithmetic" when the input is an arithmetic series array(the delta between a number and the consecutive number in the array is the same across the array). Here's what I have for so far:
array = [1,3,5,7,9] #arithmetic series input example
array.each_cons(2).map {|x,y| y - x == array[2] - array[1]}
This returns the following
[true,true,true,true,true]
My goal is to write a function that identifies what kind of series the array is, if there is one at all. Here's what I am trying to build
def isarithemetic(array)
if array.each_cons(2).map {|x,y| y - x == array[2] - array[1]} == true
return "arithmetic"
I am open to new suggestions as well.
If an array arr contains integer values, those (ordered) values comprise at most one arithmetic expression. If the average interval is integer-valued (i.e.,
((arr.last-arr.first) % (arr.size-1).zero?
is true), a unique progression is given by the values of arr.first, arr.last and arr.size, namely:
avg_interval = (arr.last-arr.first)/(arr.size-1)
(arr.first..arr.last).step(avg_interval).to_a
If the average interval is not integer-valued, it cannot be an arithmetic progression, but we don't need to check that condition. That's because by using integer arithmetic to compute avg_interval, the resulting arithmetic progression cannot equal arr if the average interval is not integer-valued.
Hence, rather than check if all the intervals are equal, we could just check to see if the above arithmetic progression equals arr.
Code
def arithmetic_progression?(arr)
return true if arr.size < 2
(arr.first..arr.last).step((arr.last-arr.first)/(arr.size-1)).to_a == arr
end
Examples
arithmetic_progression?([1,3,5,7,9]) #=> true
arithmetic_progression?([1,3,5,7,8]) #=> false
In the first example:
arr = [1,3,5,7,9]
avg_interval = (arr.last-arr.first)/(arr.size-1) #=> 2
(arr.first..arr.last).step(avg_interval).to_a #=> [1, 3, 5, 7, 9]
In the second:
arr = [1,3,5,7,8]
avg_interval = (arr.last-arr.first)/(arr.size-1) #=> 1
(arr.first..arr.last).step(avg_interval).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8]
You could then write, for example:
arithmetic_progression?([1,3,5,7,9]) ? "Arithmetic progression" :
"Not arithmetic progression" #=> "Arithmetic progression"
Variant
The method could probably be made slightly more efficient by inserting the following line after the first line of the method:
return false unless ((arr.last-arr.first) % (arr.size-1)).zero?
You should be able to do this using all?:
array.each_cons(2).map {|x,y| y - x == array[2] - array[1]}.all?
or perhaps
array.each_cons(2).all? {|x,y| y - x == array[2] - array[1]}

How do I iterate through the digits of an integer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Turning long fixed number to array Ruby
Well, I have to iterate over the digits of a integer in Ruby. Right now I was just splitting it up into an array, and then iterating over that. However I was wondering if there was a faster way to do this?
The shortest solution probably is:
1234.to_s.chars.map(&:to_i)
#=> [1, 2, 3, 4]
A more orthodox mathematical approach:
class Integer
def digits(base: 10)
quotient, remainder = divmod(base)
quotient == 0 ? [remainder] : [*quotient.digits(base: base), remainder]
end
end
0.digits #=> [0]
1234.digits #=> [1, 2, 3, 4]
0x3f.digits(base: 16) #=> [3, 15]
You can use the old trick of modulus/divide by 10, but this won't be measurably faster unless you have huge numbers, and it will give the digits to you backwards:
i = 12345
while i > 0
digit = i % 10
i /= 10
puts digit
end
Output:
5
4
3
2
1
split=->(x, y=[]) {x < 10 ? y.unshift(x) : split.(x/10, y.unshift(x%10))}
split.(1000) #=> [1,0,0,0]
split.(1234) #=> [1,2,3,4]
Ruby has divmod, which will calculate both x%10and x/10 in one go:
class Integer
def split_digits
return [0] if zero?
res = []
quotient = self.abs #take care of negative integers
until quotient.zero? do
quotient, modulus = quotient.divmod(10) #one go!
res.unshift(modulus) #put the new value on the first place, shifting all other values
end
res # done
end
end
p 135.split_digits #=>[1, 3, 5]
For things like Project Euler, where speed is of some importance, this is nice to have. Defining it on Integer causes it to be available on Bignum too.
I like to use enumerators for this purpose:
class Integer
def digits
to_s.each_char.lazy.map(&:to_i)
end
end
This gives you access to all the good Enumerator stuff:
num = 1234567890
# use each to iterate over the digits
num.digits.each do |digit|
p digit
end
# make them into an array
p num.digits.to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
# or take only some digits
p num.digits.take(5) # => [1, 2, 3, 4, 5]
# ...
Try mod by 10 (will give you the last digit), then divide by 10 (will give you the rest of digits), repeat this until you're down to the final digit. Of course, you'll have to reverse the order if you want to go through the digits from left to right.

Resources