source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/math/romannumerals.tcl @ 8597867d

1941-docker-image-to-testdevel
Last change on this file since 8597867d was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 4.9 KB
Line 
1#==========================================================================
2# Roman Numeral Utility Functions
3#==========================================================================
4# Description
5#
6#   A set of utility routines for handling and manipulating
7#   roman numerals.
8#-------------------------------------------------------------------------
9# Copyright/License
10#
11#   This code was originally harvested from the Tcler's
12#   wiki at http://wiki.tcl.tk/1823 and as such is free
13#   for any use for any purpose.
14#-------------------------------------------------------------------------
15# Modification history
16#
17#   27 Sep 2005 Kenneth Green
18#       Original version derived from wiki code
19#-------------------------------------------------------------------------
20
21package provide math::roman 1.0
22
23#==========================================================================
24# Namespace
25#==========================================================================
26namespace eval ::math::roman {
27    namespace export tointeger toroman
28
29    # We dont export 'sort' or 'expr' to prevent collision
30    # with existing commands. These functions are less likely to be
31    # commonly used and have to be accessed as fully-scoped names.
32
33    # romanvalues - array that maps roman letters to integer values.
34    #
35    variable romanvalues
36
37    # i2r - list of integer-roman tuples
38    variable i2r {1000 M 900 CM 500 D 400 CD 100 C 90 XC 50 L 40 XL 10 X 9 IX 5 V 4 IV 1 I}
39
40    # sortkey - list of patterns to supporting sorting of roman numerals
41    variable sortkey {IX VIIII L Y XC YXXXX C Z D {\^} ZM {\^ZZZZ} M _}
42    variable rsortkey {_ M {\^ZZZZ} ZM {\^} D Z C YXXXX XC Y L VIIII IX}
43
44    # Initialise array variables
45    array set romanvalues {M 1000 D 500 C 100 L 50 X 10 V 5 I 1}
46}
47
48#==========================================================================
49# Public Functions
50#==========================================================================
51
52#----------------------------------------------------------
53# Roman numerals sorted
54#
55proc ::math::roman::sort list {
56    variable sortkey
57    variable rsortkey
58
59    foreach {from to} $sortkey {
60        regsub -all $from $list $to list
61    }
62    set list [lsort $list]
63    foreach {from to} $rsortkey {
64        regsub -all $from $list $to list
65    }
66    return $list
67}
68
69#----------------------------------------------------------
70# Roman numerals from integer
71#
72proc ::math::roman::toroman {i} {
73    variable i2r
74
75    set res ""
76    foreach {value roman} $i2r {
77        while {$i>=$value} {
78            append res $roman
79            incr i -$value
80        }
81    }
82    return $res
83}
84
85#----------------------------------------------------------
86# Roman numerals parsed into integer:
87#
88proc ::math::roman::tointeger {s} {
89    variable romanvalues
90
91    set last 99999
92    set res  0
93    foreach i [split [string toupper $s] ""] {
94        if { [catch {set val $romanvalues($i)}] } {
95            return -code error "roman::tointeger - un-Roman digit $i in $s"
96        }
97        incr res $val
98        if { $val > $last } {
99            incr res [::expr -2*$last]
100        }
101        set last $val
102    }
103    return $res
104}
105
106#----------------------------------------------------------
107# Roman numeral arithmetic
108#
109proc ::math::roman::expr args {
110
111    if { [string first \$ $args] >= 0 } {
112        set args [uplevel subst $args]
113    }
114
115    regsub -all {[^IVXLCDM]} $args { & } args
116    foreach i $args {
117        catch {set i [tointeger $i]}
118        lappend res $i
119    }
120    return [toroman [::expr $res]]
121}
122
123#==========================================================
124# Developer test code
125#
126if { 0 } {
127
128    puts "Basic int-to-roman-to-int conversion test"
129    for { set i 0 } {$i < 50} {incr i} {
130        set r [::math::roman::toroman   $i]
131        set j [::math::roman::tointeger $r]
132        puts [format "%5d   %-15s %s" $i $r $j]
133        if { $i != $j } {
134            error "Invalid conversion: $i -> $r -> $j"
135        }
136    }
137
138    puts ""
139    puts "roman arithmetic test"
140    set x 23
141    set xr [::math::roman::toroman $x]
142    set y 77
143    set yr [::math::roman::toroman $y]
144    set xr+yr [::math::roman::expr $xr + $yr]
145    set yr-xr [::math::roman::expr $yr - $xr]
146    set xr*yr [::math::roman::expr $xr * $yr]
147    set yr/xr [::math::roman::expr $yr / $xr]
148    set yr/xr2 [::math::roman::expr {$yr / $xr}]
149    puts "$x + $y\t\t= [expr $x + $y]"
150    puts "$x * $y\t\t= [expr $x * $y]"
151    puts "$y - $x\t\t= [expr $y - $x]"
152    puts "$y / $x\t\t= [expr $y / $x]"
153    puts "$xr + $yr\t= ${xr+yr} = [::math::roman::tointeger ${xr+yr}]"
154    puts "$xr * $yr\t= ${xr*yr} = [::math::roman::tointeger ${xr*yr}]"
155    puts "$yr - $xr\t= ${yr-xr} = [::math::roman::tointeger ${yr-xr}]"
156    puts "$yr / $xr\t= ${yr/xr} = [::math::roman::tointeger ${yr/xr}]"
157    puts "$yr / $xr\t= ${yr/xr2} = [::math::roman::tointeger ${yr/xr2}]"
158
159    puts ""
160    puts "roman sorting test"
161    set l {X III IV I V}
162    puts "IN : $l"
163    puts "OUT: [::math::roman::sort $l]"
164}
Note: See TracBrowser for help on using the repository browser.