Как сгенерировать последовательность таблицы умножения?
Вопрос
Я хочу сгенерировать последовательность, подобную таблице умножения.Итак, для начала с 1 и остановки с 10 я ищу последовательность, подобную
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
Вот мое неудачное начало, однако, похоже, я не могу понять, как аккуратно увеличить j при достижении остановки или как сбросить i обратно к началу.
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)
Что, конечно, дает мне 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Решение
Используйте выражение последовательности:
let multable start stop = seq{
for a = start to stop do
for b = start to stop do
yield a*b
}
Выходной сигнал:
> multable 1 3 |> Seq.to_list;;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
Странно представлять фундаментально двумерную структуру таким образом.Почему бы не последовательность последовательностей:
let multable2 start stop = seq {
for a = start to stop do yield seq {
for b = start to stop do
yield a*b
}
}
Выходной сигнал:
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]]
Если вы хотите быть "умным" и избежать умножения:
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
}
}
На самом деле я не вижу никакой хорошей предварительно упакованной "последовательности от a до b" вне выражений понимания / последовательности, хотя, очевидно, есть [a..b] (список) и [| a .. b |] (массив), которые вы можете спроецировать через Seq.unfold , Seq.map и т.д.чтобы сделать Seq.
Другие советы
Я не могу вспомнить многих случаев, когда я бы предпочел Seq.unfold
, а не эквивалентный список:
> 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]]
Иногда методы Array.init также полезны:
> 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]]
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]]
Вот еще один способ использования последовательностей:
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