sharath chandra
sharath chandra

Reputation: 149

scala for-loop issue assignment issue

simple selectionSort is not working

Here doSort method is not working just because of manipulating "minimum" inside the for loop, can someone tell me what is the root cause, i couldnt understand the root cause

object SelectionSort extends App {
    val unSortedArray = ArrayBuffer(5, -1, 8, 4, 6, 21, 4, 5, -0, 0)

    def doSort (ary: ArrayBuffer[Int], startIndex: Int, endIndex: Int) = {
        var minimum = 0
        for {
            index <- startIndex to endIndex
            _ = minimum = ary(index)
            loopIndex <- index until endIndex
        } {
            if (minimum > ary(loopIndex + 1)) {
                minimum = ary(loopIndex + 1)
                val swap = ary(index)
                ary(index) = ary(loopIndex + 1)
                ary(loopIndex + 1) = swap
            }
        }
    }

    def doSortWorking (ary: ArrayBuffer[Int], startIndex: Int, endIndex: Int) = {
        var minimum = 0
        for {
            index <- startIndex to endIndex
            loopIndex <- index until endIndex
        } {
            minimum = ary(index)
            if (minimum > ary(loopIndex + 1)) {
                minimum = ary(loopIndex + 1)
                val swap = ary(index)
                ary(index) = ary(loopIndex + 1)
                ary(loopIndex + 1) = swap
            }
        }
    }

    doSort(unSortedArray, 0, unSortedArray.size - 1)
    println(unSortedArray)
    doSortWorking(unSortedArray, 0, unSortedArray.size - 1)
    println(unSortedArray)
}

Upvotes: 0

Views: 75

Answers (1)

Evgeny Veretennikov
Evgeny Veretennikov

Reputation: 4239

Just swap 2nd and third lines in for comprehension inside doSort():

def doSort (ary: ArrayBuffer[Int], startIndex: Int, endIndex: Int) = {
    var minimum = 0
    for {
        index <- startIndex to endIndex
        loopIndex <- index until endIndex
        _ = minimum = ary(index)
    } {
        if (minimum > ary(loopIndex + 1)) {
            minimum = ary(loopIndex + 1)
            val swap = ary(index)
            ary(index) = ary(loopIndex + 1)
            ary(loopIndex + 1) = swap
        }
    }
}

You should reassign new value to minimum after finding loopIndex, right inside doSortWorking function.

EDIT: Why doesn't your version of doSort work?

Let's try simplified version of it:

scala> val startIndex = 0
firstIndex: Int = 0

scala> val endIndex = 3
lastIndex: Int = 3

scala> var minimum = 0
minimum: Int = 0

scala> for {
     |   index <- startIndex to endIndex
     |   _ = minimum = index
     | } {
     |   println(minimum)
     | }
3
3
3
3

Why doesn't it print 0 1 2 3? Because for comprehension doesn't work as you thought here. Check this answer: https://stackoverflow.com/a/3754568/5053865 Here are some rules about for-comprehension evaluating. Let's apply them:

scala> for ((p, _) <-
     |   for (index <- startIndex to endIndex)
     |   yield { val x0 = minimum = index; (index, x0) }
     | ) {
     |   println(minimum)
     | }
3
3
3
3

scala> startIndex to endIndex map {
     |   index => val x0 = minimum = index; (index, x0)
     | } foreach {
     |   _ => println(minimum)
     | }
3
3
3
3

Now you should see what's really is going on here. Firstly, you assign values from startIndex to endIndex to variable minimum and only then execute body with maximum = endIndex every time!

Upvotes: 1

Related Questions