Skip to content

Commit ab760cd

Browse files
Added n-smallest-elements-in-original-order.rb
1 parent 7f4257d commit ab760cd

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
=begin
2+
Codewars. 30/04/20. 'N smallest elements in original order'. 6kyu. Here we create
3+
a method that takes an array of integers and returns the N smallest, in original
4+
order. Here is the solution I developed to solve the challenge.
5+
1) We define our method first_n_smallest_ms, which takes 2 arguments, arr, an
6+
array of integers and n, the amount of smallest elements we need to return.
7+
2) We takes the n smallest elements using the min method and store them in a
8+
variable m.
9+
3) We map over the array and if the element currently being iterated over is in
10+
the m collection, we keep it in the array and then delete that corresponding
11+
element from the m collection using the delete_at method, which takes an
12+
index position as its argument. This way no duplicates are kept, only the
13+
exact number of elements from m.
14+
4) Any element in the array which is not included in m will become a nil value
15+
because we've performed no action on it, therefore we call the compact
16+
method to remove all nil values.
17+
5) Now we've returned the n smallest elements in original order.
18+
=end
19+
20+
def first_n_smallest_ms(arr, n)
21+
m = arr.min(n)
22+
arr.map {|e| e && m.delete_at(m.index(e)) if m.include?(e)}.compact
23+
end
24+
25+
=begin
26+
Here is another solution I made, inspired by another Codewars user's solution.
27+
1) We store our n smallest elements in a variable m.
28+
2) We call each_with_object on the original array, our new object being a new
29+
array where the n smallest will be stored, in original order.
30+
3) If the element we are currently iterating over is included in m, we call the
31+
slice! method - which takes an index - to delete that element from m.
32+
Because slice! also returns that element, we can add it to the new array
33+
simultaneously, delete_at also does the same thing.
34+
4) If we try to return the new array by returning r at the end, we'll get an
35+
error because there is no need to. The new array will automatically be
36+
called, and it will now contain the n smallest elements in original order.
37+
=end
38+
39+
def first_n_smallest_ms_x(arr, n)
40+
m = arr.min(n)
41+
arr.each_with_object([]) {|e,r| r << m.slice!(m.index(e)) if m.include?(e)}
42+
end
43+
44+
=begin
45+
Here is the best solution.
46+
1) We call each_with_index on the array then tag min(n) onto the end, now we
47+
have an array of arrays where each sub-array contains a smallest as the
48+
first element and its index position as the second element. The array is
49+
sorted by the first element.
50+
2) We sort the sub-arrays by their last element, so now the mins are in their
51+
original order.
52+
3) We map over the array of arrays and keep only the first elements, thereby
53+
creating an array of the n smallest, in original order.
54+
=end
55+
56+
def first_n_smallest(arr, n)
57+
arr.each_with_index.min(n).sort_by(&:last).map(&:first)
58+
end
59+
60+
=begin
61+
Here is a final solution.
62+
1) While the array size is above n, it deletes the last occurrence of each max
63+
element.
64+
2) The delete_at method takes an index position.
65+
3) The rindex method returns the last occurrence of the object placed in its
66+
argument. The index method is the opposite, returning the first occurrence,
67+
however, the index method wouldn't work in this method.
68+
4) Once the size of the array becomes equal to n, we return it. It now contains
69+
the smallest n elements in their original order.
70+
=end
71+
72+
def first_n_smallest_x(arr, n)
73+
arr.delete_at(arr.rindex(arr.max)) while (arr.size > n) ; arr
74+
end

0 commit comments

Comments
 (0)