caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Nathan Mishra Linger" <nathan.mishralinger@gmail.com>
To: "Ashish Agarwal" <agarwal1975@gmail.com>
Cc: caml-list <caml-list@yquem.inria.fr>
Subject: Re: [Caml-list] is there a Roman Numeral library
Date: Sat, 15 Mar 2008 23:20:51 -0700	[thread overview]
Message-ID: <ab0c618e0803152320v253bd91ex5ca70d8c5b78bcc@mail.gmail.com> (raw)
In-Reply-To: <d8be5ae20803140950s6a0e3d98l39600975b8a6d418@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 611 bytes --]

Hi Ashish,

Here is something I wrote a while back.  Let me know if it works out for
you.

Nathan

2008/3/14 Ashish Agarwal <agarwal1975@gmail.com>:

> Hi all. Does anyone have an OCaml libary for working with Roman Numerals?
> Probably easy to write but am hoping it already exists. Thank you.
>
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

[-- Attachment #1.2: Type: text/html, Size: 1164 bytes --]

[-- Attachment #2: roman.ml --]
[-- Type: text/plain, Size: 2426 bytes --]

(*
        roman numeral conversions
 *)

(******************************************************************************)
(* arabic <== roman *)

exception BadNumeral of char

let eval = function
  | 'I' ->         1
  | 'V' ->         5
  | 'X' ->        10
  | 'L' ->        50
  | 'C' ->       100
  | 'D' ->       500
  | 'M' ->      1000
  | c   -> raise(BadNumeral(c))

let arabic x = 
  let n = String.length x in
  let rec loop i v p =
        if i < n then
          let c = eval (String.get x i) in
          loop (i+1) (if p < c then v-p else v+p) c
        else v + p
  in
    if n > 0
    then let v = eval (String.get x 0) in loop 1 0 v
    else 0

(******************************************************************************)
(* (arabic ==> roman) abstract interpretation on SIZES *)

let numerals_size = 7

let digit_size = function
  | 0 -> 0 | 1 -> 1 | 2 -> 2 | 3 -> 3 | 4 -> 2
  | 5 -> 1 | 6 -> 2 | 7 -> 3 | 8 -> 4 | 9 -> 2
  | _ -> assert false

let rec count_size k = function
  | (0,_) -> k
  | (n,j) ->
        if j >= 3
        then count_size (digit_size (n mod 10) + k) (n/10,j-2)
        else n+k

let roman_size n =
        if n < 0 then 0 else
        count_size 0 (n,numerals_size)

(******************************************************************************)
(* arabic ==> roman *)

exception Negative

let numerals = ['I';'V';'X';'L';'C';'D';'M']

let roman n =
  let size = roman_size n in
  let x = String.make size 'M' in
  let ( ++ ) c k = String.set x k c; k-1 in
  let digit d one five ten k =
    match d with
    | 0 -> k
    | 1 ->  one ++ k
    | 2 ->  one ++ (one ++ k)
    | 3 ->  one ++ (one ++ (one ++ k))
    | 4 ->  one ++ (five ++ k)
    | 5 -> five ++ k
    | 6 -> five ++ (one ++ k)
    | 7 -> five ++ (one ++ (one ++ k))
    | 8 -> five ++ (one ++ (one ++ (one ++ k)))
    | 9 ->  one ++ (ten ++ k)
    | _ -> raise Negative
  in
  let rec count k = function
   | 0,_ -> ()
   | n,[_] -> ()
   | n,(one :: five :: ((ten :: _) as next)) ->
        count (digit (n mod 10) one five ten k) (n/10, next)
   | _ -> assert false
  in
  count (size-1) (n,numerals); x

(******************************************************************************)
(* debugging *)

let debug = false

let () = if debug then begin
  let rec upto i j = if i > j then [] else i :: upto (i+1) j in
  let test n = arabic (roman n) = n in
  let _ = List.for_all test (upto 0 5000) in
  ()
end


[-- Attachment #3: roman.mli --]
[-- Type: application/octet-stream, Size: 106 bytes --]


exception BadNumeral of char

val arabic : string -> int

exception Negative

val roman : int -> string


  parent reply	other threads:[~2008-03-16  6:21 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-14 16:50 Ashish Agarwal
2008-03-14 20:29 ` [Caml-list] " Dave Benjamin
2008-03-16  6:20 ` Nathan Mishra Linger [this message]
2008-03-16 23:25   ` Ashish Agarwal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ab0c618e0803152320v253bd91ex5ca70d8c5b78bcc@mail.gmail.com \
    --to=nathan.mishralinger@gmail.com \
    --cc=agarwal1975@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).