How do I split arrays using a while loop? - ruby

I want to write a program that splits an array into two arrays, where any element in one array is smaller than any element in the other array.
The input that I have is:
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
And I'd like output like this:
[6, 23, 17, 18 , 9] < [45, 65, 48, 97, 32, 88]
I've tried:
i = 0
max = 0
while i < a.size
if a[i] > max
max = a[i]
end
i+=1
end
puts "this is the larger array: " + max.to_s
Which is completely off. As I am new to this, any help is appreciated.

small, large = a.sort!.shift(a.size/2) ,a
p small, large
#=> [6, 9, 17, 18, 23]
#=> [32, 45, 48, 65, 88, 97]

Try this:
newarray = a.sort.each_slice((a.size/2.0).round).to_a
It will give you an array containing your split array:
newarray = [[6,9,17,18,23,32],[45,48,65,88,97]]
In this case, if you have an odd number of elements in your array, the first array returned will always have the extra element. You can also save the arrays separately if you would like, but this way you can call each of the halves with newarray[0] and newarray[1]. If you want to split them simply add:
b = newarray[0]
c = newarray[1]

Don't use a while loop - sort the array and then split it in two
a.sort
a.in_groups_of( a.size/2)
a.sort.each_slice( a.size/2) probably does the trick without rails.

a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
a = a.sort
print a.shift(a.count/2), " < " , a
#=> [6, 9, 17, 18, 23] < [32, 45, 48, 65, 88, 97]
Another variation
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
a = a.sort
print a.values_at(0..a.count/2), " < ", a.values_at((a.count/2)+1 .. -1)
#=> [6, 9, 17, 18, 23] < [32, 45, 48, 65, 88, 97]

Assuming you want to preserve order, as in your example:
def split_it(a,n)
f = a.select {|e| e <= n}
[f, a-f]
end
a = [6, 45, 23, 65, 17, 48, 97, 32, 18, 9, 88]
f, l = split_it(a,23)
puts "#{f} < #{l}" # => [6, 23, 17, 18, 9] < [45, 65, 48, 97, 32, 88]
If you want to preserve order and have the first subarray contain nbr elements, add this:
def split_nbr(a, nbr)
n = 1
loop do
return [] if n > a.max
b = split_it(a,n)
return b if b.first.size == nbr
n += 1
end
end
f, l = split_nbr(a,3)
puts "#{f} < #{l}" # => [6, 17, 9] < [45, 23, 65, 48, 97, 32, 18, 88]

Related

Algorithm - longest wiggle subsequence

