|
| 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