12
votes

Apprendre f # - imprimer des nombres premiers

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é ... XXX

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.

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é.


3 commentaires

À titre de note latérale, il est beaucoup hors de l'esprit de F # à utiliser console.writeline . Je suggérerais d'utiliser printfn "% i" i à la place.


Printf est plus typique et peut déduire des types.


Essayez de la réécriter à l'aide d'un pli.


7 Réponses :


1
votes

Suggestion simple mais inefficace:

  • Créez une fonction pour tester si un seul numéro est PRIME
  • Créez une liste pour les numéros de 2 à 100
  • Filtrez la liste par la fonction
  • Composez le résultat avec une autre fonction pour imprimer les résultats

    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 :)

    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 ...


1 commentaires

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 #)



3
votes

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.

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é.

Il y a quelques versions intéressantes ici . Et il y a des implémentations bien connues dans d'autres langues similaires. Voici un dans OCAML qui bat un C.


0 commentaires

9
votes

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]


5 commentaires

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 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.



2
votes

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]


1 commentaires

Un peu de code là-bas pour quelqu'un qui le fait un jour :). Probablement passer votre exemple, mais merci lol ...



1
votes

Voici Mon ancien poste à Hubfs < / a> À propos de l'utilisation de SEQ récursif pour implémenter le générateur de nombres premiers.

Pour le cas où vous voulez une implémentation rapide, il existe Nice Ocaml Code de Markus Mottl

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 :)


0 commentaires

1
votes

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


0 commentaires

3
votes

Voici mes deux centimes: xxx

ou peut-être cette version plus claire de la même chose que isprime est définie comme une fonction distincte: < Pré> xxx


0 commentaires