OCaml

練習問題 5.2 ② リスト ローマ数字表現

練習問題 5.2 ②

与えられた正の整数のローマ字表現(文字列)を求める関数 roman。
I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000
ただし、roman は、単位となる数とローマ数字表現の組を大きいものから並べたリストで
表現した、ローマ数字の定義も引数として受け取ることにする。
たとえば、
# roman [(1000, “M”); (500, “D”); (100, “C”); (50, “L”); (10, “X”); (5, “V”); (1, “I”)] 1984;;
– : string = “MDCCCCLXXXIIII”
となる。
また、4, 9, 40, 90, 400, 900 などの表現にも注意して、
# roman [(1000, “M”); (900, “DM”); (500, “D”); (400, “CD”); (100, “C”); (90, “XC”);
(50, “L”); (40, “XL”); (10, “X”); (9, “IX”); (5, “V”); (4, “IV”); (1, “I”)] 1984;;
– : string =”MCMLXXXIV”
となるようにせよ。

(*
2. 与えられた正の整数のローマ字表現(文字列)を求める関数 roman。
I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000
ただし、roman は、単位となる数とローマ数字表現の組を大きいものから並べたリストで
表現した、ローマ数字の定義も引数として受け取ることにする。
たとえば、
# roman [(1000, "M"); (500, "D"); (100, "C"); (50, "L"); (10, "X"); (5, "V"); (1, "I")] 1984;;
- : string = "MDCCCCLXXXIIII"
となる。
また、4, 9, 40, 90, 400, 900 などの表現にも注意して、
# roman [(1000, "M"); (900, "DM"); (500, "D"); (400, "CD"); (100, "C"); (90, "XC"); 
(50, "L"); (40, "XL"); (10, "X"); (9, "IX"); (5, "V"); (4, "IV"); (1, "I")] 1984;;
- : string ="MCMLXXXIV"
となるようにせよ。
*)
  
let romanlist1 = [(1000, "M"); (500, "D"); (100, "C"); (50, "L"); (10, "X"); (5, "V"); (1, "I")];;

let romanlist2 = [(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")];;
  
  
let rec assoc a = function
    [] -> "Nothig"
   |(a', b) :: rest -> if a = a' then b else assoc a rest;;

let test81 = assoc 1000 romanlist1 = "M";;

(*
* pick_roman -- n 回 moji を連続表示する
* moji -- string ex."M", "D" ...
* n    -- int number
*)
let rec pick_roman moji n =
  if n = 0 then ""
  else
    moji ^ pick_roman moji (n-1);;

let test82 = pick_roman "M" 2 = "MM";;
  
(*
 * l -- list .. romanlist
 * n -- number .. ex.1984
 * return -- string .. ex."MDCCCLXXXIII"
 *)

let roman l n =
  (if ((n / 1000) > 0)
   then pick_roman "M" (n / 1000)
   else "")
  ^
    (let n2 = n mod 1000 in 
     if (n2 / 900) = 1
     then "CM"
     else pick_roman "D" (n2 / 500))
  ^
    (let n2 = ((n mod 1000) mod 900) mod 500 in        
     if (n2 / 100) = 4
     then "CD"
     else pick_roman "C" (n2 / 100))
  ^
    (let n2 = n mod 100 in
     if (n2 / 90) = 1
     then "XC"
     else pick_roman "L" (n2 / 50))
  ^
    (let n2 = ((n mod 100) mod 90) mod 50 in
     if (n2 / 10) = 4
     then "XL"
     else pick_roman "X" (n2 / 10))
  ^
    (let n2 = n mod 10 in
     if (n2 / 9) = 1
     then "IX"
     else pick_roman "V" (n2 / 5))
  ^
    (let n2 = ((n mod 10) mod 9) mod 5 in
     if n2 = 4
     then "IV"
     else pick_roman "I" n2);;

let test83 = roman romanlist1 1984 = "MCMLXXXIV";;
let test84 = roman romanlist1 1987 = "MCMLXXXVII";;

let test85 = roman romanlist2 1984 = "MCMLXXXIV";;
let test86 = roman romanlist2 1987 = "MCMLXXXVII";;

let test87 = roman romanlist2 1900 = "MCM";;
let test88 = roman romanlist2 1800 = "MDCCC";;
let test88 = roman romanlist2 1700 = "MDCC";;
let test88 = roman romanlist2 1600 = "MDC";;
let test88 = roman romanlist2 1500 = "MD";;
let test88 = roman romanlist2 1400 = "MCD";;
let test88 = roman romanlist2 1300 = "MCCC";;
let test89 = roman romanlist2 89 = "LXXXIX";;
  
  
(*
let roman l n =
  let m = n / 1000 when n / 1000 > 0 in
  let d = (n mod 1000) / 500 when (n mod 1000) / 500 > 0 in
  let c = (n mod 500) / 100 when (n mod 500) / 100 > 0 in
  let l = (n mod 100) / 50 when (n mod 100) / 50 > 0 in
  let x = (n mod 50) / 10 when (n mod 50) / 10 > 0 in
  let v = (n mod 10) / 5 when (n mod 10) / 5 > 0 in
  let i = (n mod 5) when n mod 5 > 0 in
  assoc 1000
 *)

let renketsu a b =
  (if a = 1
  then "A"
  else "B")
       ^
         (if b = 1
         then "X"
         else "Y");;

let test101 = renketsu 1 1 = "AX";;
let test102 = renketsu 1 2 = "AY";;
let test103 = renketsu 0 1 = "BX";;
let test104 = renketsu 2 1 = "BX";;
let test105 = renketsu 2 2 = "BY";;