hier, j'ai commencé à regarder F # pendant un temps libre. Je pensais que je commencerais avec le problème standard d'imprimer tous les nombres premiers jusqu'à 100. Heres ce que j'ai proposé ... La chose est que je me sens comme si j'avais approché cette d'une perspective C / C # et non embrassé le véritable aspect de la langue fonctionnelle. P> Je me demandais ce que les autres personnes pouvaient proposer - et si quelqu'un a des conseils / des pointeurs / des suggestions. Je me sens bien que le contenu est difficile à venir sur le Web pour le moment, et la dernière langue fonctionnelle que j'ai touchée était J'espère il y a environ 5 ans à l'université. p> p>
7 Réponses :
Suggestion simple mais inefficace: p>
Pour que cela fonctionne efficacement, vous souhaitez vraiment tester un chiffre d'être primordial en vérifiant s'il est divisible par des nombres premiers inférieurs, ce qui nécessitera une mémoire de mémoire. Probablement préférable d'attendre que vous obtenez la version simple qui fonctionne en premier :) p>
laissez-moi savoir si cela ne suffit pas d'un indice et je vais trouver un exemple complet - pensais que cela ne sera peut-être pas avant ce soir ... P>
Je voudrais mettre en œuvre cela en utilisant le tamis des eratosthènes ( en.wikipedia.org/wiki/sieve_of_eratosthenes ) . Je peux imaginer que pour être assez utilisable pour une approche fonctionnelle (bien que je ne sache rien du tout à propos de F #)
Utilisation d'une fonction de tamis comme Eratosthenes est un bon moyen d'y aller. Les langues fonctionnelles fonctionnent très bien avec des listes, alors je commencerais avec cela à l'esprit pour la force. P>
sur une autre note, les langages fonctionnels fonctionnent bien des fonctions (heh). Pour une langue fonctionnelle «Senteur», je construirais une fonction de tamis, puis appelez-la pour imprimer les nombres premiers. Vous pouvez même le scinder - une fonction construit la liste et fait tout le travail et l'un traverse et fait toute l'impression, séparant soigneusement la fonctionnalité. P>
Il y a quelques versions intéressantes ici A >. Et il y a des implémentations bien connues dans d'autres langues similaires. Voici un dans OCAML qui bat un C. P>
Voici une simple implication du Sieve of Eratosthenes en F #:
let rec sieve = function | (p::xs) -> p :: sieve [ for x in xs do if x % p > 0 then yield x ] | [] -> [] let primes = sieve [2..50] printfn "%A" primes // [2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47]
Nice, mais je pense que "List.Filter (Fun X -> X% P> 0) XS" serait plus idiomatique que la compréhension de la liste explicite.
Gardez à l'esprit que ce n'est pas un vrai tamis. Cet algorithme est très lent (mauvaise complexité asymptotique par rapport au tamis réel).
Laissez-moi vous expliquer la différence. Le tamis des eratosthènes ne marque que des multiples du nombre premier actuel ( p code> dans votre code). Donc, ceci est un nombre de multiples des étapes de nombres premiers actuels. Votre code effectue cependant un test de divisibilité pour tous les numéros restants, pas seulement les multiples. Comme les chiffres deviennent volumineux, il y a beaucoup plus de multiples que de multiples, votre algorithme fait donc beaucoup de travail supplémentaire par rapport au tamis réel.
L'idée vient de ce papier génial: CS.HMC.EDU/~ Oneill / Papers / Sieve-jfp.pdf
Merci pour les informations, très intéressantes! Ce code n'était qu'un port de l'exemple de Haskell trouvé sur le lien ci-dessus.
Vous ne voulez certainement pas apprendre de cet exemple, mais j'ai écrit une implémentation F # de A Tamis de journaux basé sur le passage du message:
> let p = new primes();; val p : primes > p.Next();; val it : int = 2 > p.Next();; val it : int = 3 > p.Next();; val it : int = 5 > p.Next();; val it : int = 7 > p.Next();; val it : int = 11 > p.Next();; val it : int = 13 > p.Next();; val it : int = 17 > primes.upto 100;; val it : int list = [2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71; 73; 79; 83; 89; 97]
Un peu de code là-bas pour quelqu'un qui le fait un jour :). Probablement passer votre exemple, mais merci lol ...
Voici Mon ancien poste à Hubfs < / a> À propos de l'utilisation de SEQ récursif pour implémenter le générateur de nombres premiers. P>
Pour le cas où vous voulez une implémentation rapide, il existe Nice Ocaml Code de Markus Mottl P>
P.s. Si vous souhaitez itérer le nombre de nombres premiers jusqu'à 10 ^ 20, vous voulez vraiment porter Port Prothenergen par D. J. Bernstein à F # / OCAML :) P>
Tout en résolvant le même problème, j'ai mis en œuvre Sieve of Atkins dans F#. C'est l'un des algorithmes modernes les plus efficaces.
// Create sieve let initSieve topCandidate = let result = Array.zeroCreate<bool> (topCandidate + 1) Array.set result 2 true Array.set result 3 true Array.set result 5 true result // Remove squares of primes let removeSquares sieve topCandidate = let squares = seq { 7 .. topCandidate} |> Seq.filter (fun n -> Array.get sieve n) |> Seq.map (fun n -> n * n) |> Seq.takeWhile (fun n -> n <= topCandidate) for n2 in squares do n2 |> Seq.unfold (fun state -> Some(state, state + n2)) |> Seq.takeWhile (fun x -> x <= topCandidate) |> Seq.iter (fun x -> Array.set sieve x false) sieve // Pick the primes and return as an Array let pickPrimes sieve = sieve |> Array.mapi (fun i t -> if t then Some i else None) |> Array.choose (fun t -> t) // Flip solutions of the first equation let doFirst sieve topCandidate = let set1 = Set.ofList [1; 13; 17; 29; 37; 41; 49; 53] let mutable x = 1 let mutable y = 1 let mutable go = true let mutable x2 = 4 * x * x while go do let n = x2 + y*y if n <= topCandidate then if Set.contains (n % 60) set1 then Array.get sieve n |> not |> Array.set sieve n y <- y + 2 else y <- 1 x <- x + 1 x2 <- 4 * x * x if topCandidate < x2 + 1 then go <- false // Flip solutions of the second equation let doSecond sieve topCandidate = let set2 = Set.ofList [7; 19; 31; 43] let mutable x = 1 let mutable y = 2 let mutable go = true let mutable x2 = 3 * x * x while go do let n = x2 + y*y if n <= topCandidate then if Set.contains (n % 60) set2 then Array.get sieve n |> not |> Array.set sieve n y <- y + 2 else y <- 2 x <- x + 2 x2 <- 3 * x * x if topCandidate < x2 + 4 then go <- false // Flip solutions of the third equation let doThird sieve topCandidate = let set3 = Set.ofList [11; 23; 47; 59] let mutable x = 2 let mutable y = x - 1 let mutable go = true let mutable x2 = 3 * x * x while go do let n = x2 - y*y if n <= topCandidate && 0 < y then if Set.contains (n % 60) set3 then Array.get sieve n |> not |> Array.set sieve n y <- y - 2 else x <- x + 1 y <- x - 1 x2 <- 3 * x * x if topCandidate < x2 - y*y then go <- false // Sieve of Atkin let ListAtkin (topCandidate : int) = let sieve = initSieve topCandidate [async { doFirst sieve topCandidate } async { doSecond sieve topCandidate } async { doThird sieve topCandidate }] |> Async.Parallel |> Async.RunSynchronously |> ignore removeSquares sieve topCandidate |> pickPrimes
Voici mes deux centimes: ou peut-être cette version plus claire de la même chose que isprime code> est définie comme une fonction distincte: p> < Pré> xxx pré> p>
À titre de note latérale, il est beaucoup hors de l'esprit de F # à utiliser
console.writeline code>. Je suggérerais d'utiliser
printfn "% i" i code> à la place.
Printf est plus typique et peut déduire des types.
Essayez de la réécriter à l'aide d'un pli.