7
\$\begingroup\$

The title says it all. This is yet another FizzBuzz implementation where you can specify the words you want to use, though it autoselects the divisors as the first n primes other than 2, rather than having you enter them.

I'm looking for tips on variable/function naming and that kind of thing; I couldn't think of good ones when I wrote this. I'd also like any performance improvements that can be put in.

def n_primes(count)
 primes = []
 number = 2
 until primes.length == count
 primes << number if primes.inject(true) { |memo, cur| memo and number % cur != 0 }
 number += 1
 end
 primes
end
puts 'Enter the words you would like to use'
word_array = gets.chomp.split
puts 'Enter the number to count up to'
up_to = gets.chomp.to_i
words = {}
primes = n_primes(word_array.length + 1)[1..-1]
primes.each_with_index { |prime, index| words[prime] = word_array[index] }
1.upto(up_to) do |number|
 to_print = words.reject { |n, _| number % n != 0 }.values
 to_print = [number] if to_print.length == 0
 puts to_print.join ''
end

Note: I extracted n_primes into a function because it means I don't have to use meaningless names like p or num to avoid naming conflicts. If there's a better solution, I'd like to know it.

Sample output:

Enter the words you would like to use
> Fizz Buzz Wolf Foo Bar
Enter the number to count up to
> 100
1
2
Fizz
4
Buzz
Fizz
Wolf
8
Fizz
Buzz
Foo
Fizz
Bar
Wolf
FizzBuzz
16
17
Fizz
19
Buzz
FizzWolf
Foo
23
Fizz
Buzz
Bar
Fizz
Wolf
29
FizzBuzz
31
32
FizzFoo
34
BuzzWolf
Fizz
37
38
FizzBar
Buzz
41
FizzWolf
43
Foo
FizzBuzz
46
47
Fizz
Wolf
Buzz
Fizz
Bar
53
Fizz
BuzzFoo
Wolf
Fizz
58
59
FizzBuzz
61
62
FizzWolf
64
BuzzBar
FizzFoo
67
68
Fizz
BuzzWolf
71
Fizz
73
74
FizzBuzz
76
WolfFoo
FizzBar
79
Buzz
Fizz
82
83
FizzWolf
Buzz
86
Fizz
Foo
89
FizzBuzz
WolfBar
92
Fizz
94
Buzz
Fizz
97
Wolf
FizzFoo
Buzz

(The user input is prefixed with >, though it doesn't show up when you actually run the code)

asked Jun 6, 2015 at 4:01
\$\endgroup\$

1 Answer 1

7
\$\begingroup\$
  • #n_primes

    Ruby has the Prime class as part of its stdlib, so you don't need to roll your own prime number generator.

  • n_primes(word_array.length + 1)[1..-1]

    A more Rubyesque version might use drop(1) instead of the [1..-1] slice.

  • words = {} + primes.each_with_index

    Instead of creating an empty Hash and then adding elements to it, you can use Array#zip to create an array of word/number pairs. You can turn that into a hash with Hash[], if you'd like.

  • words.reject

    Purely from a semantic standpoint, I think select would be more natural to use. I think of it as "finding the words to print" rather than "discarding the words that shouldn't be printed" which sounds like a double negative.

    You could also consider using #inject or #each_with_object to collect matches instead of #reject + #values

  • to_print.length == 0

    Use Array#empty? instead.

  • to_print.join ''

    You don't need the argument for Array#join.

I'd do this:

require "prime"
puts "Enter the words you would like to use (separated by spaces)"
words = gets.strip.split
puts "Enter the number to count up to"
count = gets.strip.to_i
pairs = Prime.first(words.count + 1).drop(1).zip(words)
1.upto(count) do |n|
 line = pairs.each_with_object([]) do |(prime, word), memo|
 memo << word if (n % prime).zero?
 end
 puts line.empty? ? n : line.join
end

Or, more in line with yours, the last part could be:

1.upto(count) do |n|
 line = pairs.select { |prime, _| (n % prime).zero? }.map(&:last)
 puts line.empty? ? n : line.join
end
answered Jun 6, 2015 at 10:30
\$\endgroup\$
5
  • \$\begingroup\$ I updated the doc link in your answer from 1.9.3 (IIRC) to 2.2.2, if you wanna accept the suggestion ;) \$\endgroup\$ Commented Jun 6, 2015 at 20:14
  • \$\begingroup\$ @QPaysTaxes Approved - I actually wanted to link to a newer one, but there was something weird going on with ruby-docs, and some of the 2.x doc pages kept saying "You've entered the forbidden area!"... with little in the way of explanation :) \$\endgroup\$ Commented Jun 6, 2015 at 20:17
  • \$\begingroup\$ @QPaysTaxes I just meant "a newer version than the 1.9 one I ended up posting" - not that the Prime class has changed very much in terms of API over the years, so it's not a huge deal either way. And oddly, the answer appears as accepted here, and I got some rep too (thanks!) \$\endgroup\$ Commented Jun 6, 2015 at 20:20
  • \$\begingroup\$ Oh, that makes sense. The API doc bit, at least. Still showing as not accepted here, and I've refreshed at least twice... Eh, I don't mind, so long as you get the rep \$\endgroup\$ Commented Jun 6, 2015 at 20:21
  • \$\begingroup\$ It's showing now... Odd. Still, unplugging the internet seems fun. BRB! \$\endgroup\$ Commented Jun 6, 2015 at 20:25

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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