Version 8 of Random worklist generator

Updated 2008-09-22 10:19:07 by theover

TV

Do make sure certain chores get no prevalence over other chores, association-wise, I made a little worklist randomizer.

Lets say I have a number of chores in a list:

 set w {
  {washing up}
  {cut the grass}
  {shave (very important!)}
  {watch CNN}
  {finish some Tcl programs}
  {work in computer field}
  {buy tickets in a lottery}
  {go voting (even more important!)}
  {etc (whatever else comes up)}
 }

Now we want a random iten from the list, or a random permutation of the list, with no priorities:

 lindex $w [expr int(9*rand())]

Of course we could do the same with the rest of the list.

Googie 17.09.2008 - I'd upgrade method of retrieving random entry:

 lindex $w [expr { int([llength $w]*rand()) }]

But there is still missing solution for removing from list jobs that are already done. So we need a procedure for that:

 proc lremove {varName idx} {
     upvar $varName lst
     set val [lindex $lst $idx]
     set lst [lreplace $lst $idx $idx]
     return $val
 }

and finally:

 lremove w [expr { int([llength $w]*rand()) }]

TV I had made this:

 proc randout l {
    set i [expr int([llength $l]*rand())] ; 
    return [list [lindex $l $i] [lrange $l 0 [expr $i-1] ] [lrange $l [expr $i+1] end ]]
 }

This is a list shuffler which can be made recursive, but it escaped me how to make a flat combined list...

( Example: (Tcl) 62 % randout $w

{go voting (even more important!)} {{washing up} {cut the grass} {shave (very important!)} {watch CNN} {finish some Tcl programs} {work in computer field} {buy tickets in a lottery}} {{etc (whatever else comes up)}}

)

Of course I know how to do that:

 proc randout l {
    set i [expr int([llength $l]*rand())] ; 
    return "[lindex $l $i] [lrange $l 0 [expr $i-1] ] [lrange $l [expr $i+1] end]"
 }

And then make that recursive for fun. But no:

 Tcl) 106 % list a b c
 a b c
 (Tcl) 107 % list a {b c}
 a {b c}
 (Tcl) 108 % list [list a {b c}]
 {a {b c}}
 (Tcl) 109 % list [list a b c]
 {a b c}
 (Tcl) 110 % list {v}
 v
 (Tcl) 111 % list {v} b
 v b

That *is* neatly solvable, but for the same reasdon I felt bwise being bogged down, this type of system-correct list processing just doesn't stick with my consciousness easily enough. Maybe later.

Googie 18.09.2008 - To make a flat of:

 proc randout l {
    set i [expr int([llength $l]*rand())] ; 
    return [list [lindex $l $i] [lrange $l 0 [expr $i-1] ] [lrange $l [expr $i+1] end ]]
 }

use just concat command:

 proc randout l {
    set i [expr int([llength $l]*rand())] ; 
    return [concat [list [lindex $l $i]] [lrange $l 0 [expr $i-1] ] [lrange $l [expr $i+1] end ]]
 }

I put lindex $l $i into a single list, because concat would understeand it as a separate list - if it was a correct Tcl list - and join it to other lists. Anyway, I'd do that like this:

 proc randout l {
    set i [expr int([llength $l]*rand())] ; 
    set ret [lindex $l $i]
    set l [linsert [lreplace $l $i $i] 0 $ret]
    return $l
 }

I think it's easier to read it and I think it's faster, since there is no additional calls to expr. NOTE: use brackets to enclose expresions in expr, like this:

 expr {$i+1}

or

 expr {$i + 1}

It makes them working faster.

TV I was interested in a nice language construct, coming from the time of basic and assembly I forget quoting hell and wish things work nice. The replace insert trick is fine but I'd prefer it that for constant (byte compilable or so) code the compiler would understand most things in an easy to remember way, and of course I'd let it wonder about what's optimal. I can make it work, don't bother...


enter categories here