Home > OS >  Ruby Solution for codewars sum of intervals 4kyu doesnot work
Ruby Solution for codewars sum of intervals 4kyu doesnot work

Time:09-06

[Sum of intervals] (https://www.codewars.com/kata/52b7ed099cdc285c300001cd/ruby)

My solution for this kyu

def sum_of_intervals(intervals)
  intervals.uniq.sort_by!(&:last) 
  sum = 0
   
  new_intervals = intervals.sort_by(&:first).each_with_object([intervals.first]) do |interval, arr|
    if interval.first <= arr.last.last
      arr[-1] = arr.last.first, [arr.last.last, interval.last].max
    else
      arr << interval
    end
  end
 
  new_intervals.each do |interval|
    sum  = (interval[1] - interval[0])
  end

  p sum
end

After writing code we have two options - test and attempt My def pass successfully with test and failed with attempt I cannot see test for attempt May be sombody could teke a look what`s wrong with my code? Thanks a lot

CodePudding user response:

intervals.uniq.sort_by!(&:last)

This almost certainly doesn't do what you think it does. Consider:

irb(main):006:0> a = [[1, 2], [3, 4], [5, 0], [1, 2]]
irb(main):007:0> a.uniq.sort_by!(&:last)
=> [[5, 0], [1, 2], [3, 4]]
irb(main):008:0> a
=> [[1, 2], [3, 4], [5, 0], [1, 2]]
irb(main):009:0> (b = a.uniq).sort_by!(&:last)
=> [[5, 0], [1, 2], [3, 4]]
irb(main):010:0> a
=> [[1, 2], [3, 4], [5, 0], [1, 2]]
irb(main):011:0> b
=> [[5, 0], [1, 2], [3, 4]]

intervals.uniq is creating a new array, which #sort_by! does sort destructively, but that does not affect intervals.

You can use the destructive #uniq! in this case, but that method will return nil if the array is already "unique", leading to an exception when you try to call #sort_by! on nil. Using &. (intervals.uniq!&.sort_by!(&:last)) will prevent the exception, but may leave your data unsorted.

You may be better served by the much simpler:

intervals = intervals.uniq.sort_by(&:last)

CodePudding user response:

Though Chris has answered your question, I would like to suggest an alternative solution.

First define a helper method, where the argument r is a range.

def completed_range_span(r)
  r.end - r.begin
end

Now define the main method.

def total_arr_lengths(arr)
  # convert arr to an array of ranges ordered by beginning of range
  a = arr.map { |e| e.first..e.last }.sort_by(&:begin)
  tot = 0
  loop do
    # If a contains only a single range add the span of that range to tot,
    # after which we are finished
    break (tot   completed_range_span(a.first)) if a.size == 1

    # We're not finished
    # For readability, assign first two elements of a to variables
    r0 = a[0]
    r1 = a[1]

    # If r0 and r1 do not overlap add the span of r0 to tot
    # else alter r1 to be the range formed by r0 and r1

    if r0.end < r1.begin
      tot  = completed_range_span(r0)
    else
      a[1]= r0.begin..[r0.end, r1.end].max
    end

    # remove r0
    a.shift
  end
end

Let's try it.

total_arr_lengths [[1,4], [7, 10], [3, 5]]                     #=> 7
total_arr_lengths [[1,2], [6, 10], [11, 15]]                   #=> 9
total_arr_lengths [[1,4], [7, 10], [3, 5]]                     #=> 7
total_arr_lengths [[1,5], [10, 20], [1, 6], [16, 19], [5, 11]] #=> 19
total_arr_lengths [[0, 20], [-100000000, 10], [30, 40]]        #=> 100000030

To help the reader confirm the results for these examples, for each argument (an array) I have displayed below the corresponding value of the array of ordered ranges obtained by the first calculation performed by the main method:

arr.map { |e| e.first..e.last }.sort_by(&:begin)
arr                                           array of ordered ranges
--------------------------------------------  -----------------------------------
[[1,4], [7, 10], [3, 5]]                      [1..4, 3..5, 7..10]
[[1,2], [6, 10], [11, 15]]                    [1..2, 6..10, 11..15]
[[1,4], [7, 10], [3, 5]]                      [1..4, 3..5, 7..10]
[[1,5], [10, 20], [1, 6], [16, 19], [5, 11]]  [1..5, 1..6, 5..11, 10..20, 16..19]
[[0, 20], [-100000000, 10], [30, 40]]         [-100000000..10, 0..20, 30..40]

I converted the arrays to ranges to improve readability (in my opinion). I don't expect it affects computational efficiency, though it generally saves some memory.

  •  Tags:  
  • ruby
  • Related