noMethodError on a < symbol ruby

101 Views Asked by At

enter image description here

The link for the error is above; I keep getting a noMethodError for a symbol and I am very confused

numList = [4,3,78,2,0,2]

def bubbleSort(list)
  again = true

  while again
    copy = list
    i = 0
    until i == list.length do
      list.each_with_index do |num, index|
        if list[index+1] < num 
          tempNum = list[index+1]
          list[index+1] = num
          list[index] = tempNum
        end
      end
      i = i+1
    end

    if copy != list
      again = true
    else
      again = false
    end
    p copy
  end
end

bubbleSort(numList)
1

There are 1 best solutions below

0
Chris On

As noted in comments, you are iterating with an index:

list.each_with_index do |num, index|

But this includes the last index, which you're trying to access one past.

if list[index+1] < num

list[index+1] return nil, which will give the error you're seeing.

irb(main):083:0> nil < 42
Traceback (most recent call last):
        5: from C:/Ruby26-x64/bin/irb.cmd:31:in `<main>'
        4: from C:/Ruby26-x64/bin/irb.cmd:31:in `load'
        3: from C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        2: from (irb):83
        1: from (irb):83:in `rescue in irb_binding'
NoMethodError (undefined method `<' for nil:NilClass)

It'd be important to avoid this access. I would also suggest avoiding the again boolean flag. Rather use loop and break out of the loop at the appropriate time.

def bubbleSort(list)
  loop do
    copy = list
    i = 0
    until i == list.length  
      list.each_with_index do |num, index|
        next if index == list.length - 1
      
        if list[index+1] < num 
          tempNum = list[index+1]
          list[index+1] = num
          list[index] = tempNum
        end
      end
      i = i+1
    end

    break if copy == list
    
    p copy
  end
end

Taking a step back and looking at how bubble sort works though, your implementation can be improved.

Each cycle through the array a bubble sort will advance the largest element to the end of the array. You don't need to cycle over the whole array each times, but can decrease the inner loop by one iteration each time.

You can also track the number of swaps. If no swaps are performed, the array is clearly sorted already, and the outer loop can be exited.

+---+---+---+---+
| 4 | 2 | 3 | 1 |  (starting state for loop)
+---+---+---+---+

  >---<
+---+---+---+---+
| 2 | 4 | 3 | 1 | (swap 4 and 2)
+---+---+---+---+

      >---<
+---+---+---+---+
| 2 | 3 | 4 | 1 | (swap 4 and 3)
+---+---+---+---+

          >---<
+---+---+---+---+
| 2 | 3 | 1 | 4 | (swap 4 and 1)
+---+---+---+---+

Three swaps are performed. The last position in the array is sorted.

+---+---+---+---+
| 2 | 3 | 1 | 4 | (starting state for loop)
+---+---+---+---+

      >---<
+---+---+---+---+
| 2 | 1 | 3 | 4 | (swap 3 and 1)
+---+---+---+---+

+---+---+---+---+
| 2 | 1 | 3 | 4 | (no swap needed for 1 and 3)
+---+---+---+---+

One swap is performed. Now the last two positions are sorted.

+---+---+---+---+
| 2 | 1 | 3 | 4 | (starting state for loop)
+---+---+---+---+

  >---<
+---+---+---+---+
| 1 | 2 | 3 | 4 | (swap 2 and 1)
+---+---+---+---+

One swap is performed. We know the last three positions are sorted. The first position therefore is sorted.

If the array is already sorted and we keep track of swaps:

+---+---+---+---+
| 1 | 2 | 3 | 4 | (starting state for loop)
+---+---+---+---+

+---+---+---+---+
| 1 | 2 | 3 | 4 | (no swap needed for 1 and 2)
+---+---+---+---+

+---+---+---+---+
| 1 | 2 | 3 | 4 | (no swap needed for 2 and 3)
+---+---+---+---+

+---+---+---+---+
| 1 | 2 | 3 | 4 | (no swap needed for 3 and 4)
+---+---+---+---+

Since zero swaps are performed, the array is known to be sorted. While bubble sort is worst case O(n^2), this technique can make it best case O(n).

def bubble_sort(arr)
  (arr.length-1).times do |x|
    swaps = 0

    0.upto(arr.length-x-2) do |i|
      if arr[i] > arr[i+1]
        temp = arr[i+1]
        arr[i+1] = arr[i]
        arr[i] = temp
        swaps += 1
      end
    end

    break if swaps == 0
  end
  
  arr
end