if 0 {[Richard Suchenwirth] 2004-02-15 - On [Integer range generator], [SS] asked for a way to enumerate a range of words, like {a..z aa ..az ba ..} Such enumeration must of course be based on an alphabet - the example shows that it's supposed to be [[a-z]] in this case. At first glance, the task appears similar to conversion from or to baseN, where N is the length of the alphabet. However, the zero element is somehow special: if "a" were 0, "aa" would be 00, which for an integer is the same. So I let "a" count as 1, up to "z" as 26 -- and "aa" is then (a)*26+(a), 1*26+1 = 27. Different from normal base conversion, az = (a)*26+(z), 1*26+26 = 52 (in place of 2*26+0) , and so on. The code below takes care of this "zero-less" base conversion, by adding 1 in word2int, or decrementing by 1 in int2word. One trivial practical use of this is the names of [Excel] spreadsheet columns, which, with [[A-Z]] as alphabet, just follow the same pattern - but their little world ends at column 256, or "IV"... My experiments show that strings of up to 13 letters can be correctly transformed to integers. Above that size, strange errors may happen: % int2word [word2int kaaaaaaaaaaaaa] coscxanchbfnjk So best check the string length early in ''word2int''. } proc word2int {word {alphabet ""}} { if {$alphabet eq ""} {set alphabet [a-z]} set i [expr {wide(0)}] foreach c [split $word ""] { set i [expr {$i*[llength $alphabet]+[lsearch $alphabet $c]+1}] } if {$i<0} {error "word $word too long to fit in integer"} set i } proc int2word {int {alphabet ""}} { if {$alphabet eq ""} {set alphabet [a-z]} set word "" set la [llength $alphabet] while {$int} { incr int -1 set word [lindex $alphabet [expr {$int % $la}]]$word set int [expr {$int/$la}] } set word } proc a-z {} {list a b c d e f g h i j k l m n o p q r s t u v w x y z} # Testing: proc must {cmd res} { if {[set r [eval $cmd]] ne $res} {error "$cmd -> $r, not $res"} } must {word2int a} 1 must {word2int z} 26 must {word2int aa} 27 must {word2int az} 52 must {word2int ba} 53 must {int2word 1} a must {int2word 26} z must {int2word 27} aa must {int2word 52} az must {int2word 53} ba must {int2word [word2int suchenwi]} suchenwi #--------------------- Systematic testing in a loop for {set i 1} {$i<10000} {incr i} { if {[word2int [int2word $i]] != $i} { error "$i: [int2word $i] / [word2int [int2word $i]]" } }