F# F中数到罗马数字函数的进一步优化#
我是F#的新手,我很好奇这是否还可以进一步优化。我不太确定我是否也做对了。我对最后一行特别好奇,因为它看起来真的很长很可怕 我在谷歌上搜索过,但只显示了罗马数字对数字的解决方案,所以我很难进行比较F# F中数到罗马数字函数的进一步优化#,f#,functional-programming,F#,Functional Programming,我是F#的新手,我很好奇这是否还可以进一步优化。我不太确定我是否也做对了。我对最后一行特别好奇,因为它看起来真的很长很可怕 我在谷歌上搜索过,但只显示了罗马数字对数字的解决方案,所以我很难进行比较 type RomanDigit = I | IV | V | IX let rec romanNumeral number = let values = [ 9; 5; 4; 1 ] let capture number values = values
type RomanDigit = I | IV | V | IX
let rec romanNumeral number =
let values = [ 9; 5; 4; 1 ]
let capture number values =
values
|> Seq.find ( fun x -> number >= x )
let toRomanDigit x =
match x with
| 9 -> IX
| 5 -> V
| 4 -> IV
| 1 -> I
match number with
| 0 -> []
| int -> Seq.toList ( Seq.concat [ [ toRomanDigit ( capture number values ) ]; romanNumeral ( number - ( capture number values ) ) ] )
感谢所有能帮我解决这个问题的人。如果我必须用一个有歧视的联合体来代表罗马字母,我不会包括IV和IX
type RomanDigit = I|V|X
let numberToRoman n =
let (r, diff) =
if n > 8 then [X], n - 10
elif n > 3 then [V], n - 5
else [], n
if diff < 0 then I::r
else r @ (List.replicate diff I)
类型RomanDigit=I | V | X
设numberton=
let(r,diff)=
如果n>8,则[X],n-10
如果n>3,则[V],n-5
else[],n
如果差异<0,则I::r
else r@(List.replicate diff I)
然后,基于此解决方案,您可以进一步将其扩展到所有数字
这是我的第一次尝试,使用折叠和部分应用程序:
type RomanDigit = I|V|X|L|C|D|M
let numberToRoman n i v x =
let (r, diff) =
if n > 8 then [x], n - 10
elif n > 3 then [v], n - 5
else [], n
if diff < 0 then i::r
else r @ (List.replicate diff i)
let allDigits (n:int) =
let (_, f) =
[(I,V); (X,L); (C,D)]
|> List.fold (fun (n, f) (i, v) ->
(n / 10, fun x -> (numberToRoman (n % 10) i v x) @ f i)) (n, (fun _ -> []))
f M
类型RomanDigit=I | V | X | L | C | D | M
设numberton i v x=
let(r,diff)=
如果n>8,则[x],n-10
如果n>3,则[v],n-5
else[],n
如果差异<0,则i::r
else r@(List.replicate diff i)
让所有数字(n:int)=
让(u,f)=
[(I,V);(X,L);(C,D)]
|>列表。折叠(乐趣(n,f)(i,v)->
(n/10,fun x->(numberToRoman(n%10)i v x)@fi))(n,(fun->[]))
f M
递归查找可从值中减去的最大数字表示的略短方法(使用List.find):
let单位=
[1000,“M”
900,“厘米”
500,“D”
400,“CD”
100,“C”
90,“XC”
50,“L”
40,“XL”
10,“X”
9,“九”
5,“V”
4,“四”
1,“我”]
设rec TOROMANNUMEAL=函数
| 0 -> ""
|n->
让x,s=units |>List.find(fun(x,s)->x下面是@Philip Trelford答案的尾部递归版本:
let toRomanNumeral n =
let rec iter acc n =
match n with
| 0 -> acc
| n ->
let x, s = units |> List.find (fun (x, _) -> x <= n)
iter (acc + s) (n-x)
iter "" n
n=
让我们重新考虑一下=
匹配
|0->acc
|n->
让x,s=units |>List.find(fun(x,|)->x初始建议:不要使用Seq
到处使用数组(Seq.*
函数比array.*
要慢得多)可能fun(x,s)->x我想问一下n
用于什么样的模式?在toRomanNumeral函数中,n是生成数字的非零整数余数for@Chad它可能是(有趣的)->x
let toRomanNumeral n =
let rec iter acc n =
match n with
| 0 -> acc
| n ->
let x, s = units |> List.find (fun (x, _) -> x <= n)
iter (acc + s) (n-x)
iter "" n