Prajakta Joshi
Prajakta Joshi

Reputation: 47

not able to sort list in tcl

I have below code in NS2 which calculates distance between two nodes and put it in a list "nbr". I want to sort out that list in ascending order as per value "d" and again store it in a list for further use for that I used lsort command but it is giving me same list that is unsorted. please help

code:.

proc distance { n1 n2 nd1 nd2} {
    set x1 [expr int([$n1 set X_])]
    set y1 [expr int([$n1 set Y_])]
    set x2 [expr int([$n2 set X_])]
    set y2 [expr int([$n2 set Y_])]
    set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
    if {$d<300} {
        if {$nd2!=$nd1 && $nd2 == 11} {
            set nbr "{$nd1 $nd2 $x1 $y1 $d}"
            set m [lsort -increasing -index 4 $nbr]
            puts $m
        }
    }
}

for {set i 1} {$i < $val(nn)} {incr i} {
    for {set j 1} {$j < $val(nn)} {incr j} {
        $ns at 5.5 "distance $node_($i) $node_($j) $i $j"
    }
}

output:

{1 11 305 455 273}
{4 11 308 386 208}
{5 11 378 426 274}
{7 11 403 377 249}
{8 11 244 405 215}
{9 11 256 343 154}
{10 11 342 328 172}
{12 11 319 192 81}
{13 11 395 196 157}
{14 11 469 191 231}
{15 11 443 140 211}
{16 11 363 115 145}
{17 11 290 135 75}
{18 11 234 121 69}
{19 11 263 60 132}
{20 11 347 60 169}

Upvotes: 1

Views: 479

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137577

Right now, you're calculating each of the distances separately, but aren't actually collecting them all into a list that can be sorted.

Let's fix this by first rewriting distance to just do the distance calculations themselves:

proc distance {n1 n2 nd1 nd2} {
    set x1 [expr int([$n1 set X_])]
    set y1 [expr int([$n1 set Y_])]
    set x2 [expr int([$n2 set X_])]
    set y2 [expr int([$n2 set Y_])]

    set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
    # Why not: set d [expr hypot($x2-$x1,$y2-$y1)]

    # I'm keeping *everything* we know at this point
    return [list $nd1 $nd2 $n1 $n2 $d $x1 $y1 $x2 $y2]
}

Then, we need another procedure that will process the whole collection (at the time the simulator calls it) and do the sorting. It will call distance to get the individual record, since we've factored that information out.

proc processDistances {count threshold {filter ""}} {
    global node_
    set distances {}
    for {set i 1} {$i < $count} {incr i} {
        for {set j 1} {$j < $count} {incr j} {
            # Skip self comparisons
            if {$i == $j} continue

            # Apply target filter
            if {$filter ne "" && $j != $filter} continue

            # Get the distance information
            set thisDistance [distance $node_($i) $node_($j) $i $j]

            # Check that the nodes are close enough
            if {[lindex $thisDistance 4] < $threshold} {
                lappend distances $thisDistance
            }
        }
    }

    # Sort the pairs, by distances
    set distances [lsort -real -increasing -index 4 $distances]

    # Print the sorted list
    foreach tuple $distances {
        puts "{$tuple}"
    }
}

Then we arrange for that whole procedure to be called at the right time:

# We recommend building callbacks using [list], not double quotes
$ns at 5.5 [list processDistances $val(nn) 300 11]

Upvotes: 1

Related Questions