Algorithm:
A sequence of numbers is called a wiggle sequence if the differences
between successive numbers strictly alternate between positive and
negative. The first difference (if one exists) may be either positive
or negative. A sequence with fewer than two elements is trivially a
wiggle sequence.
For example, [1,7,4,9,2,5] is a wiggle sequence because the
differences (6,-3,5,-7,3) are alternately positive and negative. In
contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the
first because its first two differences are positive and the second
because its last difference is zero.
Given a sequence of integers, return the length of the longest
subsequence that is a wiggle sequence. A subsequence is obtained by
deleting some number of elements (eventually, also zero) from the
original sequence, leaving the remaining elements in their original
order.
Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.
Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].
Input: [1,2,3,4,5,6,7,8,9]
Output: 2
My soln:
def wiggle_max_length(nums)
[ build_seq(nums, 0, 0, true, -1.0/0.0),
build_seq(nums, 0, 0, false, 1.0/0.0)
].max
end
def build_seq(nums, index, len, wiggle_up, prev)
return len if index >= nums.length
if wiggle_up && nums[index] - prev > 0 || !wiggle_up && nums[index] - prev < 0
build_seq(nums, index + 1, len + 1, !wiggle_up, nums[index])
else
build_seq(nums, index + 1, len, wiggle_up, prev)
end
end
This is working for smaller inputs (e.g [1,1,1,3,2,4,1,6,3,10,8] and for all the sample inputs, but its failing for very large inputs (which is harder to debug) like:
[33,53,12,64,50,41,45,21,97,35,47,92,39,0,93,55,40,46,69,42,6,95,51,68,72,9,32,84,34,64,6,2,26,98,3,43,30,60,3,68,82,9,97,19,27,98,99,4,30,96,37,9,78,43,64,4,65,30,84,90,87,64,18,50,60,1,40,32,48,50,76,100,57,29,63,53,46,57,93,98,42,80,82,9,41,55,69,84,82,79,30,79,18,97,67,23,52,38,74,15]
which should have output: 67 but my soln outputs 57. Does anyone know what is wrong here?
The approach tried is a greedy solution (because it always uses the current element if it satisfies the wiggle condition), but this does not always work.
I will try illustrating this with this simpler counter-example: 1 100 99 6 7 4 5 2 3.
One best sub-sequence is: 1 100 6 7 4 5 2 3, but the two build_seq calls from the algorithm will produce these sequences:
1 100 99
1
Edit: A slightly modified greedy approach does work -- see this link, thanks Peter de Rivaz.
Dynamic Programming can be used to obtain an optimal solution.
Note: I wrote this before seeing the article mentioned by #PeterdeRivaz. While dynamic programming (O(n2)) works, the article presents a superior (O(n)) "greedy" algorithm ("Approach #5"), which is also far easier to code than a dynamic programming solution. I have added a second answer that implements that method.
Code
def longest_wiggle(arr)
best = [{ pos_diff: { length: 0, prev_ndx: nil },
neg_diff: { length: 0, prev_ndx: nil } }]
(1..arr.size-1).each do |i|
calc_best(arr, i, :pos_diff, best)
calc_best(arr, i, :neg_diff, best)
end
unpack_best(best)
end
def calc_best(arr, i, diff, best)
curr = arr[i]
prev_indices = (0..i-1).select { |j|
(diff==:pos_diff) ? (arr[j] < curr) : (arr[j] > curr) }
best[i] = {} if best.size == i
best[i][diff] =
if prev_indices.empty?
{ length: 0, prev_ndx: nil }
else
prev_diff = previous_diff(diff)
j = prev_indices.max_by { |j| best[j][prev_diff][:length] }
{ length: (1 + best[j][prev_diff][:length]), prev_ndx: j }
end
end
def previous_diff(diff)
diff==:pos_diff ? :neg_diff : :pos_diff·
end
def unpack_best(best)
last_idx, last_diff =
best.size.times.to_a.product([:pos_diff, :neg_diff]).
max_by { |i,diff| best[i][diff][:length] }
return [0, []] if best[last_idx][last_diff][:length].zero?
best_path = []
loop do
best_path.unshift(last_idx)
prev_index = best[last_idx][last_diff][:prev_ndx]
break if prev_index.nil?
last_idx = prev_index·
last_diff = previous_diff(last_diff)
end
best_path
end
Examples
longest_wiggle([1, 4, 2, 6, 8, 3, 2, 5])
#=> [0, 1, 2, 3, 5, 7]]
The length of the longest wiggle is 6 and consists of the elements at indices 0, 1, 2, 3, 5 and 7, that is, [1, 4, 2, 6, 3, 5].
A second example uses the larger array given in the question.
arr = [33, 53, 12, 64, 50, 41, 45, 21, 97, 35, 47, 92, 39, 0, 93, 55, 40, 46,
69, 42, 6, 95, 51, 68, 72, 9, 32, 84, 34, 64, 6, 2, 26, 98, 3, 43, 30,
60, 3, 68, 82, 9, 97, 19, 27, 98, 99, 4, 30, 96, 37, 9, 78, 43, 64, 4,
65, 30, 84, 90, 87, 64, 18, 50, 60, 1, 40, 32, 48, 50, 76, 100, 57, 29,
arr.size 63, 53, 46, 57, 93, 98, 42, 80, 82, 9, 41, 55, 69, 84, 82, 79, 30, 79,
18, 97, 67, 23, 52, 38, 74, 15]
#=> 100
longest_wiggle(arr).size
#=> 67
longest_wiggle(arr)
#=> [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 16, 17, 19, 21, 22, 23, 25,
# 27, 28, 29, 30, 32, 34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 47, 49, 50,
# 52, 53, 54, 55, 56, 57, 58, 62, 63, 65, 66, 67, 70, 72, 74, 75, 77, 80,
# 81, 83, 84, 90, 91, 92, 93, 95, 96, 97, 98, 99]
As indicated, the largest wiggle is comprised of 67 elements of arr. Solution time was essentially instantaneous.
The values of arr at those indices are as follows.
[33, 53, 12, 64, 41, 45, 21, 97, 35, 47, 39, 93, 40, 46, 42, 95, 51, 68, 9,
84, 34, 64, 6, 26, 3, 43, 30, 60, 3, 68, 9, 97, 19, 27, 4, 96, 37, 78, 43,
64, 4, 65, 30, 84, 18, 50, 1, 40, 32, 76, 57, 63, 53, 57, 42, 80, 9, 41, 30,
79, 18, 97, 23, 52, 38, 74, 15]
[33, 53, 12, 64, 41, 45, 21, 97, 35, 92, 0, 93, 40, 69, 6, 95, 51, 72, 9, 84, 34, 64, 2, 98, 3, 43, 30, 60, 3, 82, 9, 97, 19, 99, 4, 96, 9, 78, 43, 64, 4, 65, 30, 90, 18, 60, 1, 40, 32, 100, 29, 63, 46, 98, 42, 82, 9, 84, 30, 79, 18, 97, 23, 52, 38, 74]
Explanation
I had intended to provide an explanation of the algorithm and its implementation, but having since learned there is a superior approach (see my note at the beginning of my answer), I have decided against doing that, but would of course be happy to answer any questions. The link in my note explains, among other things, how dynamic programming can be used here.
Let Wp[i] be the longest wiggle sequence starting at element i, and where the first difference is positive. Let Wn[i] be the same, but where the first difference is negative.
Then:
Wp[k] = max(1+Wn[k'] for k<k'<n, where A[k'] > A[k]) (or 1 if no such k' exists)
Wn[k] = max(1+Wp[k'] for k<k'<n, where A[k'] < A[k]) (or 1 if no such k' exists)
This gives an O(n^2) dynamic programming solution, here in pseudocode
Wp = [1, 1, ..., 1] -- length n
Wn = [1, 1, ..., 1] -- length n
for k = n-1, n-2, ..., 0
for k' = k+1, k+2, ..., n-1
if A[k'] > A[k]
Wp[k] = max(Wp[k], Wn[k']+1)
else if A[k'] < A[k]
Wn[k] = max(Wn[k], Wp[k']+1)
result = max(max(Wp[i], Wn[i]) for i = 0, 1, ..., n-1)
In a comment on #quertyman's answer, #PeterdeRivaz provided a link to an article that considers various approaches to solving the "longest wiggle subsequence" problem. I have implemented "Approach #5", which has a time-complexity of O(n).
The algorithm is simple as well as fast. The first step is to remove one element from each pair of consecutive elements that are equal, and continue to do so until there are no consecutive elements that are equal. For example, [1,2,2,2,3,4,4] would be converted to [1,2,3,4]. The longest wiggle subsequence includes the first and last elements of the resulting array, a, and every element a[i], 0 < i < a.size-1 for which a[i-1] < a[i] > a[i+1] ora[i-1] > a[i] > a[i+1]. In other words, it includes the first and last elements and all peaks and valley bottoms. Those elements are A, D, E, G, H, I in the graph below (taken from the above-referenced article, with permission).
Code
def longest_wiggle(arr)
arr.each_cons(2).
reject { |a,b| a==b }.
map(&:first).
push(arr.last).
each_cons(3).
select { |triple| [triple.min, triple.max].include? triple[1] }.
map { |_,n,_| n }.
unshift(arr.first).
push(arr.last)
end
Example
arr = [33, 53, 12, 64, 50, 41, 45, 21, 97, 35, 47, 92, 39, 0, 93, 55, 40,
46, 69, 42, 6, 95, 51, 68, 72, 9, 32, 84, 34, 64, 6, 2, 26, 98, 3,
43, 30, 60, 3, 68, 82, 9, 97, 19, 27, 98, 99, 4, 30, 96, 37, 9, 78,
43, 64, 4, 65, 30, 84, 90, 87, 64, 18, 50, 60, 1, 40, 32, 48, 50, 76,
100, 57, 29, 63, 53, 46, 57, 93, 98, 42, 80, 82, 9, 41, 55, 69, 84,
82, 79, 30, 79, 18, 97, 67, 23, 52, 38, 74, 15]
a = longest_wiggle(arr)
#=> [33, 53, 12, 64, 41, 45, 21, 97, 35, 92, 0, 93, 40, 69, 6, 95, 51, 72,
# 9, 84, 34, 64, 2, 98, 3, 43, 30, 60, 3, 82, 9, 97, 19, 99, 4, 96, 9,
# 78, 43, 64, 4, 65, 30, 90, 18, 60, 1, 40, 32, 100, 29, 63, 46, 98, 42,
# 82, 9, 84, 30, 79, 18, 97, 23, 52, 38, 74, 15]
a.size
#=> 67
Explanation
The steps are as follows.
arr = [3, 4, 4, 5, 2, 3, 7, 4]
enum1 = arr.each_cons(2)
#=> #<Enumerator: [3, 4, 4, 5, 2, 3, 7, 4]:each_cons(2)>
We can see the elements that will be generated by this enumerator by converting it to an array.
enum1.to_a
#=> [[3, 4], [4, 4], [4, 5], [5, 2], [2, 3], [3, 7], [7, 4]]
Continuing, remove all but one of each group of successive equal elements.
d = enum1.reject { |a,b| a==b }
#=> [[3, 4], [4, 5], [5, 2], [2, 3], [3, 7], [7, 4]]
e = d.map(&:first)
#=> [3, 4, 5, 2, 3, 7]
Add the last element.
f = e.push(arr.last)
#=> [3, 4, 5, 2, 3, 7, 4]
Next, find the peaks and valley bottoms.
enum2 = f.each_cons(3)
#=> #<Enumerator: [3, 4, 5, 2, 3, 7, 4]:each_cons(3)>
enum2.to_a
#=> [[3, 4, 5], [4, 5, 2], [5, 2, 3], [2, 3, 7], [3, 7, 4]]
g = enum2.select { |triple| [triple.min, triple.max].include? triple[1] }
#=> [[4, 5, 2], [5, 2, 3], [3, 7, 4]]
h = g.map { |_,n,_| n }
#=> [5, 2, 7]
Lastly, add the first and last values of arr.
i = h.unshift(arr.first)
#=> [3, 5, 2, 7]
i.push(arr.last)
#=> [3, 5, 2, 7, 4]

How to delete elements from an array that are followed by the same elements

I have an array. There are two 46s at indices 3 and 7:
arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1]
I got a mission to sort this array using selection sort, but not .sort. The result should be:
[1, 7, 9, 42, 46, 46, 68, 77, 86, 91]
So, I did this in a .rb file:
def insertion_sort(arr)
length = arr.size
arr.each_with_index do |number, index|
puts "Now the index is #{index}"
current_minimum = arr.last(length - index).min
puts "Now the current_minimum in last#{length - index} elements is #{current_minimum}"
arr.delete(current_minimum)
arr.insert(index, current_minimum)
end
end
arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1]
answer = insertion_sort(arr)
puts answer.to_s
I executed this file, then got this:
[1, 7, 9, 42, 68, 91, 77, 86, 46]
If I delete one 46, it came out with this:
[1, 7, 9, 42, 46, 68, 77, 86, 91]
My code does not work when there are multiple occurrences of some single value in the array. When the each_with_index block went to index 3, it deleted all 46s from the rest of the array.
Could anyone tell me how to correct this?
To "emulate" this kind of selection sort you could try iterating over an array using a range starting from 0 as the value with index 0 and with the length of the array as last element. This range won't take the last array value.
Using each you get access to each value from the created range, then, using that "index", you can create a new range, again without taking the last element but this time one step ahead, that's adding 1 to the current value for a. This way again, using each you have access to a and b, from the "parent" and "child" range created before.
Now you can check if the value for the element with index b in the array is minor than the value for the element with index a in the array, if this validation is true then create a temp variable with the value of the element in the array with index b, then the element in the array at position (index) b will be equal to the element in the array with the position a, finally the element in the array at position a, will be equal to the temp variable created before.
Finally return the array passed as argument.
def insertion_sort(array)
(0...array.length).each do |a|
((a+1)...array.size).each do |b|
if array[b] < array[a]
temp = array[b]
array[b] = array[a]
array[a] = temp
end
end
end
array
end
arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1]
p insertion_sort(arr)
# => [1, 7, 9, 42, 46, 46, 68, 77, 86, 91]
As added #MarkThomas, you can "skip" the temp variable by swapping the array values with a and b indexes:
def insertion_sort(array)
(0...array.length).map do |a|
((a+1)...array.size).each do |b|
array[a], array[b] = array[b], array[a] if array[b] < array[a]
end
end
array
end
Thanks all of you. I improved my code and it seems work well.Here's the code:
def insertion_sort(arr)
length = arr.size
arr.each_with_index do |number, index|
current_minimum = arr.last(length - index).min
current_minimum_index = arr.last(length-index).index(current_minimum) + index # this insure it will delete the right element
arr.delete_at(current_minimum_index)
arr.insert(index, current_minimum)
end
end
arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1]
answer = insertion_sort(arr)
puts "---------------------------------------------------------------"
puts "Finally we get #{answer.to_s}"
To implement a Selection Sort in Ruby you can use Kernel#loop, being careful to pass obj to break in order to get the correct return value.
arr = [7, 68, 42, 46, 9, 91, 77, 46, 86, 1]
sorted = loop.with_object([]) do |_,obj|
mindex = arr.index arr.min #find index of a minimum
obj << arr.delete_at(mindex) #push this minimum value to obj
break obj if arr.empty?
end
sorted #=> [1, 7, 9, 42, 46, 46, 68, 77, 86, 91]
See with_object for more info.

Ruby Array#include method not working as intended

Why is the include method not working well? The original question is from the Euler project, Problem 23. I couldn't figure out how to debug it.
My code:
def proper_divisors(n)
(1...n).select {|x| n % x == 0 }.inject(0){|x,y| x + y}
end
def abundant?(n)
(1...n).select {|x| n % x == 0 }.inject(0){|x,y| x + y} > n
end
def non_abundant_sums
s = 0
arr = (12..40).select { |n| n if abundant?(n) }
p arr
(1..40).each do |x|
p x unless arr.include?(proper_divisors(x) - x)
s = s + x unless arr.include?(proper_divisors(x) - x)
end
s
end
p non_abundant_sums
Using p x unless arr.include?(proper_divisors(x) - x) in the above code prints 1 through 40:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
What I want it to print is 1 through 39:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 33, 34, 35, 37, 39
A solution based on the original methods from the example.
In file problem_23.rb:
def proper_divisors(n)
(1...n).select {|x| n % x == 0 }.inject(0) {|x,y| x + y}
end
def abundant?(n)
proper_divisors(n) > n
end
def non_abundant_sum(low_n, high_n, debug=false)
puts "get all the abundant numbers within range #{low_n} to #{high_n}" if debug
arr = (low_n..high_n).select {|n| n if abundant?(n)}
puts arr.sort.inspect if debug
# http://ruby-doc.org/core-2.1.2/Array.html#method-i-repeated_combination
puts "all combinations of two abundant numbers" if debug
arr = arr.repeated_combination(2).to_a
puts arr.inspect if debug
puts "all unique sums of two abundant number combinations" if debug
arr = arr.map {|x| x[0] + x[1]}.uniq
puts arr.sort.inspect if debug
puts "only select numbers within range" if debug
arr = arr.select {|x| low_n <= x && x <= high_n}
puts arr.inspect if debug
puts "all positive integers within range" if debug
arr2 = (low_n..high_n).map {|i| i}
puts arr2.inspect if debug
puts "all positive integers less all the sums of two abundant numbers" if debug
arr = arr2 - arr
puts arr.inspect if debug
puts "sum of all the positive integers which cannot be written as the sum of two abundant numbers within range #{low_n} to #{high_n}" if debug
arr.inject(0) {|sum,n| sum + n}
end
puts non_abundant_sum(12, 40, true)
Running the code:
$ ruby problem_23.rb
get all the abundant numbers within range 12 to 40
[12, 18, 20, 24, 30, 36, 40]
all combinations of two abundant numbers
[[12, 12], [12, 18], [12, 20], [12, 24], [12, 30], [12, 36], [12, 40], [18, 18], [18, 20], [18, 24], [18, 30], [18, 36], [18, 40], [20, 20], [20, 24], [20, 30], [20, 36], [20, 40], [24, 24], [24, 30], [24, 36], [24, 40], [30, 30], [30, 36], [30, 40], [36, 36], [36, 40], [40, 40]]
all unique sums of two abundant number combinations
[24, 30, 32, 36, 38, 40, 42, 44, 48, 50, 52, 54, 56, 58, 60, 64, 66, 70, 72, 76, 80]
only select numbers within range
[24, 30, 32, 36, 38, 40]
all positive integers within range
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
all positive integers less all the sums of two abundant numbers
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 33, 34, 35, 37, 39]
sum of all the positive integers which cannot be written as the sum of two abundant numbers within range 12 to 40
554

How to add to an array with an if method

I have an array of numbers like so...
a= [28, 67, 20, 38, 4, 39, 14, 84, 20, 64, 7, 24, 17, 8, 7, 6, 15, 52, 4, 26]
I need to check if each of the numbers is greater than 30 and if so then I want to count that number and get a count of how many numbers are greater than 30. I have this but it is not working so far
def late_items
total_late = []
if a.map { |i| i > 30}
total_late << i
end
self.late_items = total_late.count
end
The count method can be passed a block to specify what kind of elements should be counted. Elements for which the block returns false or nil are ignored.
In your case, it would boil down to this:
array.count { |element| element > 30 }
You can use select to get all elements greater than 30.
a.select{|b| b > 30}.count
# => 6
Is is much simpler in Ruby:
a = [28, 67, 20, 38, 4, 39, 14, 84, 20, 64, 7, 24, 17, 8, 7, 6, 15, 52, 4, 26]
a.select{ |e| e > 30 }
It seems like you also want the index of each item that is over 30, if that is the case, this will work:
a= [28, 67, 20, 38, 4, 39, 14, 84, 20, 64, 7, 24, 17, 8, 7, 6, 15, 52, 4, 26]
count = 0
pos = []
a.each_with_index do |num, i|
if num > 30
count += 1
pos << i
end
end
puts count
print pos
#=> 6 [1,3,5,7,8,17]
You may also check the inject method. Within it you can easily get the sum of numbers greater than 30:
a.inject(0) { |sum, n| n > 30 ? sum += n : sum }
Or, if you have an array of numbers greater than 30, you can use reduce to summarize its items. Within your a variable it will look like:
a.select{ |n| n > 30 }.reduce(&:+)

1 to 100 odd numbers in array

Is there any cool way in Ruby to create an array with 1 to 100 with only odd entries (1, 3 etc). I now have a loop for this but that is obviously not a cool way to do it! Any suggestions?
My current code:
def create_1_to_100_odd_array
array = [1]
i = 3
while i < 100
array.push i
i += 2
end
array
end
Thanks in advance
The Range class comes with a very cool feature for that purpose:
1.9.3-p286 :005 > (1..10).step(2).to_a
=> [1, 3, 5, 7, 9]
May not be efficient, but a short piece of code:
(1..100).select(&:odd?)
# => [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
Just toying...
(0...50).map(&:object_id)
#or
1.step(100,2).to_a
Since you need a function, then:
def odd_to(n)
(1..n).step(2).to_a
end
Not very effective solution, but quite elegant:
(1..100).select {|a| a%2 != 0}
You can do it as a one-liner when you instantiate the array:
def create_array_of_odds_to(n)
Array.new((n + 1) / 2) {|i| 2 * i + 1}
end
create_array_of_odds_to 10 # => [1, 3, 5, 7, 9]

Resources