F#阿姆斯特朗号码流

时间:2014-10-28 09:26:25

标签: f#

我正在寻求帮助,主要是因为我对F#环境很新。我需要使用F#stream来生成无限的Armstrong数字流。任何人都可以帮助这个。我做了一些mambo jumbo,但我不知道我要去哪里。

type 'a stream = | Cons of 'a * (unit -> 'a stream)
let rec take n (Cons(x, xsf)) =
  if n = 0 then []
           else x :: take (n-1) (xsf());;

//to test if two integers are equal
let test x y =
   match (x,y) with
   | (x,y) when x < y -> false
   | (x,y) when x > y -> false
   | _ -> true

//to check for armstrong number
let check n = 
    let mutable m = n
    let mutable r = 0
    let mutable s = 0
    while m <> 0 do
        r <- m%10
        s <- s+r*r*r
        m <- m/10
    if (test n s) then true else false

let rec armstrong n =
    Cons (n, fun () -> if check (n+1) then armstrong (n+1) else armstrong (n+2))

let pos = armstrong 0
take 5 pos

1 个答案:

答案 0 :(得分:3)

说实话,你的代码看起来有点混乱。

我能想到的最基本的版本是:

let isArmstrong (a,b,c) =
    a*a*a + b*b*b + c*c*c = (a*100+b*10+c)

let armstrongs =
    seq {
        for a in [0..9] do
        for b in [0..9] do
        for c in [0..9] do
        if isArmstrong (a,b,c) then yield (a*100+b*10+c)
    }

当然假设阿姆斯特朗号是一个3位数字,其中数字的多维数据集之和就是数字本身

这会让你:

> Seq.toList armstrongs;;
val it : int list = [0; 1; 153; 370; 371; 407]

但是应该很容易添加更宽的范围或删除一位数字(想一想)。

一般情况

这个问题看起来很有趣,我选择实施一般情况(见这里):

let numbers =
    let rec create n =
        if n = 0 then [(0,[])] else
        [
            for x in [0..9] do
            for (_,xs) in create (n-1) do
            yield (n, x::xs)
        ]
    Seq.initInfinite create |> Seq.concat

let toNumber (ds : int list) =
    ds |> List.fold (fun s d -> s*10I + bigint d) 0I

let armstrong (m : int, ds : int list) =
    ds |> List.map (fun d -> bigint d ** m) |> List.sum

let leadingZero = 
    function
    | 0::_ -> true
    | _    -> false

let isArmstrong (m : int, ds : int list) =
    if leadingZero ds then false else
    let left = armstrong (m, ds)
    let right = toNumber ds
    left = right

let armstrongs =
    numbers
    |> Seq.filter isArmstrong
    |> Seq.map (snd >> toNumber)

但是这些数字很快变得非常稀疏,使用它很快就会让你失去记忆但是 前20个是:

> Seq.take 20 armstrongs |> Seq.map string |> Seq.toList;;
val it : string list =
  ["0"; "1"; "2"; "3"; "4"; "5"; "6"; "7"; "8"; "9"; "153"; "370"; "371";
   "407"; "1634"; "8208"; "9474"; "54748"; "92727"; "93084"]

备注/条款

这是最基本的版本 - 如果您只是枚举所有数字并使用基本数学来获取和取幂数字,您可以获得更高的速度/性能;)...确定您可以弄明白