I have an array of 1000 numbers, randomly generated. 10 of those numbers must be between 0-9 (including 0 and 9), and 10 of those numbers must be between 991 and 1000 (including 991 and 1000). This is what I came up with:
arr = []
980.times do
arr << (11..989).to_a.sample
end
arr2 = []
10.times do
arr2 << rand(10)
end
arr3 = []
10.times do
arr3 << (990..1000).to_a.sample
end
arr4 = []
arr4 = arr + arr2 + arr3
arr4.shuffle
Is there a more elegant way to do this in ruby?
-
\$\begingroup\$ Is it only 10 for ranges at the end or "at least 10"? \$\endgroup\$Fred the Magic Wonder Dog– Fred the Magic Wonder Dog2013年12月14日 17:45:17 +00:00Commented Dec 14, 2013 at 17:45
2 Answers 2
Some notes:
Try to learn some functional programming, you shouldn't write Ruby as it were a low-level language (like C). Favor expressions over statements. My 2-cents on the matter, I hope it helps: http://www.slideshare.net/tokland/functional-programming-with-ruby-9975242
Let me show a simple example of using FP. The first 4 lines of your code could be written like this:
arr = 980.times.map { (11..989).to_a.sample }
arr4 = []
: Why? the next line assigns it to another expression.range.to_a.sample
. That's very inefficient, betterrand(range)
.
I'd write:
ranges = [0..9, 11..989, 990..1000]
output = ranges.flat_map do |range|
range.map { rand(range) }
end.shuffle
-
\$\begingroup\$ I can't improve on your "I'd write:", but here's a variant:
ranges.reduce([]) {|arr, range| arr + Array.new(range.size) {rand(range)}}.shuffle
\$\endgroup\$Cary Swoveland– Cary Swoveland2014年01月08日 07:54:37 +00:00Commented Jan 8, 2014 at 7:54 -
\$\begingroup\$ @CarySwoveland: Not that efficiency is important here (those are small arrays), but note that
reduce
with+
leads to O(n^2) code. \$\endgroup\$tokland– tokland2014年01月08日 09:38:42 +00:00Commented Jan 8, 2014 at 9:38
Be careful at the boundaries — you didn't implement what you wanted. The output will never contain 10, and it might include 990 among the [991, 1000] range.