Here's some "few-liner" code examples, contributed by [Richard Suchenwirth]. Help yourself! Add comments when you know it better! Use the Edit.. link at bottom of page for contributing! This page was split off from the more general [Bag of algorithms] page. ---- '''English number speller''', e.g. en:num 29 => twenty-nine proc en:num {n {optional 0}} { #---------------- English spelling for integer numbers if {[catch {set n [expr $n]}]} {return $n} if {$optional && $n==0} {return ""} array set dic { 0 zero 1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 eight 9 nine 10 ten 11 eleven 12 twelve } if [info exists dic($n)] {return $dic($n)} foreach {value word} {1000000 million 1000 thousand 100 hundred} { if {$n>=$value} { return "[en:num $n/$value] $word [en:num $n%$value 1]" } } ;#--------------- composing between 13 and 99... if $n>=20 { set res $dic([expr $n/10])ty if $n%10 {append res -$dic([expr $n%10])} } else { set res $dic([expr $n-10])teen } ;#----------- fix over-regular compositions regsub "twoty" $res "twenty" res regsub "threet" $res "thirt" res regsub "fourty" $res "forty" res regsub "fivet" $res "fift" res regsub "eightt" $res "eight" res set res } ;#RS See also the converse [English number reader]. ''I have more such spellers for Arab, Hebrew, Chinese, Thai, but can't paste them here because of Unicode constants (not \u.. escaped). Tcl 8.1+ lets us look into a world where Unicodes can be cut and pasted like everything -- but the future is some time after today;-)'' ---- '''Better English speller :)''' - it's a bit longer, but it supports up to 65 digits (or so. I forget :) set pronounce {vigintillion novemdecillion octodecillion \ septendecillion sexdecillion quindecillion quattuordecillion \ tredecillion duodecillion undecillion decillion nonillion \ octillion septillion sextillion quintillion quadrillion \ trillion billion million thousand ""} proc get_num num { foreach {a b} {0 {} 1 one 2 two 3 three 4 four 5 five 6 six 7 seven \ 8 eight 9 nine 10 ten 11 eleven 12 twelve 13 thirteen 14 \ fourteen 15 fifteen 16 sixteen 17 seventeen 18 eighteen 19 \ nineteen 20 twenty 30 thirty 40 forty 50 fifty 60 sixty 70 \ seventy 80 eighty 90 ninety} {if {$num == $a} {return $b}} return $num } proc revorder list { for {set x 0;set y [expr {[llength $list] - 1}]} {$x < $y} \ {incr x;incr y -1} { set t [lindex $list $x] set list [lreplace $list $x $x [lindex $list $y]] set list [lreplace $list $y $y $t] } return $list } proc pron_form num { global pronounce set x [join [split $num ,] {}] set x [revorder [split $x {}]] set pron "" set ct [expr {[llength $pronounce] - 1}] foreach {a b c} $x { set p [pron_num $c$b$a] if {$p != ""} { lappend pron "$p [lindex $pronounce $ct]" } incr ct -1 } return [join [revorder $pron] ", "] } proc pron_num num { set num [string trimleft $num 0-] set hundred "" set ten "" set len [string length $num] if {$len == 3} { set hundred "[get_num [string index $num 0]] hundred" set num [string range $num 1 end] } if {$num > 20 && $num != $num/10} { set tens [get_num [string index $num 0]0] set ones [get_num [string index $num 1]] set ten [join [concat $tens $ones] -] } else { set ten [get_num $num] } if {[string length $hundred] && [string length $ten]} { return [concat $hundred and $ten] } else { # One of these is empty, but don't bother to work out which! return [concat $hundred $ten] } } The result of the test below has been broken up over a few lines. :^) % pron_form 12345678901234567890123456789012345678901234567890123456789012344 twelve vigintillion, three hundred and forty-five novemdecillion, six hundred and seventy-eight octodecillion, nine hundred and one septendecillion, two hundred and thirty-four sexdecillion, five hundred and sixty-seven quindecillion, eight hundred and ninety quattuordecillion, one hundred and twenty-three tredecillion, four hundred and fifty-six duodecillion, seven hundred and eighty-nine undecillion, twelve decillion, three hundred and forty-five nonillion, six hundred and seventy-eight octillion, nine hundred and one septillion, two hundred and thirty-four sextillion, five hundred sixty-seven and quintillion, eight hundred and ninety quadrillion, one hundred and twenty-three trillion, four hundred fifty-six billion, seven hundred and eighty-nine million, twelve thousand, three hundred and forty-four % neat, eh? -keith lea :) ''DKF'': modified to put the word and in between a hundreds phrase and a tens-and-units phrase ---- '''French number speller''' fr:num 99 => quatrevingt dix-neuf proc fr:num {n {optional 0}} { if {[catch {set n [expr $n]}]} {return $n} if {$optional && $n==0} {return ""} array set dic { 0 zero 1 un 2 deux 3 trois 4 quatre 5 cinq 6 six 7 sept 8 huit 9 neuf 10 dix 11 onze 12 douze 13 treize 14 quatorze 15 quinze 16 seize 20 vingt 30 trente 40 quarante 50 cinquante 60 soixante 80 quatre-vingt } if [info exists dic($n)] {return $dic($n)} foreach {value word} {1000000 million 1000 mille 100 cent} { if {$n>=$value} { return "[fr:num $n/$value] $word [fr:num $n%$value 1]" } } ;#--------------- composing between 13 and 99... if $n>=80 { set res $dic(80) if $n>80 {append res -[fr:num $n-80]} } elseif $n>=60 { set res $dic(60) if $n>60 {append res -[fr:num $n-60]} } elseif $n>=20 { set res $dic([expr $n/10]0) if $n%10 {append res -$dic([expr $n%10])} } else { set res dix-[fr:num $n-10] } set res } ;#RS ---- '''German number speller''': proc de:num {n {optional 0}} { #---------------- German spelling for integer numbers if {[catch {set n [expr $n]}]} {return $n} if {$optional && $n==0} {return ""} array set dic { 0 null 1 ein 2 zwei 3 drei 4 vier 5 f�nf 6 sechs 7 sieben 8 acht 9 neun 10 zehn 11 elf 12 zw�lf } if [info exists dic($n)] {return $dic($n)} foreach {value word} {1000000 Million 1000 _tausend 100 _hundert_} { if {$n>=$value} { set res "[de:num $n/$value] $word [de:num $n%$value 1]" regsub " _" $res "" res regsub "_ " $res "" res return $res } } ;#--------------- composing between 13 and 99... if $n>=20 { set res $dic([expr $n/10])zig if $n%10 {set res $dic([expr $n%10])und$res} } else { set res $dic([expr $n-10])zehn } ;#----------- fix over-regular compositions regsub "chsz" $res "chz" res regsub "benz" $res "bz" res regsub "weizi" $res "wanzi" res regsub "dreizig" $res "drei�ig" res set res } ;#RS ---- '''Swedish number speller''': proc sv:num {n {optional 0}} { #---------------- Swedish spelling for integer numbers # Based on en|fr|de:num by Richard Suchenwirth # Adapted to Swedish by Peter Lewerin 2001-06-10 if {[catch {set n [expr $n]}]} {return $n} if {$optional && $n==0} {return ""} array set dic { 0 noll 1 ett 2 tv� 3 tre 4 fyra 5 fem 6 sex 7 sju 8 �tta 9 nio 10 tio 11 elva 12 tolv 14 fjorton 18 arton } if [info exists dic($n)] {return $dic($n)} foreach {value word} {1000000000 miljard 1000000 miljon 1000 _tusen 100 _hundra_} { if {$n>=$value} { set s {} if {$word == "miljard" || $word == "miljon"} { set v [expr {$n/$value}] if {$v == 1} { set s "en $word" } else { set s "[sv:num $v] ${word}er" } } else { set s "[sv:num $n/$value] ${word}" } set res "$s [sv:num $n%$value 1]" regsub " _" $res "" res regsub "_ " $res "" res regsub " $" $res "" res regsub "ttt" $res "tt" res return $res } } ;#--------------- composing between 13 and 99... if {$n>=20} { set res $dic([expr $n/10])tio if $n%10 {set res $res$dic([expr $n%10])} } else { set res $dic([expr $n-10])ton } ;#----------- fix over-regular compositions regsub "ret" $res "rett" res regsub "jut" $res "jutt" res regsub "niot" $res "nitt" res regsub "tv�ti" $res "tjug" res regsub "fyrat" $res "fyrt" res regsub "ttat" $res "tt" res set res } ---- '''German time speller''': converts exact HH:MM times to fuzzy colloquial wording, optional Northern (viertel vor vier) or Southern style (dreiviertel vier) ;-) Requires de:num (see above) proc de:time {{t now} {region n}} { # format HH:MM time to spoken German (north or south) set u "usage: de:time HH:MM|now ?n|s?" if {$t=="now"} {set t [clock format [clock seconds] -format %H:%M]} if [scan $t %d:%d h min]!=2 {error $u} array set dic { 5 f�nf z zehn V Viertel h halb d dreiviertel v vor n nach + "" }; # dictionary of words used (digits also from de:num) switch -- $region { n {set cdic {{} 5n zn Vn zvh 5vh h 5nh znh Vv zv 5v +}} s {set cdic {{} 5n zn V zvh 5vh h 5nh znh d zv 5v +}} default {error $u} }; # byte-coded names for 5-minute increments (see dic) set m5 [expr int(round($min/5.))] set phr [lindex $cdic $m5] if {[regexp {[vVhd+]} $phr] && ![regexp Vn $phr]} {incr h} if ![set h [expr $h%12]] {set h 12} if ![regexp {[vn]} $phr] { set d [expr $min-$m5*5] if $d<0 { set res "kurz vor " } elseif $d>0 { set res "kurz nach " } else { set res "genau " } } foreach i [split $phr ""] {if {$i!="+"} {lappend res $dic($i)}} lappend res [de:num $h] regsub ein$ $res eins res set res } ;#RS ---- '''Morse en/decoder''': works both ways ASCII <-> Morse proc morse {s} { global _morse if ![info exists _morse] { set _morse { 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 __.. 0 _____ 1 .____ 2 ..___ 3 ...__ 4 ...._ 5 ..... 6 _.... 7 __... 8 ___.. 9 ____. } } set res "" if [regexp {^[._ ]+$} $s] { regsub -all { +} $s " B " s foreach i [split $s] { if {$i==""} continue if {$i=="B"} {append res " "; continue} set ix [lsearch $_morse $i] if $ix>=0 { append res [lindex $_morse [expr $ix-1]] } else {append res ?} } } else { foreach i [split [string toupper $s] ""] { if {$i==""} continue if {$i==" "} {append res " "; continue} set ix [lsearch -exact $_morse $i] if {$ix>=0 && $ix%2==0} { append res "[lindex $_morse [expr $ix+1]] " } } } set res } ;#RS ---- '''[Roman numbers]''' have their own page now. ---- [Bag of algorithms] - [Arts and crafts of Tcl-Tk programming]