i am currently studying ruby and your help would be much appreciated.
i am trying to display the below results in my terminal:
1
2
3 i am divisible by 3
4
5 i am divisible by 5
6 i am divisible by 3
7
8
9 i am divisible by 3
10 i am divisible by 5
11
12 i am divisible by 3
13
14
15 i am divisible by 3 and 5
16
17
18 i am divisible by 3
19
20 i am divisible by 5
i am unsure how to go about. I wrote the below code in my divisible.rb:
def count
numbers = (1..20)
numbers.each do |number|
if number % 1 == 1
puts "#{number}"
elsif number % 3 == 0
puts "#{number} i am divisible by 3"
elsif number % 5 == 0
puts "#{number} i am divisible by 5"
elsif number % 3 == 0 && number % 5 == 0
puts "#{number} i am divisible by 3 & 5"
end
end
end
but it outputs the below in the terminal:
irb(main):001:0> count
3 i am divisible by 3
5 i am divisible by 5
6 i am divisible by 3
9 i am divisible by 3
10 i am divisible by 5
12 i am divisible by 3
15 i am divisible by 3
18 i am divisible by 3
20 i am divisible by 5
=> 1..20
could one please kindly advise me on the right path
There are 3 steps to fix it
Remove 1st if statement,
You should move this: elsif number % 3 == 0 && number % 5 == 0 to 1st step
Add else puts number
it should look like:
def count
numbers = (1..20)
numbers.each do |number|
if number % 3 == 0 && number % 5 == 0
puts "#{number} i am divisible by 3 & 5"
elsif number % 3 == 0
puts "#{number} i am divisible by 3"
elsif number % 5 == 0
puts "#{number} i am divisible by 5"
else
puts number
end
end
end
UPD
Let's add an explanation about these steps:
1st and 3rd steps:
Dividing by 1 always will return 0 as a result, so the first reason is a mistake in logic and the second one is as now we know that this always is 0 we don't need to check it one more time.
2nd step:
When we check for example 3 with elsif number % 3 == 0 it will return true, so next if-statements wouldn't be checked, to fix it we should first add checking for number % 3 == 0 && number % 5 == 0
Thanks to #3limin4t0r, you are right it's always better to explain.
Just for fun, you could use the Prime class from standard lib, this way:
require 'prime'
(0..30).each do |number|
if [0, 1].include? number
puts number
next
end
if Prime.prime?(number)
puts "#{number} is prime"
else
divisors = Prime.prime_division(number).map(&:first)
puts "#{number} is divisible by " + divisors.join(" and ") if divisors.size > 1
end
end
Related
If we list all natural numbers less than 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all numbers less than 1000, multiples of 3 or 5.
I just started learning Ruby, I used to work only with C languages. Please explain why this code doesn't work. Thank you!!!
Code:
sum = 0;
i = 3;
while (i < 1000) do
if ((i % 3 == 0) || (i % 5 == 0))
sum += i;
end
end
puts "The sum of all the multiples of 3 or 5 below 1000: #{sum}"
And when I run the file, it loads indefinitely.
enter image description here
You are never incrementing i.
The while loop will terminate if: i >= 1000
But i = 3 and there is no i+=1 so this loop will never terminate.
#Raavgo has explained the problem with your code. If you are looking for a fast solution I suggest the following.
def tot(n, limit)
m, rem = limit.divmod(n)
m * (n + limit - rem)/2
end
tot(3, 999) + tot(5, 999) - tot(15, 999)
#=> 233168
The term tot(15, 999) is to compensate for double-counting of terms that are divisible by both 3 and 5.
See Numeric#divmod.
Suppose
n = 5
limit = 999
Then
m, rem = limit.divmod(n)
#=> [199, 4]
So
m #=> 199
rem #=> 4
Then we want to compute
5 + 10 + ... + 999 - rem
#=> 5 + 10 + ... + 995
This is simply the the sum of an arithmetic progression:
199 * (5 + 995)/2
which equals
m * (n + limit - rem)/2
(0..1000).select(&->(i){ (i % 3).zero? || (i % 5).zero? }).sum
(0..1000).filter { |i| i % 3 == 0 || i % 5 == 0 }.sum
your approach is fine if you increment i as said in the other answer, but a more idiomatic Ruby looks like this.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.
def multiples_of(number)
number = number.to_f - 1.0
result = 0
if (number / 5.0) == 1 || (number / 3.0) == 1
return result = result + 5.0 + 3.0
elsif (number % 3).zero? || (number % 5).zero?
result += number
multiples_of(number-1)
else
multiples_of(number-1)
end
return result
end
p multiples_of(10.0)
My code is returning 9.0 rather than 23.0.
Using Core Methods to Select & Sum from a Range
It's not entirely clear what you really want to do here. This is clearly a homework assignment, so it's probably intended to get you to think in a certain way about whatever the lesson is. If that's the case, refer to your lesson plan or ask your instructor.
That said, if you restrict the set of possible input values to integers and use iteration rather than recursion, you can trivially solve for this using Array#select on an exclusive Range, and then calling Array#sum on the intermediate result. For example:
(1...10).select { |i| i.modulo(3).zero? || i.modulo(5).zero? }.sum
#=> 23
(1...1_000).select { |i| i.modulo(3).zero? || i.modulo(5).zero? }.sum
#=> 233168
Leave off the #sum if you want to see all the selected values. In addition, you can create your own custom validator by comparing your logic to an expected result. For example:
def valid_result? range_end, checksum
(1 ... range_end).select do |i|
i.modulo(3).zero? || i.modulo(5).zero?
end.sum.eql? checksum
end
valid_result? 10, 9
#=> false
valid_result? 10, 23
#=> true
valid_result? 1_000, 233_168
#=> true
There are a number of issues with your code. Most importantly, you're making recursive calls but you aren't combining their results in any way.
Let's step through what happens with an input of 10.
You assign number = number.to_f - 1.0 which will equal 9.
Then you reach the elsif (number % 3).zero? || (number % 5).zero? condition which is true, so you call result += number and multiples_of(number-1).
However, you're discarding the return value of the recursive call and call return result no matter what. So, your recursion doesn't have any impact on the return value. And for any input besides 3 or 5 you will always return input-1 as the return value. That's why you're getting 9.
Here's an implementation which works, for comparison:
def multiples_of(number)
number -= 1
return 0 if number.zero?
if number % 5 == 0 || number % 3 == 0
number + multiples_of(number)
else
multiples_of(number)
end
end
puts multiples_of(10)
# => 23
Note that I'm calling multiples_of(number) instead of multiples_of(number - 1) because you're already decrementing the input on the function's first line. You don't need to decrement twice - that would cause you to only process every other number e.g. 9,7,5,3
explanation
to step throgh the recursion a bit to help you understand it. Let's say we have an input of 4.
We first decrement the input so number=3. Then we hits the if number % 5 == 0 || number % 3 == 0 condition so we return number + multiples_of(number).
What does multiples_of(number) return? Now we have to evaluate the next recursive call. We decrement the number so now we have number=2. We hit the else block so now we'll return multiples_of(number).
We do the same thing with the next recursive call, with number=1. This multiples_of(1). We decrement the input so now we have number=0. This matches our base case so finally we're done with recursive calls and can work up the stack to figure out what our actual return value is.
For an input of 6 it would look like so:
multiples_of(6)
\
5 + multiples_of(5)
\
multiples_of(4)
\
3 + multiples_of(3)
\
multiples_of(2)
\
multiples_of(1)
\
multiples_of(0)
\
0
The desired result can be obtained from a closed-form expression. That is, no iteration is required.
Suppose we are given a positive integer n and wish to compute the sum of all positive numbers that are multiples of 3 that do not exceed n.
1*3 + 2*3 +...+ m*3 = 3*(1 + 2 +...+ m)
where
m = n/3
1 + 2 +...+ m is the sum of an algorithmic expression, given by:
m*(1+m)/2
We therefore can write:
def tot(x,n)
m = n/x
x*m*(1+m)/2
end
For example,
tot(3,9) #=> 18 (1*3 + 2*3 + 3*3)
tot(3,11) #=> 18
tot(3,12) #=> 30 (18 + 4*3)
tot(3,17) #=> 45 (30 + 5*3)
tot(5,9) #=> 5 (1*5)
tot(5,10) #=> 15 (5 + 2*5)
tot(5,14) #=> 15
tot(5,15) #=> 30 (15 + 3*5)
The sum of numbers no larger than n that are multiple of 3's and 5's is therefore given by the following:
def sum_of_multiples(n)
tot(3,n) + tot(5,n) - tot(15,n)
end
- tot(15,n) is needed because the first two terms double-count numbers that are multiples of 15.
sum_of_multiples(9) #=> 23 (3 + 6 + 9 + 5)
sum_of_multiples(10) #=> 33 (23 + 2*5)
sum_of_multiples(11) #=> 33
sum_of_multiples(12) #=> 45 (33 + 4*3)
sum_of_multiples(14) #=> 45
sum_of_multiples(15) #=> 60 (45 + 3*5)
sum_of_multiples(29) #=> 195
sum_of_multiples(30) #=> 225
sum_of_multiples(1_000) #=> 234168
sum_of_multiples(10_000) #=> 23341668
sum_of_multiples(100_000) #=> 2333416668
sum_of_multiples(1_000_000) #=> 233334166668
I am asking the user to input a number and evaluate that number to see if it's divisible by 3.
this is my code
positive_integer = gets.chomp
if positive_integer % 3 == 0
puts "#{positive_integer} is divisible by 3"
elsif
puts "#{positive_integer} is not divisible by 3"
end
But for some reason when I input 9, 30, or any number that IS divisible by three I get "#{positive_integer} is not divisible by 3" output.
What am I doing wrong
your variable positive_integer is a string. convert it into integer by
positive_integer = gets.chomp.to_i
So i have the following 2 program:
1st program, which works as intended( Ex: input 7, output Number is prime
puts "Enter a positive number: "
number = gets.chomp.to_i
prime = true
i = 2
while i <= number/2
if number % i == 0
prime = false
end
i += 1
end
if prime == true
puts "Number is prime"
else
puts "Number is not prime"
end
2nd program, which is basically the same, just added the user the ability to check for prime numbers in a range. This program only shows 2 and 3 as prime numbers(if input is 10, for example)
puts "Enter a positive number: "
range = gets.chomp.to_i
prime = true
i = 2
number = 2
while number <= range
while i <= number/2
if number % i == 0
prime = false
end
i += 1
end
if prime == true
puts "#{number} is prime"
else
puts "#{number} is not prime"
end
number += 1
end
I think the problem is with the way im incrementing, since i can't use a for, but i tried debugging and i just don't get it, it should print out 5 and 7 aswell, if i input 10 as my range of numbers.
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