SetOps, Difference, Timing Script

# -*- tcl -*-

 # test = diff

 set max 50


 proc testA {a b} {
    if {[llength $a] == 0} {
        return {}
    }
    if {[llength $b] == 0} {
        return $a
    }

    set res {}

    set a [lsort $a]
    set b [lsort $b]

    while {1} {
        # Store lindex/0,1 in var, access later faster ?
        set n [string compare [lindex $a 0] [lindex $b 0]]
        if {$n == 0} {
            # A = B => element in both, so not in difference
            set a [lrange $a 1 end]
            set b [lrange $b 1 end]
        } elseif {$n > 0} {
            # A > B, remove B, we are beyond the element. 
            set b [lrange $b 1 end]
        } else {
            # A < B, remove A, we are beyond the element.
            # This element in A is part of the result too.
            lappend res [lindex $a 0]
            set a [lrange $a 1 end]
        }
        if {[llength $a] == 0} {
            return $res
        }
        if {[llength $b] == 0} {
            foreach e $a {
                lappend res $a
            }

            return $res
        }
    }

    return $res
 }


 proc testB {a b} {
    if {[llength $a] == 0} {
        return {}
    }
    if {[llength $b] == 0} {
        return $a
    }

    set res {}

    foreach e $b {
        set ba($e) .
    }

    foreach e $a {
        if {![info exists ba($e)]} {
            lappend res $e
        }
    }

    return $res
 }


 proc testC {a b} {
    if {[llength $a] == 0} {
        return {}
    }
    if {[llength $b] == 0} {
        return $a
    }

    set res {}

    foreach $b {.} {break}

    foreach e $a {
        if {![info exists $e]} {
            lappend res $e
        }
    }

    return $res
 }


 # DF_NE -> a, b   random, unsorted, intersection almost always empty
 # DF_EQ -> a = b, random

 set fa1  [open "|./2nep DF_A_NE Ar.dat   X.dat" w]
 set fa2  [open "|./2nep DF_A_EQ Ae0.dat  X.dat" w]

 set fb1  [open "|./2nep DF_B_NE Br.dat   X.dat" w]
 set fb2  [open "|./2nep DF_B_EQ Be0.dat  X.dat" w]

 set fc1  [open "|./2nep DF_C_NE Cr.dat   X.dat" w]
 set fc2  [open "|./2nep DF_C_EQ Ce0.dat  X.dat" w]

 set fx   [open "|./2nep DF_X     X.dat" w]


 set a0 {}
 set b0 {}

 puts stdout " ______________________________" ; flush stdout
 puts stdout " DIFF | ......A ......B ......C" ; flush stdout

 for {set i 0} {$i <= $max} {incr i} {
    set ix [format %03d $i]

    puts stderr "   * $ix (a0) =  $a0" ; flush stderr
    puts stderr "   * $ix (b0) =  $b0" ; flush stderr

    set ra1  [lindex [time {testA $a0 $b0} 1000] 0]
    set ra2  [lindex [time {testA $a0 $a0} 1000] 0]

    set rb1  [lindex [time {testB $a0 $b0} 1000] 0]
    set rb2  [lindex [time {testB $a0 $a0} 1000] 0]

    set rc1  [lindex [time {testC $a0 $b0} 1000] 0]
    set rc2  [lindex [time {testC $a0 $a0} 1000] 0]

    puts stdout " ______________________________" ; flush stdout
    puts stdout " $ix NE [format %7d $ra1] [format %7d $rb1] [format %7d $rc1]"
    puts stdout " $ix EQ [format %7d $ra2] [format %7d $rb2] [format %7d $rc2]"

    puts $fa1 $ra1
    puts $fa2 $ra2

    puts $fb1 $rb1
    puts $fb2 $rb2

    puts $fc1 $rc1
    puts $fc2 $rc2

    puts $fx  $i

    lappend a0 [string range [lindex [split [expr {rand()}] .] 1] 0 4]
    lappend b0 [string range [lindex [split [expr {rand()}] .] 1] 0 4]
 }


 puts stderr "----"     ; flush stderr
 puts stdout " ______________________________" ; flush stdout

 close $fa1
 close $fa2

 close $fb1
 close $fb2

 close $fc1
 close $fc2

 close $fx

See also SetOps.