2009-09-16 9 views
1

Je veux générer une séquence comme une table de multiplication. Donc, pour un début de 1 et un arrêt de 10 Je suis à la recherche d'une séquence commeComment générer une séquence de tables de multiplication?

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 1*1 - 1*10 
2, 4, 6, 8, 10, 12, 14, 16, 18, 20, // 2*1 - 2*10 
3, 6, 9, 12, ... // 3*1 - 3*10 

Voici mon début boiteuse, je ne peux cependant pas sembler comprendre comment incrémenter proprement j lorsque la butée est atteint, ou comment réinitialiser je revenir au début.

let multable (start,stop) = 
    (start,start) 
    |> Seq.unfold(
     fun (i,j) -> 
     Some(i*j, (i+1, j))) 

let its = multable(1, 1) 

let first10 = Seq.take 10 its 
printf "%A" (Seq.to_list first10) 

qui bien sûr me donne 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Répondre

3

utiliser une expression de la séquence:

let multable start stop = seq{ 
    for a = start to stop do 
     for b = start to stop do 
     yield a*b 
} 

sortie:

> multable 1 3 |> Seq.to_list;; 
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9] 

Il est bizarre de représenter une structure fondamentalement 2d de cette façon. Pourquoi pas une séquence de séquences:

let multable2 start stop = seq { 
    for a = start to stop do yield seq { 
     for b = start to stop do 
     yield a*b 
    } 
} 

Sortie:

val multable2 : int -> int -> seq<seq<int>> 

> multable2 1 3 |> Seq.to_list;; 
val it : seq<int> list = [seq [1; 2; 3]; seq [2; 4; 6]; seq [3; 6; 9]] 

Si vous voulez être "intelligent" et éviter la multiplication:

let multable4 start stop = seq { 
    for a = start to stop do yield seq { 
     let s = ref 0 in 
     for b = start to stop do 
     s:=!s+a 
     yield !s 
    } 
} 

je ne vois pas vraiment une belle "séquence de a à b" préemballée en dehors des expressions de séquence/de séquence, bien qu'il y ait évidemment [a..b] (liste) et [| a..b |] (tableau) que vous pouvez projeter à travers Seq.unfold, Seq. carte, etc. pour faire un Seq.

+0

Merci, j'ai fini par aller avec la première construction. Je veux être capable de filtrer la séquence de tous ces nombres. Il pourrait être possible de filtrer la 2ème 'dimension' de ces séquences, mais cela me semble plus facile. – esac

3

Je ne peux pas vraiment penser bien des cas où je préfère Seq.unfold sur une compréhension de liste équivalente:

> let multiplication n m = [for a in 1 .. n -> [for b in 1 .. m -> a * b ] ];; 

val multiplication : int -> int -> int list list 

> multiplication 5 5;; 
val it : int list list = 
    [[1; 2; 3; 4; 5]; [2; 4; 6; 8; 10]; [3; 6; 9; 12; 15]; [4; 8; 12; 16; 20]; 
    [5; 10; 15; 20; 25]] 

De temps en temps les méthodes Array.init sont utiles aussi:

> let multiplication n m = Array2D.init n m (fun n m -> n * m);; 

val multiplication : int -> int -> int [,] 

> multiplication 5 5;; 
val it : int [,] = [[0; 0; 0; 0; 0] 
        [0; 1; 2; 3; 4] 
        [0; 2; 4; 6; 8] 
        [0; 3; 6; 9; 12] 
        [0; 4; 8; 12; 16]] 
1
let Table r c = 
    [for row in 1..r do 
     yield [for col in 1..c do 
        yield row * col]] 
printfn "%A" (Table 5 4)      
// [[1; 2; 3; 4]; [2; 4; 6; 8]; [3; 6; 9; 12]; [4; 8; 12; 16]; [5; 10; 15; 20]] 
0

Voici une autre façon d'utiliser des séquences:

let rec fromXToY x y = 
    seq { 
    if x <= y 
    then yield x; yield! fromXToY (x + 1) y; 
    else() 
    } 

let scaledSequence factor items = 
    Seq.map (fun x -> factor * x) items 

let mulTable x y = 
    let sequenceOfIntegersMultipliedByValue = (fun n -> scaledSequence n (fromXToY x y)) 
    let seqOfSeqOfValues = Seq.map sequenceOfIntegersMultipliedByValue (fromXToY x y) 
    // Convert the sequence of sequences to a simple sequence of values 
    Seq.fold Seq.append Seq.empty seqOfSeqOfValues