2014-10-28 39 views
-1

我在尋求幫助,主要是因爲我對F#環境很新。我需要使用F#流來生成無限的阿姆斯壯數字流。任何人都可以幫助這個。我做了一些曼波巨無霸,但我不知道我要去哪裏。F#阿姆斯特朗數字流

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 
+2

那麼,你堅持?對我來說,這段代碼看起來是由兩個完全不同的人寫的('stream'的定義相當先進,但'test'函數有點奇怪)。 – 2014-10-28 09:31:55

+0

它是否需要成爲你的''蒸汽'或你可以'seq'?請爲* Armstrong Number *添加一個不想去Google搜索的人的定義;) – Carsten 2014-10-28 09:38:37

+0

正如Carsten指出的那樣,'seq'是: http://msdn.microsoft.com/en- gb/library/dd233209.aspx – Mau 2014-10-28 10:07:33

回答

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"] 

備註/聲明

這是最基本的版本 - 如果您只是枚舉所有數字並使用基本的數學運算來獲取和取冪數字,您可以獲得大的速度/性能;)...確定您可以算出它

+0

謝謝Carsten,這就是爲什麼我需要使用F#流,因爲它是一個無限的列表,我還沒有學過seq,但是謝謝你的解釋。 – mambo 2014-10-28 11:34:43