Last active
December 2, 2023 06:11
-
-
Save yamasushi/d250be27cb9115aeb55ec81a9c9b28a8 to your computer and use it in GitHub Desktop.
integer <----> roman numeral
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# integer ----> roman numeral | |
# Compilers 1st ed. ex. P2.1 (p. 81) | |
# Compilers 2nd ed. ex. 2.3.3 (p. 60) | |
# https://gist.github.com/yamasushi/d250be27cb9115aeb55ec81a9c9b28a8 | |
#----------------------------------------------- | |
# integer --> roman numeral | |
#----------------------------------------------- | |
# N -> N D | D | |
# N -> D R1 { N.s = n->roman(R1.k , D.d ) + R1.s } | |
# R -> D R1 { R.k = R1.k + 1 , R.s = n->roman(R1.k , D.d ) + R1.s } | |
# R -> ε { R.k = 0 , R.s= "" } | |
def integer2roman(num) | |
s,xs=I2r.N(num.to_s.chars) | |
#printf "s=#{s} , xs=#{xs}" | |
s | |
end | |
class I2r | |
@@num_table=[ | |
["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"], # 1 ~ 9 | |
["X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], # 10 ~ 90 | |
["C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"], # 100 ~ 900 | |
["M", "MM", "MMM" ] ] # 1000 ~ 3000 | |
def self.n2roman(t,n) | |
return "" if n <= 0 | |
@@num_table[t][n-1] | |
end | |
# N -> D R1 { N.s = n->roman(R1.k , D.d ) + R1.s } | |
def self.N(xs) | |
raise "error N: xs=#{xs}" if xs.nil? or xs.empty? or xs[0]!~/[0-9]/ | |
d=xs[0].to_i | |
k,s,xs=R(xs[1..]) | |
[n2roman(k,d)+s , xs] | |
end | |
# R -> D R1 { R.k = R1.k + 1 , R.s = n->roman(R1.k , D.d ) + R1.s } | |
# R -> ε { R.k = 0 , R.s= "" } | |
def self.R(xs) | |
return raise "error R:" if xs.nil? | |
return [0,"",xs] if xs.empty? or xs[0] !~ /[0-9]/ #ε | |
d=xs[0].to_i | |
k,s,xs=R(xs[1..]) | |
[k+1 , n2roman(k,d)+s , xs] | |
end | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# roman numeral ---> integer | |
# https://gist.github.com/yamasushi/d250be27cb9115aeb55ec81a9c9b28a8 | |
# Compilers 2nd ed. ex. 2.3.4 (p. 60) | |
#----------------------------------------------- | |
# roman numeral ---> integer | |
#----------------------------------------------- | |
def roman2integer(str) | |
n,xs=R2i.N (str.chars) | |
n | |
end | |
class R2i | |
def self.M0(xs) | |
M("I","V","X",xs) | |
end | |
def self.M1(xs) | |
M("X","L","C",xs) | |
end | |
def self.M2(xs) | |
M("C","D","M",xs) | |
end | |
def self.M3(xs) | |
M("M",nil,nil,xs) | |
end | |
def self.N(xs) | |
n3,xs=M3(xs) | |
n2,xs=M2(xs) | |
n1,xs=M1(xs) | |
n0,xs=M0(xs) | |
[ n3*1000 + n2*100 + n1*10 + n0 , xs] | |
end | |
def self.M( _I , _V, _X , xs) | |
# R -> I {R.n = 1} | ε {R.n = 0} | |
_R=lambda{|xs| | |
return [0,xs] if xs.empty? # ε | |
case xs[0] | |
when _I | |
return [ 1 , xs[1..]] | |
else | |
return [ 0 , xs ] # ε | |
end | |
} | |
# P -> I R {P.n = 1 + R.n } | |
# | V {P.n = 3 } | |
# | X {P.n = 8 } | |
# | ε {P.n = 0 } | |
_P=lambda{ |xs| | |
return [0,xs] if xs.empty? # ε | |
case xs[0] | |
when _I | |
n, xs = _R::(xs[1..]) | |
return [ 1+n , xs ] | |
when _V | |
return [ 3 , xs[1..] ] | |
when _X | |
return [ 8 , xs[1..] ] | |
else | |
return [ 0 , xs ] # ε | |
end | |
} | |
# S -> I R {S.n = 1 + R.n} | ε {S.n = 0} | |
_S=lambda{|xs| | |
return [0,xs] if xs.empty? # ε | |
case xs[0] | |
when _I | |
n, xs = _R::(xs[1..]) | |
return [ n+1 , xs ] | |
else | |
return [ 0 , xs ] # ε | |
end | |
} | |
# Q -> I S {Q.n = 1 + S.n} | ε {Q.n = 0} | |
_Q=lambda{|xs| | |
return [0,xs] if xs.empty? # ε | |
case xs[0] | |
when _I | |
n, xs= _S::( xs[1..] ) | |
return [ n+1 , xs ] | |
else | |
return [ 0 , xs ] # ε | |
end | |
} | |
# M -> I P {M.n = 1 + P.n } | |
# | V Q {M.n = 5 + Q.n } | |
# | ε M.n = 0 | |
return [0,xs] if xs.empty? # ε | |
case xs[0] | |
when _I | |
n, xs = _P::(xs[1..]) | |
return [ n+1 , xs ] | |
when _V | |
n, xs = _Q::(xs[1..]) | |
return [ 5+n , xs ] | |
else | |
return [ 0 , xs ] # ε | |
end | |
end # def self.M | |
end # class |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# test roman numeral <--> integer | |
# https://gist.github.com/yamasushi/d250be27cb9115aeb55ec81a9c9b28a8 | |
load "./i2r.rb" | |
load "./r2i.rb" | |
def test_roman(max) | |
max.times do |i| | |
r=integer2roman(i) | |
j=roman2integer(r) | |
puts "#{i} --i2r--> #{r} --r2i--> #{j}" | |
raise "error!" if i!=j | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment