6 people like it.
Like the snippet!
Use of Active Patterns to convert integer to Roman numerals
A good use case for demonstrating the use of active patterns
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:
|
open System
let rep times letter = [for _ in 1 .. times -> letter]
let div n divisor letter =
let q = n / divisor
if q > 0 then
let roman = rep q letter
let rem = n % divisor
Some(roman,rem)
else
None
let sub n divisor letterList = if n / divisor > 0 then Some(letterList,n - divisor) else None
let (|Thousand|_|) n = div n 1000 'M'
let (|NineH|_|) n = sub n 900 ['C';'M']
let (|FiveH|_|) n = div n 500 'D'
let (|FourH|_|) n = sub n 400 ['C';'D']
let (|Hundred|_|) n = div n 100 'C'
let (|Ninety|_|) n = sub n 90 ['X';'C']
let (|Fifty|_|) n = div n 50 'L'
let (|Forty|_|) n = sub n 40 ['X';'L']
let (|Ten|_|) n = div n 10 'X'
let (|Nine|_|) n = sub n 9 ['I';'X']
let (|Five|_|) n = div n 5 'V'
let (|Four|_|) n = sub n 4 ['I';'V']
let (|One|_|) n = div n 1 'I'
let toRoman (n:int) =
let rec loop acc dvnd =
match dvnd with
| 0 -> String(acc |> List.rev |> List.collect (fun x->x) |> List.toArray)
| Thousand (roman,rem)
| NineH (roman,rem)
| FiveH (roman,rem)
| FourH (roman,rem)
| Hundred (roman,rem)
| Ninety (roman,rem)
| Fifty (roman,rem)
| Forty (roman,rem)
| Ten (roman,rem)
| Nine (roman,rem)
| Five (roman,rem)
| Four (roman,rem)
| One (roman,rem) -> loop (roman::acc) rem
| _ -> failwithf "unable to convert %A" dvnd
loop [] n
toRoman 3999 //"MMMCMXCIX"
toRoman 3000 //"MMM"
toRoman 495 //"CDXCV"
toRoman 1 // "I"
toRoman 2 // "II"
|
namespace System
val rep : times:int -> letter:'a -> 'a list
val times : int
val letter : 'a
val div : n:int -> divisor:int -> letter:'a -> ('a list * int) option
val n : int
val divisor : int
val q : int
val roman : 'a list
val rem : int
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
val sub : n:int -> divisor:int -> letterList:'a -> ('a * int) option
val letterList : 'a
val toRoman : n:int -> String
Multiple items
val int : value:'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val loop : (char list list -> int -> String)
val acc : char list list
val dvnd : int
Multiple items
type String =
new : value:char[] -> string + 8 overloads
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : value:obj -> int + 1 overload
member Contains : value:string -> bool + 3 overloads
member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
member EndsWith : value:string -> bool + 3 overloads
member EnumerateRunes : unit -> StringRuneEnumerator
member Equals : obj:obj -> bool + 2 overloads
member GetEnumerator : unit -> CharEnumerator
...
--------------------
String(value: char []) : String
String(value: nativeptr<char>) : String
String(value: nativeptr<sbyte>) : String
String(value: ReadOnlySpan<char>) : String
String(c: char, count: int) : String
String(value: char [], startIndex: int, length: int) : String
String(value: nativeptr<char>, startIndex: int, length: int) : String
String(value: nativeptr<sbyte>, startIndex: int, length: int) : String
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : String
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IReadOnlyList<'T>
interface IReadOnlyCollection<'T>
interface IEnumerable
interface IEnumerable<'T>
member GetReverseIndex : rank:int * offset:int -> int
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
...
val rev : list:'T list -> 'T list
val collect : mapping:('T -> 'U list) -> list:'T list -> 'U list
val x : char list
val toArray : list:'T list -> 'T []
active recognizer Thousand: int -> (char list * int) option
val roman : char list
active recognizer NineH: int -> (char list * int) option
active recognizer FiveH: int -> (char list * int) option
active recognizer FourH: int -> (char list * int) option
active recognizer Hundred: int -> (char list * int) option
active recognizer Ninety: int -> (char list * int) option
active recognizer Fifty: int -> (char list * int) option
active recognizer Forty: int -> (char list * int) option
active recognizer Ten: int -> (char list * int) option
active recognizer Nine: int -> (char list * int) option
active recognizer Five: int -> (char list * int) option
active recognizer Four: int -> (char list * int) option
active recognizer One: int -> (char list * int) option
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T
More information