0

I'm trying to automate a test. Is there a better approach to solving this? I'm trying to create an array that only contains multiples of three and nothing else.

(1...100).each_with_object([]) { |i, a| a << i if i % 3 == 0 }.reject { |i| i % 5 == 0 }
4
  • I'm not quite sure what series of numbers you're after, but every number which is evenly divisible by 3 is evenly divisible by another number. If x divides evenly by 3 to give y, x will divide evenly by y to give 3. There are no numbers except for 3 and 9 which meet your criteria of being "multiples of 3 and nothing else" and that's assuming you'll disregard that every number is a multiple of 1. Commented Mar 6, 2014 at 3:39
  • I had an interview that involved doing FizzBuzz with RSpec. I came up with a good solution, but I didn't have time to automate my tests. I want to ensure that this array I would create would only print "Fizz" for multiples of three and three alone. I would do the same thing for multiples of five. Instead of saying: [3, 6, 9].each { |x| expect(fizzbuzz(x)).to eq('Fizz') } Commented Mar 6, 2014 at 3:42
  • @meagar: "(multiples of three) and nothing else". not "multiples of (three and nothing else)". :) Commented Mar 6, 2014 at 3:42
  • @Amadan I thought the rejecting multiples of 5 was the beginning of attempting to filter out all the numbers that were multiples of something besides 3, which would have left a pretty empty array. Commented Mar 6, 2014 at 3:46

3 Answers 3

2

Why not map the digits 1 to 33 by multiplying each by three, then rejecting the multiples of 5?

(1..33).map { |i| i * 3 }.reject { |i| i % 5 == 0 }
Sign up to request clarification or add additional context in comments.

2 Comments

I totally forgot about map! Thanks for that insight.
+1 for map and lowering the number of enumerations.You could even do even (1.33).map{|i| i * 3 unless i * 3 % 5 ==0}.compact!
1

I'm trying to create an array that only contains multiples of three and nothing else.

Using the Numeric#step enumerator:

3.step(100, 3).to_a

creates all multiples of three up to 100.

Your code seems to have an additional effect of filtering out the fives too. You can filter them out:

3.step(100, 3).reject { |i| i % 5 == 0 }

Or you can do something completely different:

require 'set'
((1..100).to_set - 3.step(100, 3) - 5.step(100, 5)).to_a

A bit more legible than the reject way, but probably a bit slower.

2 Comments

I've never used step, very cool. You taught me something new. :-)
(1..100).to_set can also be written Set.new(1..100). I wasn't aware that to_set could be used to convert an Enumerable object (and, hence, Enumerator objects such as 3.step(100,3), since Enumerator includes Enumerable) to a set, but [that it does](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/set/rdoc/Set.html), but I still don't understand why there is no Enumerable#to_set. I only find Set.to_set`.
0

A million and 1 ways to iterate in ruby

(1..100).collect{|i| i if i % 3 == 0 && i % 5 != 0}.compact!
(1..100).select{|i| i if i % 3 == 0 && i % 5 != 0}

Here's another one and it reads really nicely

(1..100).find_all{|i| i % 3 ==0 && i % 5 !=0}

2 Comments

collect doesn't really fit here; use select or reject
fair enough since I have to call compact! added select as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.