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