2016-07-26 7 views
3

사용자가 루프 또는 메서드 내에서 많은 System.Random()을 인스턴스화하여 동일한 무작위 항목을 많이 생성하는 다른 질문을 검색했습니다. 시계. 하지만 여기서는 하나의 인스턴스가 System.Random()이지만 여러 개의 난수 목록을 생성하려고 할 때 모두 동일합니다. F # System.Random()을 사용하여 임의의 숫자 목록 가져 오기 동일한 목록 제공

module Scripts = 
let rnd = System.Random() 

let getRandom36 = 
    let rec generate (l : list<int>) = 
     match l.Length with 
     |8 -> l 
     |_ -> let number = rnd.Next 38 
       if(List.exists(fun elem -> elem=number) l) then generate l else generate (number::l) 
    List.sort(generate List.empty) 

let myseq = Seq.init 4 (fun _ -> getRandom36) 

중요한 부분

getRandom36 작품 내부의 코드는, 내가 다른 방식으로 작동하도록 함부로 변경되었습니다하지만 myseq;;를 호출 할 때 같은 모양리스트가 계속 방법을 정말하지 않습니다.

myseq;; 
val it : seq<int list> = 
    seq 
    [[2; 8; 10; 11; 18; 21; 22; 35]; [2; 8; 10; 11; 18; 21; 22; 35]; 
    [2; 8; 10; 11; 18; 21; 22; 35]; [2; 8; 10; 11; 18; 21; 22; 35]; ...] 

왜 그런가? 각 반복마다 rnd의 새 인스턴스가 작성되지 않았기 때문에 매번 rnd.Next이 달라야합니다.

+0

rnd.Next은 38는 0과 38 사이의 난수를 얻는 것입니다 :-) –

+0

예, 모바일에서 이것을 읽지 않아야합니다. – s952163

+0

재귀가되고 목록이 필요합니까? – s952163

답변

5

getRandom36은 값이 아닌 함수입니다. 아래와 같이 고정 할 수 있습니다

let rnd = System.Random() 

let getRandom36 _ = 
    let rec generate (l : list<int>) = 
     match l.Length with 
     |8 -> l 
     |_ -> let number = rnd.Next 38 
       if(List.exists(fun elem -> elem=number) l) then generate l else generate (number::l) 
    List.sort(generate List.empty) 

let myseq = Seq.init 4 getRandom36 
+0

와우, 이제 나는 매우 바보 같다. 고마워! –

+2

어리 석을 필요가 없습니다. 그것은 아주 흔한 실수입니다. – FuleSnabel

2

문제는 getRandom36가 아닌 값 함수 것입니다. 그것은 한 번 평가 된 다음 항상 동일한 목록을 반환합니다. 함수로를 켜고 제대로 작동합니다 :

module Scripts = 

    let rnd = System.Random() 

    let getRandom36() = 
     let rec generate (l : _ list) = 
      match l.Length with 
      | 8 -> l 
      | _ -> let number = rnd.Next 38 
        if List.exists (fun elem -> elem = number) l 
        then l else (number :: l) 
        |> generate 
     List.sort (generate []) 

    let myseq = Seq.init 4 (fun _ -> getRandom36()) 
0

영업 이익은 재귀를 사용하여 매우 구체적인 솔루션을 찾고 될 수도 있지만, MathDotNet 또는 주식을 사용하여 난수를 생성하기 쉬운/빠른 방법이 있습니다 System.Random.

#load @"..\..\FSLAB\packages\FsLab\FsLab.fsx" 

open MathNet.Numerics.LinearAlgebra 
open MathNet.Numerics.Distributions 
open MathNet.Numerics.Random 

let rng = Random.shared 
Array2D.init<int> 4 8 (fun i j -> rng.Next(38)) 

또는 :

예를 들어

[for i in 1..4 -> List.init 8 (fun x -> rnd.Next(38))]

그리고 예를 들어 이미 존재하는 배열을 채울 것입니다 .NextInt32s 같은 기능이 있습니다 :

let fillArray (x:int []) = rng.NextInt32s(x,0,38) 
let xs = [|for i in 1..4 -> Array.zeroCreate<int> 8|] 
xs |> Array.map (fun x -> fillArray(x))